diff options
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: |