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]) |
