def remove_repos_by_id(repo_ids): """ Try to remove each of the given 'repo_ids': Find the url and determine the path. If resource exists on the filesystem level -> remove its files and DB record. """ for git_repo in repo_ids: git_repo_id = ''.join(('git_repo_id:', str(git_repo))) repo_url = redis.hmget(git_repo_id, 'url')[0] if repo_url: repo_name = repo_url.split('/')[-1] # assuming url is valid! git_repo_path = path.join(GIT_REPOS_PATH, repo_name) if check_repo_was_cloned(git_repo_path, git_repo_id): rmtree(git_repo_path) # folder on FS redis.delete(git_repo_id) # DB record redis.delete(repo_url) # DB record else: raise BadRequest('Bad Request', 400, {'error': 'The repository with id %s is ' 'not yet cloned.' % git_repo}) else: raise BadRequest('Bad Request', 400, {'error': 'Could not find an url for repository ' 'with a given id %s. Repository may not exist.' % git_repo})
def check_repo_was_cloned(repo_path, repo_id): """ Returns True if in the given 'repo_path' a .git folder can be found, it contains a non-empty index file, and respective DB record has a 'last_checkout' timestamp. """ path_to_git_index = path.join(repo_path, '.git/index') if path.exists(path_to_git_index): if stat(path_to_git_index).st_size > 0: if redis.hmget(repo_id, 'last_checkout')[0]: return True
def run_git_clone_or_checkout(git_repo_id): """ Clones or checks out the repository to 'GIT_REPOS_PATH/'. Operations performed with lock to avoid race conditions if two users are POSTing the same url at the same time. """ # Get the respective repo url, branch, revision: repo_url = redis.hmget(git_repo_id, 'url')[0] repo_branch = redis.hmget(git_repo_id, 'branch')[0] or 'master' repo_revision = redis.hmget(git_repo_id, 'revision')[0] repo_name = repo_url.split('/')[-1] # assuming url is valid! git_repo_path = path.join(GIT_REPOS_PATH, repo_name) # where to clone clone_params = {'branch': repo_branch} # branch to clone with open("".join((repo_name, '.lock')), 'w') as lock_file: fcntl.flock(lock_file, fcntl.LOCK_EX) # lock try: if check_repo_was_cloned(git_repo_path, git_repo_id): redis.hdel(git_repo_id, 'last_checkout') # del last_checkout value GitRepo = Repo(git_repo_path) GitRepo.git.checkout(repo_branch) else: # otherwise clone the repo: GitRepo = Repo.clone_from(repo_url, git_repo_path, **clone_params) if repo_revision: # goto exact commit/revision, if was specified GitRepo.git.checkout(repo_revision) update_repo_stats(git_repo_id, git_repo_path, GitRepo) except (git_exc.CheckoutError, git_exc.InvalidGitRepositoryError, git_exc.NoSuchPathError, git_exc.GitCommandError) as exc: app.logger.error("Error while git was working: %s" % exc) fcntl.flock(lock_file, fcntl.LOCK_UN) # unlock