summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--project.py29
-rw-r--r--subcmds/sync.py10
-rw-r--r--tests/test_subcmds_sync.py2
3 files changed, 25 insertions, 16 deletions
diff --git a/project.py b/project.py
index 9bfd4827..73263d93 100644
--- a/project.py
+++ b/project.py
@@ -1539,18 +1539,14 @@ class Project:
1539 force_checkout=False, 1539 force_checkout=False,
1540 force_rebase=False, 1540 force_rebase=False,
1541 submodules=False, 1541 submodules=False,
1542 errors=None,
1543 verbose=False, 1542 verbose=False,
1544 ): 1543 ):
1545 """Perform only the local IO portion of the sync process. 1544 """Perform only the local IO portion of the sync process.
1546 1545
1547 Network access is not required. 1546 Network access is not required.
1548 """ 1547 """
1549 if errors is None:
1550 errors = []
1551 1548
1552 def fail(error: Exception): 1549 def fail(error: Exception):
1553 errors.append(error)
1554 syncbuf.fail(self, error) 1550 syncbuf.fail(self, error)
1555 1551
1556 if not os.path.exists(self.gitdir): 1552 if not os.path.exists(self.gitdir):
@@ -4031,7 +4027,8 @@ class _Later:
4031 if not self.quiet: 4027 if not self.quiet:
4032 out.nl() 4028 out.nl()
4033 return True 4029 return True
4034 except GitError: 4030 except GitError as e:
4031 syncbuf.fail(self.project, e)
4035 out.nl() 4032 out.nl()
4036 return False 4033 return False
4037 4034
@@ -4047,7 +4044,12 @@ class _SyncColoring(Coloring):
4047class SyncBuffer: 4044class SyncBuffer:
4048 def __init__(self, config, detach_head=False): 4045 def __init__(self, config, detach_head=False):
4049 self._messages = [] 4046 self._messages = []
4050 self._failures = [] 4047
4048 # Failures that have not yet been printed. Cleared after printing.
4049 self._pending_failures = []
4050 # A persistent record of all failures during the buffer's lifetime.
4051 self._all_failures = []
4052
4051 self._later_queue1 = [] 4053 self._later_queue1 = []
4052 self._later_queue2 = [] 4054 self._later_queue2 = []
4053 4055
@@ -4062,7 +4064,9 @@ class SyncBuffer:
4062 self._messages.append(_InfoMessage(project, fmt % args)) 4064 self._messages.append(_InfoMessage(project, fmt % args))
4063 4065
4064 def fail(self, project, err=None): 4066 def fail(self, project, err=None):
4065 self._failures.append(_Failure(project, err)) 4067 failure = _Failure(project, err)
4068 self._pending_failures.append(failure)
4069 self._all_failures.append(failure)
4066 self._MarkUnclean() 4070 self._MarkUnclean()
4067 4071
4068 def later1(self, project, what, quiet): 4072 def later1(self, project, what, quiet):
@@ -4082,6 +4086,11 @@ class SyncBuffer:
4082 self.recent_clean = True 4086 self.recent_clean = True
4083 return recent_clean 4087 return recent_clean
4084 4088
4089 @property
4090 def errors(self):
4091 """Returns a list of all exceptions accumulated in the buffer."""
4092 return [f.why for f in self._all_failures if f.why]
4093
4085 def _MarkUnclean(self): 4094 def _MarkUnclean(self):
4086 self.clean = False 4095 self.clean = False
4087 self.recent_clean = False 4096 self.recent_clean = False
@@ -4100,18 +4109,18 @@ class SyncBuffer:
4100 return True 4109 return True
4101 4110
4102 def _PrintMessages(self): 4111 def _PrintMessages(self):
4103 if self._messages or self._failures: 4112 if self._messages or self._pending_failures:
4104 if os.isatty(2): 4113 if os.isatty(2):
4105 self.out.write(progress.CSI_ERASE_LINE) 4114 self.out.write(progress.CSI_ERASE_LINE)
4106 self.out.write("\r") 4115 self.out.write("\r")
4107 4116
4108 for m in self._messages: 4117 for m in self._messages:
4109 m.Print(self) 4118 m.Print(self)
4110 for m in self._failures: 4119 for m in self._pending_failures:
4111 m.Print(self) 4120 m.Print(self)
4112 4121
4113 self._messages = [] 4122 self._messages = []
4114 self._failures = [] 4123 self._pending_failures = []
4115 4124
4116 4125
4117class MetaProject(Project): 4126class MetaProject(Project):
diff --git a/subcmds/sync.py b/subcmds/sync.py
index 82c065e2..ed2e516a 100644
--- a/subcmds/sync.py
+++ b/subcmds/sync.py
@@ -1092,10 +1092,10 @@ later is required to fix a server side protocol bug.
1092 force_sync=force_sync, 1092 force_sync=force_sync,
1093 force_checkout=force_checkout, 1093 force_checkout=force_checkout,
1094 force_rebase=force_rebase, 1094 force_rebase=force_rebase,
1095 errors=errors,
1096 verbose=verbose, 1095 verbose=verbose,
1097 ) 1096 )
1098 success = syncbuf.Finish() 1097 success = syncbuf.Finish()
1098 errors.extend(syncbuf.errors)
1099 except KeyboardInterrupt: 1099 except KeyboardInterrupt:
1100 logger.error("Keyboard interrupt while processing %s", project.name) 1100 logger.error("Keyboard interrupt while processing %s", project.name)
1101 except GitError as e: 1101 except GitError as e:
@@ -1753,10 +1753,10 @@ later is required to fix a server side protocol bug.
1753 mp.Sync_LocalHalf( 1753 mp.Sync_LocalHalf(
1754 syncbuf, 1754 syncbuf,
1755 submodules=mp.manifest.HasSubmodules, 1755 submodules=mp.manifest.HasSubmodules,
1756 errors=errors,
1757 verbose=opt.verbose, 1756 verbose=opt.verbose,
1758 ) 1757 )
1759 clean = syncbuf.Finish() 1758 clean = syncbuf.Finish()
1759 errors.extend(syncbuf.errors)
1760 self.event_log.AddSync( 1760 self.event_log.AddSync(
1761 mp, event_log.TASK_SYNC_LOCAL, start, time.time(), clean 1761 mp, event_log.TASK_SYNC_LOCAL, start, time.time(), clean
1762 ) 1762 )
@@ -2284,19 +2284,17 @@ later is required to fix a server side protocol bug.
2284 project.manifest.manifestProject.config, 2284 project.manifest.manifestProject.config,
2285 detach_head=opt.detach_head, 2285 detach_head=opt.detach_head,
2286 ) 2286 )
2287 local_half_errors = []
2288 project.Sync_LocalHalf( 2287 project.Sync_LocalHalf(
2289 syncbuf, 2288 syncbuf,
2290 force_sync=opt.force_sync, 2289 force_sync=opt.force_sync,
2291 force_checkout=opt.force_checkout, 2290 force_checkout=opt.force_checkout,
2292 force_rebase=opt.rebase, 2291 force_rebase=opt.rebase,
2293 errors=local_half_errors,
2294 verbose=opt.verbose, 2292 verbose=opt.verbose,
2295 ) 2293 )
2296 checkout_success = syncbuf.Finish() 2294 checkout_success = syncbuf.Finish()
2297 if local_half_errors: 2295 if syncbuf.errors:
2298 checkout_error = SyncError( 2296 checkout_error = SyncError(
2299 aggregate_errors=local_half_errors 2297 aggregate_errors=syncbuf.errors
2300 ) 2298 )
2301 except KeyboardInterrupt: 2299 except KeyboardInterrupt:
2302 logger.error( 2300 logger.error(
diff --git a/tests/test_subcmds_sync.py b/tests/test_subcmds_sync.py
index 5955e404..940c69fc 100644
--- a/tests/test_subcmds_sync.py
+++ b/tests/test_subcmds_sync.py
@@ -801,6 +801,7 @@ class InterleavedSyncTest(unittest.TestCase):
801 with mock.patch("subcmds.sync.SyncBuffer") as mock_sync_buffer: 801 with mock.patch("subcmds.sync.SyncBuffer") as mock_sync_buffer:
802 mock_sync_buf_instance = mock.MagicMock() 802 mock_sync_buf_instance = mock.MagicMock()
803 mock_sync_buf_instance.Finish.return_value = True 803 mock_sync_buf_instance.Finish.return_value = True
804 mock_sync_buf_instance.errors = []
804 mock_sync_buffer.return_value = mock_sync_buf_instance 805 mock_sync_buffer.return_value = mock_sync_buf_instance
805 806
806 result_obj = self.cmd._SyncProjectList(opt, [0]) 807 result_obj = self.cmd._SyncProjectList(opt, [0])
@@ -909,6 +910,7 @@ class InterleavedSyncTest(unittest.TestCase):
909 with mock.patch("subcmds.sync.SyncBuffer") as mock_sync_buffer: 910 with mock.patch("subcmds.sync.SyncBuffer") as mock_sync_buffer:
910 mock_sync_buf_instance = mock.MagicMock() 911 mock_sync_buf_instance = mock.MagicMock()
911 mock_sync_buf_instance.Finish.return_value = True 912 mock_sync_buf_instance.Finish.return_value = True
913 mock_sync_buf_instance.errors = []
912 mock_sync_buffer.return_value = mock_sync_buf_instance 914 mock_sync_buffer.return_value = mock_sync_buf_instance
913 915
914 result_obj = self.cmd._SyncProjectList(opt, [0]) 916 result_obj = self.cmd._SyncProjectList(opt, [0])