diff options
author | Jason Chang <jasonnc@google.com> | 2023-07-14 16:45:35 -0700 |
---|---|---|
committer | LUCI <gerrit-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2023-08-02 18:29:05 +0000 |
commit | 32b59565b7bd41ec1a121869823557f0b2b022d7 (patch) | |
tree | 0cd0fe644ecc6e319df96861f26b77a55c9969eb /subcmds/sync.py | |
parent | a6413f5d88f12466b3daa833668d0f59fc65ece4 (diff) | |
download | git-repo-32b59565b7bd41ec1a121869823557f0b2b022d7.tar.gz |
Refactor errors for sync command
Per discussion in go/repo-error-update updated aggregated and exit
errors for sync command.
Aggregated errors are errors that result in eventual command failure.
Exit errors are errors that result in immediate command failure.
Also updated main.py to log aggregated and exit errors to git sessions
log
Bug: b/293344017
Change-Id: I77a21f14da32fe2e68c16841feb22de72e86a251
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/379614
Reviewed-by: Aravind Vasudevan <aravindvasudev@google.com>
Tested-by: Jason Chang <jasonnc@google.com>
Commit-Queue: Jason Chang <jasonnc@google.com>
Diffstat (limited to 'subcmds/sync.py')
-rw-r--r-- | subcmds/sync.py | 159 |
1 files changed, 114 insertions, 45 deletions
diff --git a/subcmds/sync.py b/subcmds/sync.py index 5f8bc2f0..eaca50c9 100644 --- a/subcmds/sync.py +++ b/subcmds/sync.py | |||
@@ -63,9 +63,16 @@ from command import ( | |||
63 | MirrorSafeCommand, | 63 | MirrorSafeCommand, |
64 | WORKER_BATCH_SIZE, | 64 | WORKER_BATCH_SIZE, |
65 | ) | 65 | ) |
66 | from error import RepoChangedException, GitError | 66 | from error import ( |
67 | RepoChangedException, | ||
68 | GitError, | ||
69 | RepoExitError, | ||
70 | SyncError, | ||
71 | UpdateManifestError, | ||
72 | RepoUnhandledExceptionError, | ||
73 | ) | ||
67 | import platform_utils | 74 | import platform_utils |
68 | from project import SyncBuffer | 75 | from project import SyncBuffer, DeleteWorktreeError |
69 | from progress import Progress, elapsed_str, jobs_str | 76 | from progress import Progress, elapsed_str, jobs_str |
70 | from repo_trace import Trace | 77 | from repo_trace import Trace |
71 | import ssh | 78 | import ssh |
@@ -94,6 +101,7 @@ class _FetchOneResult(NamedTuple): | |||
94 | """ | 101 | """ |
95 | 102 | ||
96 | success: bool | 103 | success: bool |
104 | errors: List[Exception] | ||
97 | project: Project | 105 | project: Project |
98 | start: float | 106 | start: float |
99 | finish: float | 107 | finish: float |
@@ -110,6 +118,7 @@ class _FetchResult(NamedTuple): | |||
110 | 118 | ||
111 | success: bool | 119 | success: bool |
112 | projects: Set[str] | 120 | projects: Set[str] |
121 | errors: List[Exception] | ||
113 | 122 | ||
114 | 123 | ||
115 | class _FetchMainResult(NamedTuple): | 124 | class _FetchMainResult(NamedTuple): |
@@ -120,6 +129,7 @@ class _FetchMainResult(NamedTuple): | |||
120 | """ | 129 | """ |
121 | 130 | ||
122 | all_projects: List[Project] | 131 | all_projects: List[Project] |
132 | errors: List[Exception] | ||
123 | 133 | ||
124 | 134 | ||
125 | class _CheckoutOneResult(NamedTuple): | 135 | class _CheckoutOneResult(NamedTuple): |
@@ -133,11 +143,24 @@ class _CheckoutOneResult(NamedTuple): | |||
133 | """ | 143 | """ |
134 | 144 | ||
135 | success: bool | 145 | success: bool |
146 | errors: List[Exception] | ||
136 | project: Project | 147 | project: Project |
137 | start: float | 148 | start: float |
138 | finish: float | 149 | finish: float |
139 | 150 | ||
140 | 151 | ||
152 | class SuperprojectError(SyncError): | ||
153 | """Superproject sync repo.""" | ||
154 | |||
155 | |||
156 | class SyncFailFastError(SyncError): | ||
157 | """Sync exit error when --fail-fast set.""" | ||
158 | |||
159 | |||
160 | class SmartSyncError(SyncError): | ||
161 | """Smart sync exit error.""" | ||
162 | |||
163 | |||
141 | class Sync(Command, MirrorSafeCommand): | 164 | class Sync(Command, MirrorSafeCommand): |
142 | COMMON = True | 165 | COMMON = True |
143 | MULTI_MANIFEST_SUPPORT = True | 166 | MULTI_MANIFEST_SUPPORT = True |
@@ -588,7 +611,7 @@ later is required to fix a server side protocol bug. | |||
588 | file=sys.stderr, | 611 | file=sys.stderr, |
589 | ) | 612 | ) |
590 | if update_result.fatal and opt.use_superproject is not None: | 613 | if update_result.fatal and opt.use_superproject is not None: |
591 | sys.exit(1) | 614 | raise SuperprojectError() |
592 | if need_unload: | 615 | if need_unload: |
593 | m.outer_client.manifest.Unload() | 616 | m.outer_client.manifest.Unload() |
594 | 617 | ||
@@ -621,6 +644,7 @@ later is required to fix a server side protocol bug. | |||
621 | self._sync_dict[k] = start | 644 | self._sync_dict[k] = start |
622 | success = False | 645 | success = False |
623 | remote_fetched = False | 646 | remote_fetched = False |
647 | errors = [] | ||
624 | buf = io.StringIO() | 648 | buf = io.StringIO() |
625 | try: | 649 | try: |
626 | sync_result = project.Sync_NetworkHalf( | 650 | sync_result = project.Sync_NetworkHalf( |
@@ -644,6 +668,8 @@ later is required to fix a server side protocol bug. | |||
644 | ) | 668 | ) |
645 | success = sync_result.success | 669 | success = sync_result.success |
646 | remote_fetched = sync_result.remote_fetched | 670 | remote_fetched = sync_result.remote_fetched |
671 | if sync_result.error: | ||
672 | errors.append(sync_result.error) | ||
647 | 673 | ||
648 | output = buf.getvalue() | 674 | output = buf.getvalue() |
649 | if (opt.verbose or not success) and output: | 675 | if (opt.verbose or not success) and output: |
@@ -659,6 +685,7 @@ later is required to fix a server side protocol bug. | |||
659 | print(f"Keyboard interrupt while processing {project.name}") | 685 | print(f"Keyboard interrupt while processing {project.name}") |
660 | except GitError as e: | 686 | except GitError as e: |
661 | print("error.GitError: Cannot fetch %s" % str(e), file=sys.stderr) | 687 | print("error.GitError: Cannot fetch %s" % str(e), file=sys.stderr) |
688 | errors.append(e) | ||
662 | except Exception as e: | 689 | except Exception as e: |
663 | print( | 690 | print( |
664 | "error: Cannot fetch %s (%s: %s)" | 691 | "error: Cannot fetch %s (%s: %s)" |
@@ -666,11 +693,14 @@ later is required to fix a server side protocol bug. | |||
666 | file=sys.stderr, | 693 | file=sys.stderr, |
667 | ) | 694 | ) |
668 | del self._sync_dict[k] | 695 | del self._sync_dict[k] |
696 | errors.append(e) | ||
669 | raise | 697 | raise |
670 | 698 | ||
671 | finish = time.time() | 699 | finish = time.time() |
672 | del self._sync_dict[k] | 700 | del self._sync_dict[k] |
673 | return _FetchOneResult(success, project, start, finish, remote_fetched) | 701 | return _FetchOneResult( |
702 | success, errors, project, start, finish, remote_fetched | ||
703 | ) | ||
674 | 704 | ||
675 | @classmethod | 705 | @classmethod |
676 | def _FetchInitChild(cls, ssh_proxy): | 706 | def _FetchInitChild(cls, ssh_proxy): |
@@ -701,6 +731,7 @@ later is required to fix a server side protocol bug. | |||
701 | jobs = opt.jobs_network | 731 | jobs = opt.jobs_network |
702 | fetched = set() | 732 | fetched = set() |
703 | remote_fetched = set() | 733 | remote_fetched = set() |
734 | errors = [] | ||
704 | pm = Progress( | 735 | pm = Progress( |
705 | "Fetching", | 736 | "Fetching", |
706 | len(projects), | 737 | len(projects), |
@@ -745,6 +776,8 @@ later is required to fix a server side protocol bug. | |||
745 | finish, | 776 | finish, |
746 | success, | 777 | success, |
747 | ) | 778 | ) |
779 | if result.errors: | ||
780 | errors.extend(result.errors) | ||
748 | if result.remote_fetched: | 781 | if result.remote_fetched: |
749 | remote_fetched.add(project) | 782 | remote_fetched.add(project) |
750 | # Check for any errors before running any more tasks. | 783 | # Check for any errors before running any more tasks. |
@@ -813,7 +846,7 @@ later is required to fix a server side protocol bug. | |||
813 | if not self.outer_client.manifest.IsArchive: | 846 | if not self.outer_client.manifest.IsArchive: |
814 | self._GCProjects(projects, opt, err_event) | 847 | self._GCProjects(projects, opt, err_event) |
815 | 848 | ||
816 | return _FetchResult(ret, fetched) | 849 | return _FetchResult(ret, fetched, errors) |
817 | 850 | ||
818 | def _FetchMain( | 851 | def _FetchMain( |
819 | self, opt, args, all_projects, err_event, ssh_proxy, manifest | 852 | self, opt, args, all_projects, err_event, ssh_proxy, manifest |
@@ -832,6 +865,7 @@ later is required to fix a server side protocol bug. | |||
832 | List of all projects that should be checked out. | 865 | List of all projects that should be checked out. |
833 | """ | 866 | """ |
834 | rp = manifest.repoProject | 867 | rp = manifest.repoProject |
868 | errors = [] | ||
835 | 869 | ||
836 | to_fetch = [] | 870 | to_fetch = [] |
837 | now = time.time() | 871 | now = time.time() |
@@ -843,6 +877,9 @@ later is required to fix a server side protocol bug. | |||
843 | result = self._Fetch(to_fetch, opt, err_event, ssh_proxy) | 877 | result = self._Fetch(to_fetch, opt, err_event, ssh_proxy) |
844 | success = result.success | 878 | success = result.success |
845 | fetched = result.projects | 879 | fetched = result.projects |
880 | if result.errors: | ||
881 | errors.extend(result.errors) | ||
882 | |||
846 | if not success: | 883 | if not success: |
847 | err_event.set() | 884 | err_event.set() |
848 | 885 | ||
@@ -854,8 +891,11 @@ later is required to fix a server side protocol bug. | |||
854 | "\nerror: Exited sync due to fetch errors.\n", | 891 | "\nerror: Exited sync due to fetch errors.\n", |
855 | file=sys.stderr, | 892 | file=sys.stderr, |
856 | ) | 893 | ) |
857 | sys.exit(1) | 894 | raise SyncError( |
858 | return _FetchMainResult([]) | 895 | "error: Exited sync due to fetch errors.", |
896 | aggregate_errors=errors, | ||
897 | ) | ||
898 | return _FetchMainResult([], errors) | ||
859 | 899 | ||
860 | # Iteratively fetch missing and/or nested unregistered submodules. | 900 | # Iteratively fetch missing and/or nested unregistered submodules. |
861 | previously_missing_set = set() | 901 | previously_missing_set = set() |
@@ -883,11 +923,13 @@ later is required to fix a server side protocol bug. | |||
883 | result = self._Fetch(missing, opt, err_event, ssh_proxy) | 923 | result = self._Fetch(missing, opt, err_event, ssh_proxy) |
884 | success = result.success | 924 | success = result.success |
885 | new_fetched = result.projects | 925 | new_fetched = result.projects |
926 | if result.errors: | ||
927 | errors.extend(result.errors) | ||
886 | if not success: | 928 | if not success: |
887 | err_event.set() | 929 | err_event.set() |
888 | fetched.update(new_fetched) | 930 | fetched.update(new_fetched) |
889 | 931 | ||
890 | return _FetchMainResult(all_projects) | 932 | return _FetchMainResult(all_projects, errors) |
891 | 933 | ||
892 | def _CheckoutOne(self, detach_head, force_sync, project): | 934 | def _CheckoutOne(self, detach_head, force_sync, project): |
893 | """Checkout work tree for one project | 935 | """Checkout work tree for one project |
@@ -905,8 +947,11 @@ later is required to fix a server side protocol bug. | |||
905 | project.manifest.manifestProject.config, detach_head=detach_head | 947 | project.manifest.manifestProject.config, detach_head=detach_head |
906 | ) | 948 | ) |
907 | success = False | 949 | success = False |
950 | errors = [] | ||
908 | try: | 951 | try: |
909 | project.Sync_LocalHalf(syncbuf, force_sync=force_sync) | 952 | project.Sync_LocalHalf( |
953 | syncbuf, force_sync=force_sync, errors=errors | ||
954 | ) | ||
910 | success = syncbuf.Finish() | 955 | success = syncbuf.Finish() |
911 | except GitError as e: | 956 | except GitError as e: |
912 | print( | 957 | print( |
@@ -914,6 +959,7 @@ later is required to fix a server side protocol bug. | |||
914 | % (project.name, str(e)), | 959 | % (project.name, str(e)), |
915 | file=sys.stderr, | 960 | file=sys.stderr, |
916 | ) | 961 | ) |
962 | errors.append(e) | ||
917 | except Exception as e: | 963 | except Exception as e: |
918 | print( | 964 | print( |
919 | "error: Cannot checkout %s: %s: %s" | 965 | "error: Cannot checkout %s: %s: %s" |
@@ -925,9 +971,9 @@ later is required to fix a server side protocol bug. | |||
925 | if not success: | 971 | if not success: |
926 | print("error: Cannot checkout %s" % (project.name), file=sys.stderr) | 972 | print("error: Cannot checkout %s" % (project.name), file=sys.stderr) |
927 | finish = time.time() | 973 | finish = time.time() |
928 | return _CheckoutOneResult(success, project, start, finish) | 974 | return _CheckoutOneResult(success, errors, project, start, finish) |
929 | 975 | ||
930 | def _Checkout(self, all_projects, opt, err_results): | 976 | def _Checkout(self, all_projects, opt, err_results, checkout_errors): |
931 | """Checkout projects listed in all_projects | 977 | """Checkout projects listed in all_projects |
932 | 978 | ||
933 | Args: | 979 | Args: |
@@ -949,6 +995,10 @@ later is required to fix a server side protocol bug. | |||
949 | self.event_log.AddSync( | 995 | self.event_log.AddSync( |
950 | project, event_log.TASK_SYNC_LOCAL, start, finish, success | 996 | project, event_log.TASK_SYNC_LOCAL, start, finish, success |
951 | ) | 997 | ) |
998 | |||
999 | if result.errors: | ||
1000 | checkout_errors.extend(result.errors) | ||
1001 | |||
952 | # Check for any errors before running any more tasks. | 1002 | # Check for any errors before running any more tasks. |
953 | # ...we'll let existing jobs finish, though. | 1003 | # ...we'll let existing jobs finish, though. |
954 | if success: | 1004 | if success: |
@@ -1214,10 +1264,9 @@ later is required to fix a server side protocol bug. | |||
1214 | revisionId=None, | 1264 | revisionId=None, |
1215 | groups=None, | 1265 | groups=None, |
1216 | ) | 1266 | ) |
1217 | if not project.DeleteWorktree( | 1267 | project.DeleteWorktree( |
1218 | quiet=opt.quiet, force=opt.force_remove_dirty | 1268 | quiet=opt.quiet, force=opt.force_remove_dirty |
1219 | ): | 1269 | ) |
1220 | return 1 | ||
1221 | 1270 | ||
1222 | new_project_paths.sort() | 1271 | new_project_paths.sort() |
1223 | with open(file_path, "w") as fd: | 1272 | with open(file_path, "w") as fd: |
@@ -1260,7 +1309,7 @@ later is required to fix a server side protocol bug. | |||
1260 | file=sys.stderr, | 1309 | file=sys.stderr, |
1261 | ) | 1310 | ) |
1262 | platform_utils.remove(copylinkfile_path) | 1311 | platform_utils.remove(copylinkfile_path) |
1263 | return False | 1312 | raise |
1264 | 1313 | ||
1265 | need_remove_files = [] | 1314 | need_remove_files = [] |
1266 | need_remove_files.extend( | 1315 | need_remove_files.extend( |
@@ -1285,12 +1334,10 @@ later is required to fix a server side protocol bug. | |||
1285 | 1334 | ||
1286 | def _SmartSyncSetup(self, opt, smart_sync_manifest_path, manifest): | 1335 | def _SmartSyncSetup(self, opt, smart_sync_manifest_path, manifest): |
1287 | if not manifest.manifest_server: | 1336 | if not manifest.manifest_server: |
1288 | print( | 1337 | raise SmartSyncError( |
1289 | "error: cannot smart sync: no manifest server defined in " | 1338 | "error: cannot smart sync: no manifest server defined in " |
1290 | "manifest", | 1339 | "manifest" |
1291 | file=sys.stderr, | ||
1292 | ) | 1340 | ) |
1293 | sys.exit(1) | ||
1294 | 1341 | ||
1295 | manifest_server = manifest.manifest_server | 1342 | manifest_server = manifest.manifest_server |
1296 | if not opt.quiet: | 1343 | if not opt.quiet: |
@@ -1368,33 +1415,28 @@ later is required to fix a server side protocol bug. | |||
1368 | with open(smart_sync_manifest_path, "w") as f: | 1415 | with open(smart_sync_manifest_path, "w") as f: |
1369 | f.write(manifest_str) | 1416 | f.write(manifest_str) |
1370 | except IOError as e: | 1417 | except IOError as e: |
1371 | print( | 1418 | raise SmartSyncError( |
1372 | "error: cannot write manifest to %s:\n%s" | 1419 | "error: cannot write manifest to %s:\n%s" |
1373 | % (smart_sync_manifest_path, e), | 1420 | % (smart_sync_manifest_path, e), |
1374 | file=sys.stderr, | 1421 | aggregate_errors=[e], |
1375 | ) | 1422 | ) |
1376 | sys.exit(1) | ||
1377 | self._ReloadManifest(manifest_name, manifest) | 1423 | self._ReloadManifest(manifest_name, manifest) |
1378 | else: | 1424 | else: |
1379 | print( | 1425 | raise SmartSyncError( |
1380 | "error: manifest server RPC call failed: %s" % manifest_str, | 1426 | "error: manifest server RPC call failed: %s" % manifest_str |
1381 | file=sys.stderr, | ||
1382 | ) | 1427 | ) |
1383 | sys.exit(1) | ||
1384 | except (socket.error, IOError, xmlrpc.client.Fault) as e: | 1428 | except (socket.error, IOError, xmlrpc.client.Fault) as e: |
1385 | print( | 1429 | raise SmartSyncError( |
1386 | "error: cannot connect to manifest server %s:\n%s" | 1430 | "error: cannot connect to manifest server %s:\n%s" |
1387 | % (manifest.manifest_server, e), | 1431 | % (manifest.manifest_server, e), |
1388 | file=sys.stderr, | 1432 | aggregate_errors=[e], |
1389 | ) | 1433 | ) |
1390 | sys.exit(1) | ||
1391 | except xmlrpc.client.ProtocolError as e: | 1434 | except xmlrpc.client.ProtocolError as e: |
1392 | print( | 1435 | raise SmartSyncError( |
1393 | "error: cannot connect to manifest server %s:\n%d %s" | 1436 | "error: cannot connect to manifest server %s:\n%d %s" |
1394 | % (manifest.manifest_server, e.errcode, e.errmsg), | 1437 | % (manifest.manifest_server, e.errcode, e.errmsg), |
1395 | file=sys.stderr, | 1438 | aggregate_errors=[e], |
1396 | ) | 1439 | ) |
1397 | sys.exit(1) | ||
1398 | 1440 | ||
1399 | return manifest_name | 1441 | return manifest_name |
1400 | 1442 | ||
@@ -1436,7 +1478,7 @@ later is required to fix a server side protocol bug. | |||
1436 | """ | 1478 | """ |
1437 | if not opt.local_only: | 1479 | if not opt.local_only: |
1438 | start = time.time() | 1480 | start = time.time() |
1439 | success = mp.Sync_NetworkHalf( | 1481 | result = mp.Sync_NetworkHalf( |
1440 | quiet=opt.quiet, | 1482 | quiet=opt.quiet, |
1441 | verbose=opt.verbose, | 1483 | verbose=opt.verbose, |
1442 | current_branch_only=self._GetCurrentBranchOnly( | 1484 | current_branch_only=self._GetCurrentBranchOnly( |
@@ -1453,19 +1495,24 @@ later is required to fix a server side protocol bug. | |||
1453 | ) | 1495 | ) |
1454 | finish = time.time() | 1496 | finish = time.time() |
1455 | self.event_log.AddSync( | 1497 | self.event_log.AddSync( |
1456 | mp, event_log.TASK_SYNC_NETWORK, start, finish, success | 1498 | mp, event_log.TASK_SYNC_NETWORK, start, finish, result.success |
1457 | ) | 1499 | ) |
1458 | 1500 | ||
1459 | if mp.HasChanges: | 1501 | if mp.HasChanges: |
1502 | errors = [] | ||
1460 | syncbuf = SyncBuffer(mp.config) | 1503 | syncbuf = SyncBuffer(mp.config) |
1461 | start = time.time() | 1504 | start = time.time() |
1462 | mp.Sync_LocalHalf(syncbuf, submodules=mp.manifest.HasSubmodules) | 1505 | mp.Sync_LocalHalf( |
1506 | syncbuf, submodules=mp.manifest.HasSubmodules, errors=errors | ||
1507 | ) | ||
1463 | clean = syncbuf.Finish() | 1508 | clean = syncbuf.Finish() |
1464 | self.event_log.AddSync( | 1509 | self.event_log.AddSync( |
1465 | mp, event_log.TASK_SYNC_LOCAL, start, time.time(), clean | 1510 | mp, event_log.TASK_SYNC_LOCAL, start, time.time(), clean |
1466 | ) | 1511 | ) |
1467 | if not clean: | 1512 | if not clean: |
1468 | sys.exit(1) | 1513 | raise UpdateManifestError( |
1514 | aggregate_errors=errors, project=mp.name | ||
1515 | ) | ||
1469 | self._ReloadManifest(manifest_name, mp.manifest) | 1516 | self._ReloadManifest(manifest_name, mp.manifest) |
1470 | 1517 | ||
1471 | def ValidateOptions(self, opt, args): | 1518 | def ValidateOptions(self, opt, args): |
@@ -1546,6 +1593,15 @@ later is required to fix a server side protocol bug. | |||
1546 | opt.jobs_checkout = min(opt.jobs_checkout, jobs_soft_limit) | 1593 | opt.jobs_checkout = min(opt.jobs_checkout, jobs_soft_limit) |
1547 | 1594 | ||
1548 | def Execute(self, opt, args): | 1595 | def Execute(self, opt, args): |
1596 | errors = [] | ||
1597 | try: | ||
1598 | self._ExecuteHelper(opt, args, errors) | ||
1599 | except RepoExitError: | ||
1600 | raise | ||
1601 | except (KeyboardInterrupt, Exception) as e: | ||
1602 | raise RepoUnhandledExceptionError(e, aggregate_errors=errors) | ||
1603 | |||
1604 | def _ExecuteHelper(self, opt, args, errors): | ||
1549 | manifest = self.outer_manifest | 1605 | manifest = self.outer_manifest |
1550 | if not opt.outer_manifest: | 1606 | if not opt.outer_manifest: |
1551 | manifest = self.manifest | 1607 | manifest = self.manifest |
@@ -1695,6 +1751,8 @@ later is required to fix a server side protocol bug. | |||
1695 | result = self._FetchMain( | 1751 | result = self._FetchMain( |
1696 | opt, args, all_projects, err_event, ssh_proxy, manifest | 1752 | opt, args, all_projects, err_event, ssh_proxy, manifest |
1697 | ) | 1753 | ) |
1754 | if result.errors: | ||
1755 | errors.extend(result.errors) | ||
1698 | all_projects = result.all_projects | 1756 | all_projects = result.all_projects |
1699 | 1757 | ||
1700 | if opt.network_only: | 1758 | if opt.network_only: |
@@ -1712,36 +1770,47 @@ later is required to fix a server side protocol bug. | |||
1712 | "`repo sync -l` will update some local checkouts.", | 1770 | "`repo sync -l` will update some local checkouts.", |
1713 | file=sys.stderr, | 1771 | file=sys.stderr, |
1714 | ) | 1772 | ) |
1715 | sys.exit(1) | 1773 | raise SyncFailFastError(aggregate_errors=errors) |
1716 | 1774 | ||
1717 | for m in self.ManifestList(opt): | 1775 | for m in self.ManifestList(opt): |
1718 | if m.IsMirror or m.IsArchive: | 1776 | if m.IsMirror or m.IsArchive: |
1719 | # Bail out now, we have no working tree. | 1777 | # Bail out now, we have no working tree. |
1720 | continue | 1778 | continue |
1721 | 1779 | ||
1722 | if self.UpdateProjectList(opt, m): | 1780 | try: |
1781 | self.UpdateProjectList(opt, m) | ||
1782 | except Exception as e: | ||
1723 | err_event.set() | 1783 | err_event.set() |
1724 | err_update_projects = True | 1784 | err_update_projects = True |
1785 | errors.append(e) | ||
1786 | if isinstance(e, DeleteWorktreeError): | ||
1787 | errors.extend(e.aggregate_errors) | ||
1725 | if opt.fail_fast: | 1788 | if opt.fail_fast: |
1726 | print( | 1789 | print( |
1727 | "\nerror: Local checkouts *not* updated.", | 1790 | "\nerror: Local checkouts *not* updated.", |
1728 | file=sys.stderr, | 1791 | file=sys.stderr, |
1729 | ) | 1792 | ) |
1730 | sys.exit(1) | 1793 | raise SyncFailFastError(aggregate_errors=errors) |
1731 | 1794 | ||
1732 | err_update_linkfiles = not self.UpdateCopyLinkfileList(m) | 1795 | err_update_linkfiles = False |
1733 | if err_update_linkfiles: | 1796 | try: |
1797 | self.UpdateCopyLinkfileList(m) | ||
1798 | except Exception as e: | ||
1799 | err_update_linkfiles = True | ||
1800 | errors.append(e) | ||
1734 | err_event.set() | 1801 | err_event.set() |
1735 | if opt.fail_fast: | 1802 | if opt.fail_fast: |
1736 | print( | 1803 | print( |
1737 | "\nerror: Local update copyfile or linkfile failed.", | 1804 | "\nerror: Local update copyfile or linkfile failed.", |
1738 | file=sys.stderr, | 1805 | file=sys.stderr, |
1739 | ) | 1806 | ) |
1740 | sys.exit(1) | 1807 | raise SyncFailFastError(aggregate_errors=errors) |
1741 | 1808 | ||
1742 | err_results = [] | 1809 | err_results = [] |
1743 | # NB: We don't exit here because this is the last step. | 1810 | # NB: We don't exit here because this is the last step. |
1744 | err_checkout = not self._Checkout(all_projects, opt, err_results) | 1811 | err_checkout = not self._Checkout( |
1812 | all_projects, opt, err_results, errors | ||
1813 | ) | ||
1745 | if err_checkout: | 1814 | if err_checkout: |
1746 | err_event.set() | 1815 | err_event.set() |
1747 | 1816 | ||
@@ -1784,7 +1853,7 @@ later is required to fix a server side protocol bug. | |||
1784 | "error.", | 1853 | "error.", |
1785 | file=sys.stderr, | 1854 | file=sys.stderr, |
1786 | ) | 1855 | ) |
1787 | sys.exit(1) | 1856 | raise SyncError(aggregate_errors=errors) |
1788 | 1857 | ||
1789 | # Log the previous sync analysis state from the config. | 1858 | # Log the previous sync analysis state from the config. |
1790 | self.git_event_log.LogDataConfigEvents( | 1859 | self.git_event_log.LogDataConfigEvents( |
@@ -1842,7 +1911,7 @@ def _PostRepoFetch(rp, repo_verify=True, verbose=False): | |||
1842 | try: | 1911 | try: |
1843 | rp.work_git.reset("--keep", new_rev) | 1912 | rp.work_git.reset("--keep", new_rev) |
1844 | except GitError as e: | 1913 | except GitError as e: |
1845 | sys.exit(str(e)) | 1914 | raise RepoUnhandledExceptionError(e) |
1846 | print("info: Restarting repo with latest version", file=sys.stderr) | 1915 | print("info: Restarting repo with latest version", file=sys.stderr) |
1847 | raise RepoChangedException(["--repo-upgraded"]) | 1916 | raise RepoChangedException(["--repo-upgraded"]) |
1848 | else: | 1917 | else: |