enhance(downloader): log git commands that failed (#3372)

This commit is contained in:
jack1142 2020-01-16 02:54:23 +01:00 committed by Michael H
parent 29feab638a
commit a1b95e5072
2 changed files with 81 additions and 89 deletions

View File

@ -38,6 +38,10 @@ class GitException(DownloaderException):
Generic class for git exceptions. Generic class for git exceptions.
""" """
def __init__(self, message: str, git_command: str) -> None:
self.git_command = git_command
super().__init__(f"Git command failed: {git_command}\nError message: {message}")
class InvalidRepoName(DownloaderException): class InvalidRepoName(DownloaderException):
""" """
@ -138,8 +142,8 @@ class AmbiguousRevision(GitException):
Thrown when specified revision is ambiguous. Thrown when specified revision is ambiguous.
""" """
def __init__(self, message: str, candidates: List[Candidate]) -> None: def __init__(self, message: str, git_command: str, candidates: List[Candidate]) -> None:
super().__init__(message) super().__init__(message, git_command)
self.candidates = candidates self.candidates = candidates

View File

@ -203,21 +203,20 @@ class Repo(RepoJSONMixin):
""" """
valid_exit_codes = (0, 1) valid_exit_codes = (0, 1)
p = await self._run( git_command = ProcessFormatter().format(
ProcessFormatter().format( self.GIT_IS_ANCESTOR,
self.GIT_IS_ANCESTOR, path=self.folder_path,
path=self.folder_path, maybe_ancestor_rev=maybe_ancestor_rev,
maybe_ancestor_rev=maybe_ancestor_rev, descendant_rev=descendant_rev,
descendant_rev=descendant_rev,
),
valid_exit_codes=valid_exit_codes,
) )
p = await self._run(git_command, valid_exit_codes=valid_exit_codes)
if p.returncode in valid_exit_codes: if p.returncode in valid_exit_codes:
return not bool(p.returncode) return not bool(p.returncode)
raise errors.GitException( raise errors.GitException(
f"Git failed to determine if commit {maybe_ancestor_rev}" f"Git failed to determine if commit {maybe_ancestor_rev}"
f" is ancestor of {descendant_rev} for repo at path: {self.folder_path}" f" is ancestor of {descendant_rev} for repo at path: {self.folder_path}",
git_command,
) )
async def is_on_branch(self) -> bool: async def is_on_branch(self) -> bool:
@ -253,15 +252,14 @@ class Repo(RepoJSONMixin):
""" """
if new_rev is None: if new_rev is None:
new_rev = self.branch new_rev = self.branch
p = await self._run( git_command = ProcessFormatter().format(
ProcessFormatter().format( self.GIT_DIFF_FILE_STATUS, path=self.folder_path, old_rev=old_rev, new_rev=new_rev
self.GIT_DIFF_FILE_STATUS, path=self.folder_path, old_rev=old_rev, new_rev=new_rev
)
) )
p = await self._run(git_command)
if p.returncode != 0: if p.returncode != 0:
raise errors.GitDiffError( raise errors.GitDiffError(
"Git diff failed for repo at path: {}".format(self.folder_path) f"Git diff failed for repo at path: {self.folder_path}", git_command
) )
stdout = p.stdout.strip(b"\t\n\x00 ").decode().split("\x00\t") stdout = p.stdout.strip(b"\t\n\x00 ").decode().split("\x00\t")
@ -310,18 +308,17 @@ class Repo(RepoJSONMixin):
async with self.checkout(descendant_rev): async with self.checkout(descendant_rev):
return discord.utils.get(self.available_modules, name=module_name) return discord.utils.get(self.available_modules, name=module_name)
p = await self._run( git_command = ProcessFormatter().format(
ProcessFormatter().format( self.GIT_GET_LAST_MODULE_OCCURRENCE_COMMIT,
self.GIT_GET_LAST_MODULE_OCCURRENCE_COMMIT, path=self.folder_path,
path=self.folder_path, descendant_rev=descendant_rev,
descendant_rev=descendant_rev, module_name=module_name,
module_name=module_name,
)
) )
p = await self._run(git_command)
if p.returncode != 0: if p.returncode != 0:
raise errors.GitException( raise errors.GitException(
"Git log failed for repo at path: {}".format(self.folder_path) f"Git log failed for repo at path: {self.folder_path}", git_command
) )
commit = p.stdout.decode().strip() commit = p.stdout.decode().strip()
@ -418,19 +415,18 @@ class Repo(RepoJSONMixin):
to get messages for. to get messages for.
:return: Git commit note log :return: Git commit note log
""" """
p = await self._run( git_command = ProcessFormatter().format(
ProcessFormatter().format( self.GIT_LOG,
self.GIT_LOG, path=self.folder_path,
path=self.folder_path, old_rev=old_rev,
old_rev=old_rev, relative_file_path=relative_file_path,
relative_file_path=relative_file_path,
)
) )
p = await self._run(git_command)
if p.returncode != 0: if p.returncode != 0:
raise errors.GitException( raise errors.GitException(
"An exception occurred while executing git log on" f"An exception occurred while executing git log on this repo: {self.folder_path}",
" this repo: {}".format(self.folder_path) git_command,
) )
return p.stdout.decode().strip() return p.stdout.decode().strip()
@ -457,21 +453,24 @@ class Repo(RepoJSONMixin):
Full sha1 object name for provided revision. Full sha1 object name for provided revision.
""" """
p = await self._run( git_command = ProcessFormatter().format(
ProcessFormatter().format(self.GIT_GET_FULL_SHA1, path=self.folder_path, rev=rev) self.GIT_GET_FULL_SHA1, path=self.folder_path, rev=rev
) )
p = await self._run(git_command)
if p.returncode != 0: if p.returncode != 0:
stderr = p.stderr.decode().strip() stderr = p.stderr.decode().strip()
ambiguous_error = f"error: short SHA1 {rev} is ambiguous\nhint: The candidates are:\n" ambiguous_error = f"error: short SHA1 {rev} is ambiguous\nhint: The candidates are:\n"
if not stderr.startswith(ambiguous_error): if not stderr.startswith(ambiguous_error):
raise errors.UnknownRevision(f"Revision {rev} cannot be found.") raise errors.UnknownRevision(f"Revision {rev} cannot be found.", git_command)
candidates = [] candidates = []
for match in self.AMBIGUOUS_ERROR_REGEX.finditer(stderr, len(ambiguous_error)): for match in self.AMBIGUOUS_ERROR_REGEX.finditer(stderr, len(ambiguous_error)):
candidates.append(Candidate(match["rev"], match["type"], match["desc"])) candidates.append(Candidate(match["rev"], match["type"], match["desc"]))
if candidates: if candidates:
raise errors.AmbiguousRevision(f"Short SHA1 {rev} is ambiguous.", candidates) raise errors.AmbiguousRevision(
raise errors.UnknownRevision(f"Revision {rev} cannot be found.") f"Short SHA1 {rev} is ambiguous.", git_command, candidates
)
raise errors.UnknownRevision(f"Revision {rev} cannot be found.", git_command)
return p.stdout.decode().strip() return p.stdout.decode().strip()
@ -554,17 +553,14 @@ class Repo(RepoJSONMixin):
return return
exists, __ = self._existing_git_repo() exists, __ = self._existing_git_repo()
if not exists: if not exists:
raise errors.MissingGitRepo( raise errors.MissingGitRepo(f"A git repo does not exist at path: {self.folder_path}")
"A git repo does not exist at path: {}".format(self.folder_path)
)
p = await self._run( git_command = ProcessFormatter().format(self.GIT_CHECKOUT, path=self.folder_path, rev=rev)
ProcessFormatter().format(self.GIT_CHECKOUT, path=self.folder_path, rev=rev) p = await self._run(git_command)
)
if p.returncode != 0: if p.returncode != 0:
raise errors.UnknownRevision( raise errors.UnknownRevision(
"Could not checkout to {}. This revision may not exist".format(rev) f"Could not checkout to {rev}. This revision may not exist", git_command
) )
await self._setup_repo() await self._setup_repo()
@ -619,25 +615,22 @@ class Repo(RepoJSONMixin):
""" """
exists, path = self._existing_git_repo() exists, path = self._existing_git_repo()
if exists: if exists:
raise errors.ExistingGitRepo("A git repo already exists at path: {}".format(path)) raise errors.ExistingGitRepo(f"A git repo already exists at path: {path}")
if self.branch is not None: if self.branch is not None:
p = await self._run( git_command = ProcessFormatter().format(
ProcessFormatter().format( self.GIT_CLONE, branch=self.branch, url=self.url, folder=self.folder_path
self.GIT_CLONE, branch=self.branch, url=self.url, folder=self.folder_path
)
) )
else: else:
p = await self._run( git_command = ProcessFormatter().format(
ProcessFormatter().format( self.GIT_CLONE_NO_BRANCH, url=self.url, folder=self.folder_path
self.GIT_CLONE_NO_BRANCH, url=self.url, folder=self.folder_path
)
) )
p = await self._run(git_command)
if p.returncode: if p.returncode:
# Try cleaning up folder # Try cleaning up folder
shutil.rmtree(str(self.folder_path), ignore_errors=True) shutil.rmtree(str(self.folder_path), ignore_errors=True)
raise errors.CloningError("Error when running git clone.") raise errors.CloningError("Error when running git clone.", git_command)
if self.branch is None: if self.branch is None:
self.branch = await self.current_branch() self.branch = await self.current_branch()
@ -657,17 +650,14 @@ class Repo(RepoJSONMixin):
""" """
exists, __ = self._existing_git_repo() exists, __ = self._existing_git_repo()
if not exists: if not exists:
raise errors.MissingGitRepo( raise errors.MissingGitRepo(f"A git repo does not exist at path: {self.folder_path}")
"A git repo does not exist at path: {}".format(self.folder_path)
)
p = await self._run( git_command = ProcessFormatter().format(self.GIT_CURRENT_BRANCH, path=self.folder_path)
ProcessFormatter().format(self.GIT_CURRENT_BRANCH, path=self.folder_path) p = await self._run(git_command)
)
if p.returncode != 0: if p.returncode != 0:
raise errors.GitException( raise errors.GitException(
"Could not determine current branch at path: {}".format(self.folder_path) f"Could not determine current branch at path: {self.folder_path}", git_command
) )
return p.stdout.decode().strip() return p.stdout.decode().strip()
@ -683,16 +673,13 @@ class Repo(RepoJSONMixin):
""" """
exists, __ = self._existing_git_repo() exists, __ = self._existing_git_repo()
if not exists: if not exists:
raise errors.MissingGitRepo( raise errors.MissingGitRepo(f"A git repo does not exist at path: {self.folder_path}")
"A git repo does not exist at path: {}".format(self.folder_path)
)
p = await self._run( git_command = ProcessFormatter().format(self.GIT_CURRENT_COMMIT, path=self.folder_path)
ProcessFormatter().format(self.GIT_CURRENT_COMMIT, path=self.folder_path) p = await self._run(git_command)
)
if p.returncode != 0: if p.returncode != 0:
raise errors.CurrentHashError("Unable to determine commit hash.") raise errors.CurrentHashError("Unable to determine commit hash.", git_command)
return p.stdout.decode().strip() return p.stdout.decode().strip()
@ -715,16 +702,15 @@ class Repo(RepoJSONMixin):
exists, __ = self._existing_git_repo() exists, __ = self._existing_git_repo()
if not exists: if not exists:
raise errors.MissingGitRepo( raise errors.MissingGitRepo(f"A git repo does not exist at path: {self.folder_path}")
"A git repo does not exist at path: {}".format(self.folder_path)
)
p = await self._run( git_command = ProcessFormatter().format(
ProcessFormatter().format(self.GIT_LATEST_COMMIT, path=self.folder_path, branch=branch) self.GIT_LATEST_COMMIT, path=self.folder_path, branch=branch
) )
p = await self._run(git_command)
if p.returncode != 0: if p.returncode != 0:
raise errors.CurrentHashError("Unable to determine latest commit hash.") raise errors.CurrentHashError("Unable to determine latest commit hash.", git_command)
return p.stdout.decode().strip() return p.stdout.decode().strip()
@ -751,10 +737,11 @@ class Repo(RepoJSONMixin):
if folder is None: if folder is None:
folder = self.folder_path folder = self.folder_path
p = await self._run(ProcessFormatter().format(Repo.GIT_DISCOVER_REMOTE_URL, path=folder)) git_command = ProcessFormatter().format(Repo.GIT_DISCOVER_REMOTE_URL, path=folder)
p = await self._run(git_command)
if p.returncode != 0: if p.returncode != 0:
raise errors.NoRemoteURL("Unable to discover a repo URL.") raise errors.NoRemoteURL("Unable to discover a repo URL.", git_command)
return p.stdout.decode().strip() return p.stdout.decode().strip()
@ -773,19 +760,18 @@ class Repo(RepoJSONMixin):
await self.checkout(branch) await self.checkout(branch)
exists, __ = self._existing_git_repo() exists, __ = self._existing_git_repo()
if not exists: if not exists:
raise errors.MissingGitRepo( raise errors.MissingGitRepo(f"A git repo does not exist at path: {self.folder_path}")
"A git repo does not exist at path: {}".format(self.folder_path)
)
p = await self._run( git_command = ProcessFormatter().format(
ProcessFormatter().format(self.GIT_HARD_RESET, path=self.folder_path, branch=branch) self.GIT_HARD_RESET, path=self.folder_path, branch=branch
) )
p = await self._run(git_command)
if p.returncode != 0: if p.returncode != 0:
raise errors.HardResetError( raise errors.HardResetError(
"Some error occurred when trying to" "Some error occurred when trying to execute a hard reset on the repo at"
" execute a hard reset on the repo at" f" the following path: {self.folder_path}",
" the following path: {}".format(self.folder_path) git_command,
) )
async def update(self) -> Tuple[str, str]: async def update(self) -> Tuple[str, str]:
@ -795,7 +781,7 @@ class Repo(RepoJSONMixin):
------- -------
`tuple` of `str` `tuple` of `str`
:py:code`(old commit hash, new commit hash)` :py:code`(old commit hash, new commit hash)`
Raises Raises
------- -------
`UpdateError` - if git pull results with non-zero exit code `UpdateError` - if git pull results with non-zero exit code
@ -804,12 +790,14 @@ class Repo(RepoJSONMixin):
await self.hard_reset() await self.hard_reset()
p = await self._run(ProcessFormatter().format(self.GIT_PULL, path=self.folder_path)) git_command = ProcessFormatter().format(self.GIT_PULL, path=self.folder_path)
p = await self._run(git_command)
if p.returncode != 0: if p.returncode != 0:
raise errors.UpdateError( raise errors.UpdateError(
"Git pull returned a non zero exit code" "Git pull returned a non zero exit code"
" for the repo located at path: {}".format(self.folder_path) f" for the repo located at path: {self.folder_path}",
git_command,
) )
await self._setup_repo() await self._setup_repo()
@ -1114,7 +1102,7 @@ class RepoManager:
""" """
repo = self.get_repo(name) repo = self.get_repo(name)
if repo is None: if repo is None:
raise errors.MissingGitRepo("There is no repo with the name {}".format(name)) raise errors.MissingGitRepo(f"There is no repo with the name {name}")
safe_delete(repo.folder_path) safe_delete(repo.folder_path)