diff options
| author | Jason Chang <jasonnc@google.com> | 2023-07-26 13:23:40 -0700 |
|---|---|---|
| committer | LUCI <gerrit-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2023-07-31 21:31:36 +0000 |
| commit | a6413f5d88f12466b3daa833668d0f59fc65ece4 (patch) | |
| tree | 25410555a8941c500fbd55a974476ace04198dca /git_command.py | |
| parent | 8c35d948cfa76ec685ad36fb1cb3a0fcc749f428 (diff) | |
| download | git-repo-a6413f5d88f12466b3daa833668d0f59fc65ece4.tar.gz | |
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>
Diffstat (limited to 'git_command.py')
| -rw-r--r-- | git_command.py | 74 |
1 files changed, 72 insertions, 2 deletions
diff --git a/git_command.py b/git_command.py index c7245ade..588a64fd 100644 --- a/git_command.py +++ b/git_command.py | |||
| @@ -40,6 +40,10 @@ GIT_DIR = "GIT_DIR" | |||
| 40 | 40 | ||
| 41 | LAST_GITDIR = None | 41 | LAST_GITDIR = None |
| 42 | LAST_CWD = None | 42 | LAST_CWD = None |
| 43 | DEFAULT_GIT_FAIL_MESSAGE = "git command failure" | ||
| 44 | # Common line length limit | ||
| 45 | GIT_ERROR_STDOUT_LINES = 1 | ||
| 46 | GIT_ERROR_STDERR_LINES = 1 | ||
| 43 | 47 | ||
| 44 | 48 | ||
| 45 | class _GitCall(object): | 49 | class _GitCall(object): |
| @@ -237,6 +241,7 @@ class GitCommand(object): | |||
| 237 | cwd=None, | 241 | cwd=None, |
| 238 | gitdir=None, | 242 | gitdir=None, |
| 239 | objdir=None, | 243 | objdir=None, |
| 244 | verify_command=False, | ||
| 240 | ): | 245 | ): |
| 241 | if project: | 246 | if project: |
| 242 | if not cwd: | 247 | if not cwd: |
| @@ -244,6 +249,10 @@ class GitCommand(object): | |||
| 244 | if not gitdir: | 249 | if not gitdir: |
| 245 | gitdir = project.gitdir | 250 | gitdir = project.gitdir |
| 246 | 251 | ||
| 252 | self.project = project | ||
| 253 | self.cmdv = cmdv | ||
| 254 | self.verify_command = verify_command | ||
| 255 | |||
| 247 | # Git on Windows wants its paths only using / for reliability. | 256 | # Git on Windows wants its paths only using / for reliability. |
| 248 | if platform_utils.isWindows(): | 257 | if platform_utils.isWindows(): |
| 249 | if objdir: | 258 | if objdir: |
| @@ -332,7 +341,11 @@ class GitCommand(object): | |||
| 332 | stderr=stderr, | 341 | stderr=stderr, |
| 333 | ) | 342 | ) |
| 334 | except Exception as e: | 343 | except Exception as e: |
| 335 | raise GitError("%s: %s" % (command[1], e)) | 344 | raise GitCommandError( |
| 345 | message="%s: %s" % (command[1], e), | ||
| 346 | project=project.name if project else None, | ||
| 347 | command_args=cmdv, | ||
| 348 | ) | ||
| 336 | 349 | ||
| 337 | if ssh_proxy: | 350 | if ssh_proxy: |
| 338 | ssh_proxy.add_client(p) | 351 | ssh_proxy.add_client(p) |
| @@ -366,4 +379,61 @@ class GitCommand(object): | |||
| 366 | return env | 379 | return env |
| 367 | 380 | ||
| 368 | def Wait(self): | 381 | def Wait(self): |
| 369 | return self.rc | 382 | if not self.verify_command or self.rc == 0: |
| 383 | return self.rc | ||
| 384 | |||
| 385 | stdout = ( | ||
| 386 | "\n".join(self.stdout.split("\n")[:GIT_ERROR_STDOUT_LINES]) | ||
| 387 | if self.stdout | ||
| 388 | else None | ||
| 389 | ) | ||
| 390 | |||
| 391 | stderr = ( | ||
| 392 | "\n".join(self.stderr.split("\n")[:GIT_ERROR_STDERR_LINES]) | ||
| 393 | if self.stderr | ||
| 394 | else None | ||
| 395 | ) | ||
| 396 | project = self.project.name if self.project else None | ||
| 397 | raise GitCommandError( | ||
| 398 | project=project, | ||
| 399 | command_args=self.cmdv, | ||
| 400 | git_rc=self.rc, | ||
| 401 | git_stdout=stdout, | ||
| 402 | git_stderr=stderr, | ||
| 403 | ) | ||
| 404 | |||
| 405 | |||
| 406 | class GitCommandError(GitError): | ||
| 407 | """ | ||
| 408 | Error raised from a failed git command. | ||
| 409 | Note that GitError can refer to any Git related error (e.g. branch not | ||
| 410 | specified for project.py 'UploadForReview'), while GitCommandError is | ||
| 411 | raised exclusively from non-zero exit codes returned from git commands. | ||
| 412 | """ | ||
| 413 | |||
| 414 | def __init__( | ||
| 415 | self, | ||
| 416 | message: str = DEFAULT_GIT_FAIL_MESSAGE, | ||
| 417 | git_rc: int = None, | ||
| 418 | git_stdout: str = None, | ||
| 419 | git_stderr: str = None, | ||
| 420 | **kwargs, | ||
| 421 | ): | ||
| 422 | super().__init__( | ||
| 423 | message, | ||
| 424 | **kwargs, | ||
| 425 | ) | ||
| 426 | self.git_rc = git_rc | ||
| 427 | self.git_stdout = git_stdout | ||
| 428 | self.git_stderr = git_stderr | ||
| 429 | |||
| 430 | def __str__(self): | ||
| 431 | args = "[]" if not self.command_args else " ".join(self.command_args) | ||
| 432 | error_type = type(self).__name__ | ||
| 433 | return f"""{error_type}: {self.message} | ||
| 434 | Project: {self.project} | ||
| 435 | Args: {args} | ||
| 436 | Stdout: | ||
| 437 | {self.git_stdout} | ||
| 438 | Stderr: | ||
| 439 | {self.git_stderr}""" | ||
