From a64149a7a77814132629bbb4c07d922c2222df25 Mon Sep 17 00:00:00 2001 From: Gavin Mak Date: Wed, 13 Aug 2025 22:48:36 -0700 Subject: sync: Record and propagate errors from deferred actions Failures in deferred sync actions were not recorded because `_Later.Run` discarded the `GitError` exception. Record the specific error using `syncbuf.fail()` and propagate it for proper error aggregation and reporting. Bug: 438178765 Change-Id: Iad59e389f9677bd6b8d873ee1ea2aa6ce44c86fa Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/498141 Tested-by: Gavin Mak Reviewed-by: Scott Lee --- project.py | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) (limited to 'project.py') diff --git a/project.py b/project.py index 9bfd4827..73263d93 100644 --- a/project.py +++ b/project.py @@ -1539,18 +1539,14 @@ class Project: force_checkout=False, force_rebase=False, submodules=False, - errors=None, verbose=False, ): """Perform only the local IO portion of the sync process. Network access is not required. """ - if errors is None: - errors = [] def fail(error: Exception): - errors.append(error) syncbuf.fail(self, error) if not os.path.exists(self.gitdir): @@ -4031,7 +4027,8 @@ class _Later: if not self.quiet: out.nl() return True - except GitError: + except GitError as e: + syncbuf.fail(self.project, e) out.nl() return False @@ -4047,7 +4044,12 @@ class _SyncColoring(Coloring): class SyncBuffer: def __init__(self, config, detach_head=False): self._messages = [] - self._failures = [] + + # Failures that have not yet been printed. Cleared after printing. + self._pending_failures = [] + # A persistent record of all failures during the buffer's lifetime. + self._all_failures = [] + self._later_queue1 = [] self._later_queue2 = [] @@ -4062,7 +4064,9 @@ class SyncBuffer: self._messages.append(_InfoMessage(project, fmt % args)) def fail(self, project, err=None): - self._failures.append(_Failure(project, err)) + failure = _Failure(project, err) + self._pending_failures.append(failure) + self._all_failures.append(failure) self._MarkUnclean() def later1(self, project, what, quiet): @@ -4082,6 +4086,11 @@ class SyncBuffer: self.recent_clean = True return recent_clean + @property + def errors(self): + """Returns a list of all exceptions accumulated in the buffer.""" + return [f.why for f in self._all_failures if f.why] + def _MarkUnclean(self): self.clean = False self.recent_clean = False @@ -4100,18 +4109,18 @@ class SyncBuffer: return True def _PrintMessages(self): - if self._messages or self._failures: + if self._messages or self._pending_failures: if os.isatty(2): self.out.write(progress.CSI_ERASE_LINE) self.out.write("\r") for m in self._messages: m.Print(self) - for m in self._failures: + for m in self._pending_failures: m.Print(self) self._messages = [] - self._failures = [] + self._pending_failures = [] class MetaProject(Project): -- cgit v1.2.3-54-g00ecf