diff options
| -rw-r--r-- | subcmds/sync.py | 86 |
1 files changed, 57 insertions, 29 deletions
diff --git a/subcmds/sync.py b/subcmds/sync.py index ca4b97b3..808df208 100644 --- a/subcmds/sync.py +++ b/subcmds/sync.py | |||
| @@ -368,7 +368,7 @@ later is required to fix a server side protocol bug. | |||
| 368 | 368 | ||
| 369 | return success | 369 | return success |
| 370 | 370 | ||
| 371 | def _Fetch(self, projects, opt): | 371 | def _Fetch(self, projects, opt, err_event): |
| 372 | fetched = set() | 372 | fetched = set() |
| 373 | lock = _threading.Lock() | 373 | lock = _threading.Lock() |
| 374 | pm = Progress('Fetching projects', len(projects), | 374 | pm = Progress('Fetching projects', len(projects), |
| @@ -380,7 +380,6 @@ later is required to fix a server side protocol bug. | |||
| 380 | 380 | ||
| 381 | threads = set() | 381 | threads = set() |
| 382 | sem = _threading.Semaphore(self.jobs) | 382 | sem = _threading.Semaphore(self.jobs) |
| 383 | err_event = _threading.Event() | ||
| 384 | for project_list in objdir_project_map.values(): | 383 | for project_list in objdir_project_map.values(): |
| 385 | # Check for any errors before running any more tasks. | 384 | # Check for any errors before running any more tasks. |
| 386 | # ...we'll let existing threads finish, though. | 385 | # ...we'll let existing threads finish, though. |
| @@ -409,16 +408,11 @@ later is required to fix a server side protocol bug. | |||
| 409 | for t in threads: | 408 | for t in threads: |
| 410 | t.join() | 409 | t.join() |
| 411 | 410 | ||
| 412 | # If we saw an error, exit with code 1 so that other scripts can check. | ||
| 413 | if err_event.isSet() and opt.fail_fast: | ||
| 414 | print('\nerror: Exited sync due to fetch errors', file=sys.stderr) | ||
| 415 | sys.exit(1) | ||
| 416 | |||
| 417 | pm.end() | 411 | pm.end() |
| 418 | self._fetch_times.Save() | 412 | self._fetch_times.Save() |
| 419 | 413 | ||
| 420 | if not self.manifest.IsArchive: | 414 | if not self.manifest.IsArchive: |
| 421 | self._GCProjects(projects) | 415 | self._GCProjects(projects, opt, err_event) |
| 422 | 416 | ||
| 423 | return fetched | 417 | return fetched |
| 424 | 418 | ||
| @@ -504,12 +498,16 @@ later is required to fix a server side protocol bug. | |||
| 504 | 498 | ||
| 505 | return success | 499 | return success |
| 506 | 500 | ||
| 507 | def _Checkout(self, all_projects, opt): | 501 | def _Checkout(self, all_projects, opt, err_event, err_results): |
| 508 | """Checkout projects listed in all_projects | 502 | """Checkout projects listed in all_projects |
| 509 | 503 | ||
| 510 | Args: | 504 | Args: |
| 511 | all_projects: List of all projects that should be checked out. | 505 | all_projects: List of all projects that should be checked out. |
| 512 | opt: Program options returned from optparse. See _Options(). | 506 | opt: Program options returned from optparse. See _Options(). |
| 507 | err_event: We'll set this event in the case of an error (after printing | ||
| 508 | out info about the error). | ||
| 509 | err_results: A list of strings, paths to git repos where checkout | ||
| 510 | failed. | ||
| 513 | """ | 511 | """ |
| 514 | 512 | ||
| 515 | # Perform checkouts in multiple threads when we are using partial clone. | 513 | # Perform checkouts in multiple threads when we are using partial clone. |
| @@ -528,8 +526,6 @@ later is required to fix a server side protocol bug. | |||
| 528 | 526 | ||
| 529 | threads = set() | 527 | threads = set() |
| 530 | sem = _threading.Semaphore(syncjobs) | 528 | sem = _threading.Semaphore(syncjobs) |
| 531 | err_event = _threading.Event() | ||
| 532 | err_results = [] | ||
| 533 | 529 | ||
| 534 | for project in all_projects: | 530 | for project in all_projects: |
| 535 | # Check for any errors before running any more tasks. | 531 | # Check for any errors before running any more tasks. |
| @@ -560,15 +556,8 @@ later is required to fix a server side protocol bug. | |||
| 560 | t.join() | 556 | t.join() |
| 561 | 557 | ||
| 562 | pm.end() | 558 | pm.end() |
| 563 | # If we saw an error, exit with code 1 so that other scripts can check. | ||
| 564 | if err_event.isSet(): | ||
| 565 | print('\nerror: Exited sync due to checkout errors', file=sys.stderr) | ||
| 566 | if err_results: | ||
| 567 | print('Failing repos:\n%s' % '\n'.join(err_results), | ||
| 568 | file=sys.stderr) | ||
| 569 | sys.exit(1) | ||
| 570 | 559 | ||
| 571 | def _GCProjects(self, projects): | 560 | def _GCProjects(self, projects, opt, err_event): |
| 572 | gc_gitdirs = {} | 561 | gc_gitdirs = {} |
| 573 | for project in projects: | 562 | for project in projects: |
| 574 | if len(project.manifest.GetProjectsWithName(project.name)) > 1: | 563 | if len(project.manifest.GetProjectsWithName(project.name)) > 1: |
| @@ -592,7 +581,6 @@ later is required to fix a server side protocol bug. | |||
| 592 | 581 | ||
| 593 | threads = set() | 582 | threads = set() |
| 594 | sem = _threading.Semaphore(jobs) | 583 | sem = _threading.Semaphore(jobs) |
| 595 | err_event = _threading.Event() | ||
| 596 | 584 | ||
| 597 | def GC(bare_git): | 585 | def GC(bare_git): |
| 598 | try: | 586 | try: |
| @@ -607,7 +595,7 @@ later is required to fix a server side protocol bug. | |||
| 607 | sem.release() | 595 | sem.release() |
| 608 | 596 | ||
| 609 | for bare_git in gc_gitdirs.values(): | 597 | for bare_git in gc_gitdirs.values(): |
| 610 | if err_event.isSet(): | 598 | if err_event.isSet() and opt.fail_fast: |
| 611 | break | 599 | break |
| 612 | sem.acquire() | 600 | sem.acquire() |
| 613 | t = _threading.Thread(target=GC, args=(bare_git,)) | 601 | t = _threading.Thread(target=GC, args=(bare_git,)) |
| @@ -618,10 +606,6 @@ later is required to fix a server side protocol bug. | |||
| 618 | for t in threads: | 606 | for t in threads: |
| 619 | t.join() | 607 | t.join() |
| 620 | 608 | ||
| 621 | if err_event.isSet(): | ||
| 622 | print('\nerror: Exited sync due to gc errors', file=sys.stderr) | ||
| 623 | sys.exit(1) | ||
| 624 | |||
| 625 | def _ReloadManifest(self, manifest_name=None): | 609 | def _ReloadManifest(self, manifest_name=None): |
| 626 | if manifest_name: | 610 | if manifest_name: |
| 627 | # Override calls _Unload already | 611 | # Override calls _Unload already |
| @@ -902,6 +886,8 @@ later is required to fix a server side protocol bug. | |||
| 902 | print('error: failed to remove existing smart sync override manifest: %s' % | 886 | print('error: failed to remove existing smart sync override manifest: %s' % |
| 903 | e, file=sys.stderr) | 887 | e, file=sys.stderr) |
| 904 | 888 | ||
| 889 | err_event = _threading.Event() | ||
| 890 | |||
| 905 | rp = self.manifest.repoProject | 891 | rp = self.manifest.repoProject |
| 906 | rp.PreSync() | 892 | rp.PreSync() |
| 907 | 893 | ||
| @@ -955,6 +941,10 @@ later is required to fix a server side protocol bug. | |||
| 955 | missing_ok=True, | 941 | missing_ok=True, |
| 956 | submodules_ok=opt.fetch_submodules) | 942 | submodules_ok=opt.fetch_submodules) |
| 957 | 943 | ||
| 944 | err_network_sync = False | ||
| 945 | err_update_projects = False | ||
| 946 | err_checkout = False | ||
| 947 | |||
| 958 | self._fetch_times = _FetchTimes(self.manifest) | 948 | self._fetch_times = _FetchTimes(self.manifest) |
| 959 | if not opt.local_only: | 949 | if not opt.local_only: |
| 960 | to_fetch = [] | 950 | to_fetch = [] |
| @@ -964,10 +954,14 @@ later is required to fix a server side protocol bug. | |||
| 964 | to_fetch.extend(all_projects) | 954 | to_fetch.extend(all_projects) |
| 965 | to_fetch.sort(key=self._fetch_times.Get, reverse=True) | 955 | to_fetch.sort(key=self._fetch_times.Get, reverse=True) |
| 966 | 956 | ||
| 967 | fetched = self._Fetch(to_fetch, opt) | 957 | fetched = self._Fetch(to_fetch, opt, err_event) |
| 958 | |||
| 968 | _PostRepoFetch(rp, opt.no_repo_verify) | 959 | _PostRepoFetch(rp, opt.no_repo_verify) |
| 969 | if opt.network_only: | 960 | if opt.network_only: |
| 970 | # bail out now; the rest touches the working tree | 961 | # bail out now; the rest touches the working tree |
| 962 | if err_event.isSet(): | ||
| 963 | print('\nerror: Exited sync due to fetch errors.\n', file=sys.stderr) | ||
| 964 | sys.exit(1) | ||
| 971 | return | 965 | return |
| 972 | 966 | ||
| 973 | # Iteratively fetch missing and/or nested unregistered submodules | 967 | # Iteratively fetch missing and/or nested unregistered submodules |
| @@ -989,22 +983,56 @@ later is required to fix a server side protocol bug. | |||
| 989 | if previously_missing_set == missing_set: | 983 | if previously_missing_set == missing_set: |
| 990 | break | 984 | break |
| 991 | previously_missing_set = missing_set | 985 | previously_missing_set = missing_set |
| 992 | fetched.update(self._Fetch(missing, opt)) | 986 | fetched.update(self._Fetch(missing, opt, err_event)) |
| 987 | |||
| 988 | # If we saw an error, exit with code 1 so that other scripts can check. | ||
| 989 | if err_event.isSet(): | ||
| 990 | err_network_sync = True | ||
| 991 | if opt.fail_fast: | ||
| 992 | print('\nerror: Exited sync due to fetch errors.\n' | ||
| 993 | 'Local checkouts *not* updated. Resolve network issues & ' | ||
| 994 | 'retry.\n' | ||
| 995 | '`repo sync -l` will update some local checkouts.', | ||
| 996 | file=sys.stderr) | ||
| 997 | sys.exit(1) | ||
| 993 | 998 | ||
| 994 | if self.manifest.IsMirror or self.manifest.IsArchive: | 999 | if self.manifest.IsMirror or self.manifest.IsArchive: |
| 995 | # bail out now, we have no working tree | 1000 | # bail out now, we have no working tree |
| 996 | return | 1001 | return |
| 997 | 1002 | ||
| 998 | if self.UpdateProjectList(opt): | 1003 | if self.UpdateProjectList(opt): |
| 999 | sys.exit(1) | 1004 | err_event.set() |
| 1005 | err_update_projects = True | ||
| 1006 | if opt.fail_fast: | ||
| 1007 | print('\nerror: Local checkouts *not* updated.', file=sys.stderr) | ||
| 1008 | sys.exit(1) | ||
| 1000 | 1009 | ||
| 1001 | self._Checkout(all_projects, opt) | 1010 | err_results = [] |
| 1011 | self._Checkout(all_projects, opt, err_event, err_results) | ||
| 1012 | if err_event.isSet(): | ||
| 1013 | err_checkout = True | ||
| 1014 | # NB: We don't exit here because this is the last step. | ||
| 1002 | 1015 | ||
| 1003 | # If there's a notice that's supposed to print at the end of the sync, print | 1016 | # If there's a notice that's supposed to print at the end of the sync, print |
| 1004 | # it now... | 1017 | # it now... |
| 1005 | if self.manifest.notice: | 1018 | if self.manifest.notice: |
| 1006 | print(self.manifest.notice) | 1019 | print(self.manifest.notice) |
| 1007 | 1020 | ||
| 1021 | # If we saw an error, exit with code 1 so that other scripts can check. | ||
| 1022 | if err_event.isSet(): | ||
| 1023 | print('\nerror: Unable to fully sync the tree.', file=sys.stderr) | ||
| 1024 | if err_network_sync: | ||
| 1025 | print('error: Downloading network changes failed.', file=sys.stderr) | ||
| 1026 | if err_update_projects: | ||
| 1027 | print('error: Updating local project lists failed.', file=sys.stderr) | ||
| 1028 | if err_checkout: | ||
| 1029 | print('error: Checking out local projects failed.', file=sys.stderr) | ||
| 1030 | if err_results: | ||
| 1031 | print('Failing repos:\n%s' % '\n'.join(err_results), file=sys.stderr) | ||
| 1032 | print('Try re-running with "-j1 --fail-fast" to exit at the first error.', | ||
| 1033 | file=sys.stderr) | ||
| 1034 | sys.exit(1) | ||
| 1035 | |||
| 1008 | def _PostRepoUpgrade(manifest, quiet=False): | 1036 | def _PostRepoUpgrade(manifest, quiet=False): |
| 1009 | wrapper = Wrapper() | 1037 | wrapper = Wrapper() |
| 1010 | if wrapper.NeedSetupGnuPG(): | 1038 | if wrapper.NeedSetupGnuPG(): |
