Update errors to extend BaseRepoError
In order to better analyze and track repo errors, repo command failures
need to be tied to specific errors in repo source code.
Additionally a new GitCommandError was added to differentiate between
general git related errors to failed git commands. Git commands that opt
into verification will raise a GitCommandError if the command failed.
The first step in this process is a general error refactoring
Bug: b/293344017
Change-Id: I46944b1825ce892757c8dd3f7e2fab7e460760c0
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/380994
Commit-Queue: Jason Chang <jasonnc@google.com>
Reviewed-by: Aravind Vasudevan <aravindvasudev@google.com>
Tested-by: Jason Chang <jasonnc@google.com>
Reviewed-by: Joanna Wang <jojwang@google.com>
diff --git a/git_command.py b/git_command.py
index c7245ad..588a64f 100644
--- a/git_command.py
+++ b/git_command.py
@@ -40,6 +40,10 @@
LAST_GITDIR = None
LAST_CWD = None
+DEFAULT_GIT_FAIL_MESSAGE = "git command failure"
+# Common line length limit
+GIT_ERROR_STDOUT_LINES = 1
+GIT_ERROR_STDERR_LINES = 1
class _GitCall(object):
@@ -237,6 +241,7 @@
cwd=None,
gitdir=None,
objdir=None,
+ verify_command=False,
):
if project:
if not cwd:
@@ -244,6 +249,10 @@
if not gitdir:
gitdir = project.gitdir
+ self.project = project
+ self.cmdv = cmdv
+ self.verify_command = verify_command
+
# Git on Windows wants its paths only using / for reliability.
if platform_utils.isWindows():
if objdir:
@@ -332,7 +341,11 @@
stderr=stderr,
)
except Exception as e:
- raise GitError("%s: %s" % (command[1], e))
+ raise GitCommandError(
+ message="%s: %s" % (command[1], e),
+ project=project.name if project else None,
+ command_args=cmdv,
+ )
if ssh_proxy:
ssh_proxy.add_client(p)
@@ -366,4 +379,61 @@
return env
def Wait(self):
- return self.rc
+ if not self.verify_command or self.rc == 0:
+ return self.rc
+
+ stdout = (
+ "\n".join(self.stdout.split("\n")[:GIT_ERROR_STDOUT_LINES])
+ if self.stdout
+ else None
+ )
+
+ stderr = (
+ "\n".join(self.stderr.split("\n")[:GIT_ERROR_STDERR_LINES])
+ if self.stderr
+ else None
+ )
+ project = self.project.name if self.project else None
+ raise GitCommandError(
+ project=project,
+ command_args=self.cmdv,
+ git_rc=self.rc,
+ git_stdout=stdout,
+ git_stderr=stderr,
+ )
+
+
+class GitCommandError(GitError):
+ """
+ Error raised from a failed git command.
+ Note that GitError can refer to any Git related error (e.g. branch not
+ specified for project.py 'UploadForReview'), while GitCommandError is
+ raised exclusively from non-zero exit codes returned from git commands.
+ """
+
+ def __init__(
+ self,
+ message: str = DEFAULT_GIT_FAIL_MESSAGE,
+ git_rc: int = None,
+ git_stdout: str = None,
+ git_stderr: str = None,
+ **kwargs,
+ ):
+ super().__init__(
+ message,
+ **kwargs,
+ )
+ self.git_rc = git_rc
+ self.git_stdout = git_stdout
+ self.git_stderr = git_stderr
+
+ def __str__(self):
+ args = "[]" if not self.command_args else " ".join(self.command_args)
+ error_type = type(self).__name__
+ return f"""{error_type}: {self.message}
+ Project: {self.project}
+ Args: {args}
+ Stdout:
+{self.git_stdout}
+ Stderr:
+{self.git_stderr}"""