diff options
-rw-r--r-- | project.py | 29 | ||||
-rw-r--r-- | subcmds/sync.py | 10 | ||||
-rw-r--r-- | tests/test_subcmds_sync.py | 2 |
3 files changed, 25 insertions, 16 deletions
@@ -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): | |||
4047 | class SyncBuffer: | 4044 | class 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 | ||
4117 | class MetaProject(Project): | 4126 | class 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]) |