From 1a87da68c870ce09ab6ffac30589da12e7ff6a8d Mon Sep 17 00:00:00 2001 From: Leo Neat Date: Fri, 31 Jan 2020 15:31:18 -0800 Subject: [cifuzz] - commit and pull request hook functionality (#3310) --- infra/repo_manager.py | 94 ++++++++++++++++++++++++++++----------------------- 1 file changed, 51 insertions(+), 43 deletions(-) (limited to 'infra/repo_manager.py') diff --git a/infra/repo_manager.py b/infra/repo_manager.py index bb3fe237..cf98ab94 100644 --- a/infra/repo_manager.py +++ b/infra/repo_manager.py @@ -27,27 +27,23 @@ import shutil import utils -class RepoManagerError(Exception): - """Class to describe the exceptions in RepoManager.""" - - class RepoManager: """Class to manage git repos from python. Attributes: - repo_url: The location of the git repo - base_dir: The location of where the repo clone is stored locally - repo_name: The name of the github project - repo_dir: The location of the main repo + repo_url: The location of the git repo. + base_dir: The location of where the repo clone is stored locally. + repo_name: The name of the GitHub project. + repo_dir: The location of the main repo. """ def __init__(self, repo_url, base_dir, repo_name=None): """Constructs a repo manager class. Args: - repo_url: The github url needed to clone - base_dir: The full filepath where the git repo is located - repo_name: The name of the directory the repo is cloned to + repo_url: The github url needed to clone. + base_dir: The full file-path where the git repo is located. + repo_name: The name of the directory the repo is cloned to. """ self.repo_url = repo_url self.base_dir = base_dir @@ -62,7 +58,7 @@ class RepoManager: """Creates a clone of the repo in the specified directory. Raises: - RepoManagerError if the repo was not able to be cloned + ValueError: when the repo is not able to be cloned. """ if not os.path.exists(self.base_dir): os.makedirs(self.base_dir) @@ -70,13 +66,13 @@ class RepoManager: out, err = utils.execute(['git', 'clone', self.repo_url, self.repo_name], location=self.base_dir) if not self._is_git_repo(): - raise RepoManagerError('%s is not a git repo' % self.repo_url) + raise ValueError('%s is not a git repo' % self.repo_url) def _is_git_repo(self): """Test if the current repo dir is a git repo or not. Returns: - True if the current repo_dir is a valid git repo + True if the current repo_dir is a valid git repo. """ git_path = os.path.join(self.repo_dir, '.git') return os.path.isdir(git_path) @@ -85,19 +81,13 @@ class RepoManager: """Checks to see if a commit exists in the project repo. Args: - commit: The commit SHA you are checking + commit: The commit SHA you are checking. Returns: - True if the commit exits in the project - - Raises: - ValueException: an empty string was passed in as a commit + True if the commit exits in the project. """ - - # Handle the exception case, if empty string is passed execute will - # raise a ValueError if not commit.rstrip(): - raise RepoManagerError('An empty string is not a valid commit SHA') + return False _, err_code = utils.execute(['git', 'cat-file', '-e', commit], self.repo_dir) @@ -107,7 +97,7 @@ class RepoManager: """Gets the current commit SHA of the repo. Returns: - The current active commit SHA + The current active commit SHA. """ out, _ = utils.execute(['git', 'rev-parse', 'HEAD'], self.repo_dir, @@ -118,20 +108,21 @@ class RepoManager: """Gets the list of commits(inclusive) between the old and new commits. Args: - old_commit: The oldest commit to be in the list - new_commit: The newest commit to be in the list + old_commit: The oldest commit to be in the list. + new_commit: The newest commit to be in the list. Returns: - The list of commit SHAs from newest to oldest + The list of commit SHAs from newest to oldest. Raises: - RepoManagerError when commits dont exist + ValueError: When either the old or new commit does not exist. + RuntimeError: When there is an error getting the commit list. """ if not self.commit_exists(old_commit): - raise RepoManagerError('The old commit %s does not exist' % old_commit) + raise ValueError('The old commit %s does not exist' % old_commit) if not self.commit_exists(new_commit): - raise RepoManagerError('The new commit %s does not exist' % new_commit) + raise ValueError('The new commit %s does not exist' % new_commit) if old_commit == new_commit: return [old_commit] out, err_code = utils.execute( @@ -139,37 +130,54 @@ class RepoManager: commits = out.split('\n') commits = [commit for commit in commits if commit] if err_code or not commits: - raise RepoManagerError('Error getting commit list between %s and %s ' % - (old_commit, new_commit)) + raise RuntimeError('Error getting commit list between %s and %s ' % + (old_commit, new_commit)) # Make sure result is inclusive commits.append(old_commit) return commits + def fetch_unshallow(self): + """Gets the current git repository history.""" + git_path = os.path.join(self.repo_dir, '.git', 'shallow') + if os.path.exists(git_path): + utils.execute(['git', 'fetch', '--unshallow'], + self.repo_dir, + check_result=True) + + def checkout_pr(self, pr_ref): + """Checks out a remote pull request. + + Args: + pr_ref: The pull request reference to be checked out. + """ + self.fetch_unshallow() + utils.execute(['git', 'fetch', 'origin', pr_ref], + self.repo_dir, + check_result=True) + utils.execute(['git', 'checkout', '-f', 'FETCH_HEAD'], + self.repo_dir, + check_result=True) + def checkout_commit(self, commit): """Checks out a specific commit from the repo. Args: - commit: The commit SHA to be checked out + commit: The commit SHA to be checked out. Raises: - RepoManagerError when checkout is not successful + RuntimeError: when checkout is not successful. + ValueError: when commit does not exist. """ + self.fetch_unshallow() if not self.commit_exists(commit): - raise RepoManagerError('Commit %s does not exist in current branch' % - commit) - - git_path = os.path.join(self.repo_dir, '.git', 'shallow') - if os.path.exists(git_path): - utils.execute(['git', 'fetch', '--unshallow'], - self.repo_dir, - check_result=True) + raise ValueError('Commit %s does not exist in current branch' % commit) utils.execute(['git', 'checkout', '-f', commit], self.repo_dir, check_result=True) utils.execute(['git', 'clean', '-fxd'], self.repo_dir, check_result=True) if self.get_current_commit() != commit: - raise RepoManagerError('Error checking out commit %s' % commit) + raise RuntimeError('Error checking out commit %s' % commit) def remove_repo(self): """Attempts to remove the git repo. """ -- cgit v1.2.3