diff options
| author | LaMont Jones <lamontjones@google.com> | 2022-04-11 22:50:11 +0000 |
|---|---|---|
| committer | LaMont Jones <lamontjones@google.com> | 2022-05-26 00:03:37 +0000 |
| commit | bdcba7dc36f1c8e6041681eb5b3b5229c93c7c5c (patch) | |
| tree | ef0dbd149d7e5cd35c4d007a5052ba42bcc1c881 /subcmds/sync.py | |
| parent | 1d00a7e2ae64b6c08aff60c2e7ed5c2d89caf8d6 (diff) | |
| download | git-repo-bdcba7dc36f1c8e6041681eb5b3b5229c93c7c5c.tar.gz | |
sync: add multi-manifest supportv2.26
With this change, partial syncs (sync with a project list) are again
supported.
If the updated manifest includes new sub manifests, download them
inheriting options from the parent manifestProject.
Change-Id: Id952f85df2e26d34e38b251973be26434443ff56
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/334819
Reviewed-by: Mike Frysinger <vapier@google.com>
Tested-by: LaMont Jones <lamontjones@google.com>
Diffstat (limited to 'subcmds/sync.py')
| -rw-r--r-- | subcmds/sync.py | 274 |
1 files changed, 176 insertions, 98 deletions
diff --git a/subcmds/sync.py b/subcmds/sync.py index 9a66e48b..0abe23d6 100644 --- a/subcmds/sync.py +++ b/subcmds/sync.py | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | # See the License for the specific language governing permissions and | 12 | # See the License for the specific language governing permissions and |
| 13 | # limitations under the License. | 13 | # limitations under the License. |
| 14 | 14 | ||
| 15 | import collections | ||
| 15 | import functools | 16 | import functools |
| 16 | import http.cookiejar as cookielib | 17 | import http.cookiejar as cookielib |
| 17 | import io | 18 | import io |
| @@ -66,7 +67,7 @@ _ONE_DAY_S = 24 * 60 * 60 | |||
| 66 | class Sync(Command, MirrorSafeCommand): | 67 | class Sync(Command, MirrorSafeCommand): |
| 67 | jobs = 1 | 68 | jobs = 1 |
| 68 | COMMON = True | 69 | COMMON = True |
| 69 | MULTI_MANIFEST_SUPPORT = False | 70 | MULTI_MANIFEST_SUPPORT = True |
| 70 | helpSummary = "Update working tree to the latest revision" | 71 | helpSummary = "Update working tree to the latest revision" |
| 71 | helpUsage = """ | 72 | helpUsage = """ |
| 72 | %prog [<project>...] | 73 | %prog [<project>...] |
| @@ -295,52 +296,92 @@ later is required to fix a server side protocol bug. | |||
| 295 | """ | 296 | """ |
| 296 | return git_superproject.UseSuperproject(opt.use_superproject, manifest) or opt.current_branch_only | 297 | return git_superproject.UseSuperproject(opt.use_superproject, manifest) or opt.current_branch_only |
| 297 | 298 | ||
| 298 | def _UpdateProjectsRevisionId(self, opt, args, load_local_manifests, superproject_logging_data, manifest): | 299 | def _UpdateProjectsRevisionId(self, opt, args, superproject_logging_data, |
| 299 | """Update revisionId of every project with the SHA from superproject. | 300 | manifest): |
| 301 | """Update revisionId of projects with the commit hash from the superproject. | ||
| 300 | 302 | ||
| 301 | This function updates each project's revisionId with SHA from superproject. | 303 | This function updates each project's revisionId with the commit hash from |
| 302 | It writes the updated manifest into a file and reloads the manifest from it. | 304 | the superproject. It writes the updated manifest into a file and reloads |
| 305 | the manifest from it. When appropriate, sub manifests are also processed. | ||
| 303 | 306 | ||
| 304 | Args: | 307 | Args: |
| 305 | opt: Program options returned from optparse. See _Options(). | 308 | opt: Program options returned from optparse. See _Options(). |
| 306 | args: Arguments to pass to GetProjects. See the GetProjects | 309 | args: Arguments to pass to GetProjects. See the GetProjects |
| 307 | docstring for details. | 310 | docstring for details. |
| 308 | load_local_manifests: Whether to load local manifests. | 311 | superproject_logging_data: A dictionary of superproject data to log. |
| 309 | superproject_logging_data: A dictionary of superproject data that is to be logged. | ||
| 310 | manifest: The manifest to use. | 312 | manifest: The manifest to use. |
| 311 | |||
| 312 | Returns: | ||
| 313 | Returns path to the overriding manifest file instead of None. | ||
| 314 | """ | 313 | """ |
| 315 | superproject = self.manifest.superproject | 314 | have_superproject = manifest.superproject or any( |
| 316 | superproject.SetQuiet(opt.quiet) | 315 | m.superproject for m in manifest.all_children) |
| 317 | print_messages = git_superproject.PrintMessages(opt.use_superproject, | 316 | if not have_superproject: |
| 318 | self.manifest) | 317 | return |
| 319 | superproject.SetPrintMessages(print_messages) | 318 | |
| 320 | if opt.local_only: | 319 | if opt.local_only: |
| 321 | manifest_path = superproject.manifest_path | 320 | manifest_path = manifest.superproject.manifest_path |
| 322 | if manifest_path: | 321 | if manifest_path: |
| 323 | self._ReloadManifest(manifest_path, manifest, load_local_manifests) | 322 | self._ReloadManifest(manifest_path, manifest) |
| 324 | return manifest_path | 323 | return |
| 325 | 324 | ||
| 326 | all_projects = self.GetProjects(args, | 325 | all_projects = self.GetProjects(args, |
| 327 | missing_ok=True, | 326 | missing_ok=True, |
| 328 | submodules_ok=opt.fetch_submodules) | 327 | submodules_ok=opt.fetch_submodules, |
| 329 | update_result = superproject.UpdateProjectsRevisionId( | 328 | manifest=manifest, |
| 330 | all_projects, git_event_log=self.git_event_log) | 329 | all_manifests=not opt.this_manifest_only) |
| 331 | manifest_path = update_result.manifest_path | 330 | |
| 332 | superproject_logging_data['updatedrevisionid'] = bool(manifest_path) | 331 | per_manifest = collections.defaultdict(list) |
| 333 | if manifest_path: | 332 | manifest_paths = {} |
| 334 | self._ReloadManifest(manifest_path, manifest, load_local_manifests) | 333 | if opt.this_manifest_only: |
| 334 | per_manifest[manifest.path_prefix] = all_projects | ||
| 335 | else: | 335 | else: |
| 336 | if print_messages: | 336 | for p in all_projects: |
| 337 | print('warning: Update of revisionId from superproject has failed, ' | 337 | per_manifest[p.manifest.path_prefix].append(p) |
| 338 | 'repo sync will not use superproject to fetch the source. ', | 338 | |
| 339 | 'Please resync with the --no-use-superproject option to avoid this repo warning.', | 339 | superproject_logging_data = {} |
| 340 | file=sys.stderr) | 340 | need_unload = False |
| 341 | if update_result.fatal and opt.use_superproject is not None: | 341 | for m in self.ManifestList(opt): |
| 342 | sys.exit(1) | 342 | if not m.path_prefix in per_manifest: |
| 343 | return manifest_path | 343 | continue |
| 344 | use_super = git_superproject.UseSuperproject(opt.use_superproject, m) | ||
| 345 | if superproject_logging_data: | ||
| 346 | superproject_logging_data['multimanifest'] = True | ||
| 347 | superproject_logging_data.update( | ||
| 348 | superproject=use_super, | ||
| 349 | haslocalmanifests=bool(m.HasLocalManifests), | ||
| 350 | hassuperprojecttag=bool(m.superproject), | ||
| 351 | ) | ||
| 352 | if use_super and (m.IsMirror or m.IsArchive): | ||
| 353 | # Don't use superproject, because we have no working tree. | ||
| 354 | use_super = False | ||
| 355 | superproject_logging_data['superproject'] = False | ||
| 356 | superproject_logging_data['noworktree'] = True | ||
| 357 | if opt.use_superproject is not False: | ||
| 358 | print(f'{m.path_prefix}: not using superproject because there is no ' | ||
| 359 | 'working tree.') | ||
| 360 | |||
| 361 | if not use_super: | ||
| 362 | continue | ||
| 363 | m.superproject.SetQuiet(opt.quiet) | ||
| 364 | print_messages = git_superproject.PrintMessages(opt.use_superproject, m) | ||
| 365 | m.superproject.SetPrintMessages(print_messages) | ||
| 366 | update_result = m.superproject.UpdateProjectsRevisionId( | ||
| 367 | per_manifest[m.path_prefix], git_event_log=self.git_event_log) | ||
| 368 | manifest_path = update_result.manifest_path | ||
| 369 | superproject_logging_data['updatedrevisionid'] = bool(manifest_path) | ||
| 370 | if manifest_path: | ||
| 371 | m.SetManifestOverride(manifest_path) | ||
| 372 | need_unload = True | ||
| 373 | else: | ||
| 374 | if print_messages: | ||
| 375 | print(f'{m.path_prefix}: warning: Update of revisionId from ' | ||
| 376 | 'superproject has failed, repo sync will not use superproject ' | ||
| 377 | 'to fetch the source. ', | ||
| 378 | 'Please resync with the --no-use-superproject option to avoid ' | ||
| 379 | 'this repo warning.', | ||
| 380 | file=sys.stderr) | ||
| 381 | if update_result.fatal and opt.use_superproject is not None: | ||
| 382 | sys.exit(1) | ||
| 383 | if need_unload: | ||
| 384 | m.outer_client.manifest.Unload() | ||
| 344 | 385 | ||
| 345 | def _FetchProjectList(self, opt, projects): | 386 | def _FetchProjectList(self, opt, projects): |
| 346 | """Main function of the fetch worker. | 387 | """Main function of the fetch worker. |
| @@ -485,8 +526,8 @@ later is required to fix a server side protocol bug. | |||
| 485 | 526 | ||
| 486 | return (ret, fetched) | 527 | return (ret, fetched) |
| 487 | 528 | ||
| 488 | def _FetchMain(self, opt, args, all_projects, err_event, manifest_name, | 529 | def _FetchMain(self, opt, args, all_projects, err_event, |
| 489 | load_local_manifests, ssh_proxy, manifest): | 530 | ssh_proxy, manifest): |
| 490 | """The main network fetch loop. | 531 | """The main network fetch loop. |
| 491 | 532 | ||
| 492 | Args: | 533 | Args: |
| @@ -494,8 +535,6 @@ later is required to fix a server side protocol bug. | |||
| 494 | args: Command line args used to filter out projects. | 535 | args: Command line args used to filter out projects. |
| 495 | all_projects: List of all projects that should be fetched. | 536 | all_projects: List of all projects that should be fetched. |
| 496 | err_event: Whether an error was hit while processing. | 537 | err_event: Whether an error was hit while processing. |
| 497 | manifest_name: Manifest file to be reloaded. | ||
| 498 | load_local_manifests: Whether to load local manifests. | ||
| 499 | ssh_proxy: SSH manager for clients & masters. | 538 | ssh_proxy: SSH manager for clients & masters. |
| 500 | manifest: The manifest to use. | 539 | manifest: The manifest to use. |
| 501 | 540 | ||
| @@ -526,10 +565,12 @@ later is required to fix a server side protocol bug. | |||
| 526 | # Iteratively fetch missing and/or nested unregistered submodules | 565 | # Iteratively fetch missing and/or nested unregistered submodules |
| 527 | previously_missing_set = set() | 566 | previously_missing_set = set() |
| 528 | while True: | 567 | while True: |
| 529 | self._ReloadManifest(manifest_name, self.manifest, load_local_manifests) | 568 | self._ReloadManifest(None, manifest) |
| 530 | all_projects = self.GetProjects(args, | 569 | all_projects = self.GetProjects(args, |
| 531 | missing_ok=True, | 570 | missing_ok=True, |
| 532 | submodules_ok=opt.fetch_submodules) | 571 | submodules_ok=opt.fetch_submodules, |
| 572 | manifest=manifest, | ||
| 573 | all_manifests=not opt.this_manifest_only) | ||
| 533 | missing = [] | 574 | missing = [] |
| 534 | for project in all_projects: | 575 | for project in all_projects: |
| 535 | if project.gitdir not in fetched: | 576 | if project.gitdir not in fetched: |
| @@ -624,7 +665,7 @@ later is required to fix a server side protocol bug. | |||
| 624 | for project in projects: | 665 | for project in projects: |
| 625 | # Make sure pruning never kicks in with shared projects. | 666 | # Make sure pruning never kicks in with shared projects. |
| 626 | if (not project.use_git_worktrees and | 667 | if (not project.use_git_worktrees and |
| 627 | len(project.manifest.GetProjectsWithName(project.name)) > 1): | 668 | len(project.manifest.GetProjectsWithName(project.name, all_manifests=True)) > 1): |
| 628 | if not opt.quiet: | 669 | if not opt.quiet: |
| 629 | print('\r%s: Shared project %s found, disabling pruning.' % | 670 | print('\r%s: Shared project %s found, disabling pruning.' % |
| 630 | (project.relpath, project.name)) | 671 | (project.relpath, project.name)) |
| @@ -698,7 +739,7 @@ later is required to fix a server side protocol bug. | |||
| 698 | t.join() | 739 | t.join() |
| 699 | pm.end() | 740 | pm.end() |
| 700 | 741 | ||
| 701 | def _ReloadManifest(self, manifest_name, manifest, load_local_manifests=True): | 742 | def _ReloadManifest(self, manifest_name, manifest): |
| 702 | """Reload the manfiest from the file specified by the |manifest_name|. | 743 | """Reload the manfiest from the file specified by the |manifest_name|. |
| 703 | 744 | ||
| 704 | It unloads the manifest if |manifest_name| is None. | 745 | It unloads the manifest if |manifest_name| is None. |
| @@ -706,17 +747,29 @@ later is required to fix a server side protocol bug. | |||
| 706 | Args: | 747 | Args: |
| 707 | manifest_name: Manifest file to be reloaded. | 748 | manifest_name: Manifest file to be reloaded. |
| 708 | manifest: The manifest to use. | 749 | manifest: The manifest to use. |
| 709 | load_local_manifests: Whether to load local manifests. | ||
| 710 | """ | 750 | """ |
| 711 | if manifest_name: | 751 | if manifest_name: |
| 712 | # Override calls Unload already | 752 | # Override calls Unload already |
| 713 | manifest.Override(manifest_name, load_local_manifests=load_local_manifests) | 753 | manifest.Override(manifest_name) |
| 714 | else: | 754 | else: |
| 715 | manifest.Unload() | 755 | manifest.Unload() |
| 716 | 756 | ||
| 717 | def UpdateProjectList(self, opt, manifest): | 757 | def UpdateProjectList(self, opt, manifest): |
| 758 | """Update the cached projects list for |manifest| | ||
| 759 | |||
| 760 | In a multi-manifest checkout, each manifest has its own project.list. | ||
| 761 | |||
| 762 | Args: | ||
| 763 | opt: Program options returned from optparse. See _Options(). | ||
| 764 | manifest: The manifest to use. | ||
| 765 | |||
| 766 | Returns: | ||
| 767 | 0: success | ||
| 768 | 1: failure | ||
| 769 | """ | ||
| 718 | new_project_paths = [] | 770 | new_project_paths = [] |
| 719 | for project in self.GetProjects(None, missing_ok=True): | 771 | for project in self.GetProjects(None, missing_ok=True, manifest=manifest, |
| 772 | all_manifests=False): | ||
| 720 | if project.relpath: | 773 | if project.relpath: |
| 721 | new_project_paths.append(project.relpath) | 774 | new_project_paths.append(project.relpath) |
| 722 | file_name = 'project.list' | 775 | file_name = 'project.list' |
| @@ -766,7 +819,8 @@ later is required to fix a server side protocol bug. | |||
| 766 | new_paths = {} | 819 | new_paths = {} |
| 767 | new_linkfile_paths = [] | 820 | new_linkfile_paths = [] |
| 768 | new_copyfile_paths = [] | 821 | new_copyfile_paths = [] |
| 769 | for project in self.GetProjects(None, missing_ok=True): | 822 | for project in self.GetProjects(None, missing_ok=True, |
| 823 | manifest=manifest, all_manifests=False): | ||
| 770 | new_linkfile_paths.extend(x.dest for x in project.linkfiles) | 824 | new_linkfile_paths.extend(x.dest for x in project.linkfiles) |
| 771 | new_copyfile_paths.extend(x.dest for x in project.copyfiles) | 825 | new_copyfile_paths.extend(x.dest for x in project.copyfiles) |
| 772 | 826 | ||
| @@ -897,8 +951,40 @@ later is required to fix a server side protocol bug. | |||
| 897 | 951 | ||
| 898 | return manifest_name | 952 | return manifest_name |
| 899 | 953 | ||
| 954 | def _UpdateAllManifestProjects(self, opt, mp, manifest_name): | ||
| 955 | """Fetch & update the local manifest project. | ||
| 956 | |||
| 957 | After syncing the manifest project, if the manifest has any sub manifests, | ||
| 958 | those are recursively processed. | ||
| 959 | |||
| 960 | Args: | ||
| 961 | opt: Program options returned from optparse. See _Options(). | ||
| 962 | mp: the manifestProject to query. | ||
| 963 | manifest_name: Manifest file to be reloaded. | ||
| 964 | """ | ||
| 965 | if not mp.standalone_manifest_url: | ||
| 966 | self._UpdateManifestProject(opt, mp, manifest_name) | ||
| 967 | |||
| 968 | if mp.manifest.submanifests: | ||
| 969 | for submanifest in mp.manifest.submanifests.values(): | ||
| 970 | child = submanifest.repo_client.manifest | ||
| 971 | child.manifestProject.SyncWithPossibleInit( | ||
| 972 | submanifest, | ||
| 973 | current_branch_only=self._GetCurrentBranchOnly(opt, child), | ||
| 974 | verbose=opt.verbose, | ||
| 975 | tags=opt.tags, | ||
| 976 | git_event_log=self.git_event_log, | ||
| 977 | ) | ||
| 978 | self._UpdateAllManifestProjects(opt, child.manifestProject, None) | ||
| 979 | |||
| 900 | def _UpdateManifestProject(self, opt, mp, manifest_name): | 980 | def _UpdateManifestProject(self, opt, mp, manifest_name): |
| 901 | """Fetch & update the local manifest project.""" | 981 | """Fetch & update the local manifest project. |
| 982 | |||
| 983 | Args: | ||
| 984 | opt: Program options returned from optparse. See _Options(). | ||
| 985 | mp: the manifestProject to query. | ||
| 986 | manifest_name: Manifest file to be reloaded. | ||
| 987 | """ | ||
| 902 | if not opt.local_only: | 988 | if not opt.local_only: |
| 903 | start = time.time() | 989 | start = time.time() |
| 904 | success = mp.Sync_NetworkHalf(quiet=opt.quiet, verbose=opt.verbose, | 990 | success = mp.Sync_NetworkHalf(quiet=opt.quiet, verbose=opt.verbose, |
| @@ -924,6 +1010,7 @@ later is required to fix a server side protocol bug. | |||
| 924 | if not clean: | 1010 | if not clean: |
| 925 | sys.exit(1) | 1011 | sys.exit(1) |
| 926 | self._ReloadManifest(manifest_name, mp.manifest) | 1012 | self._ReloadManifest(manifest_name, mp.manifest) |
| 1013 | |||
| 927 | if opt.jobs is None: | 1014 | if opt.jobs is None: |
| 928 | self.jobs = mp.manifest.default.sync_j | 1015 | self.jobs = mp.manifest.default.sync_j |
| 929 | 1016 | ||
| @@ -948,9 +1035,6 @@ later is required to fix a server side protocol bug. | |||
| 948 | if opt.prune is None: | 1035 | if opt.prune is None: |
| 949 | opt.prune = True | 1036 | opt.prune = True |
| 950 | 1037 | ||
| 951 | if self.outer_client.manifest.is_multimanifest and not opt.this_manifest_only and args: | ||
| 952 | self.OptionParser.error('partial syncs must use --this-manifest-only') | ||
| 953 | |||
| 954 | def Execute(self, opt, args): | 1038 | def Execute(self, opt, args): |
| 955 | if opt.jobs: | 1039 | if opt.jobs: |
| 956 | self.jobs = opt.jobs | 1040 | self.jobs = opt.jobs |
| @@ -959,7 +1043,7 @@ later is required to fix a server side protocol bug. | |||
| 959 | self.jobs = min(self.jobs, (soft_limit - 5) // 3) | 1043 | self.jobs = min(self.jobs, (soft_limit - 5) // 3) |
| 960 | 1044 | ||
| 961 | manifest = self.outer_manifest | 1045 | manifest = self.outer_manifest |
| 962 | if opt.this_manifest_only or not opt.outer_manifest: | 1046 | if not opt.outer_manifest: |
| 963 | manifest = self.manifest | 1047 | manifest = self.manifest |
| 964 | 1048 | ||
| 965 | if opt.manifest_name: | 1049 | if opt.manifest_name: |
| @@ -994,39 +1078,26 @@ later is required to fix a server side protocol bug. | |||
| 994 | 'receive updates; run `repo init --repo-rev=stable` to fix.', | 1078 | 'receive updates; run `repo init --repo-rev=stable` to fix.', |
| 995 | file=sys.stderr) | 1079 | file=sys.stderr) |
| 996 | 1080 | ||
| 997 | mp = manifest.manifestProject | 1081 | for m in self.ManifestList(opt): |
| 998 | is_standalone_manifest = bool(mp.standalone_manifest_url) | 1082 | mp = m.manifestProject |
| 999 | if not is_standalone_manifest: | 1083 | is_standalone_manifest = bool(mp.standalone_manifest_url) |
| 1000 | mp.PreSync() | 1084 | if not is_standalone_manifest: |
| 1085 | mp.PreSync() | ||
| 1001 | 1086 | ||
| 1002 | if opt.repo_upgraded: | 1087 | if opt.repo_upgraded: |
| 1003 | _PostRepoUpgrade(manifest, quiet=opt.quiet) | 1088 | _PostRepoUpgrade(m, quiet=opt.quiet) |
| 1004 | 1089 | ||
| 1005 | if not opt.mp_update: | 1090 | if opt.mp_update: |
| 1091 | self._UpdateAllManifestProjects(opt, mp, manifest_name) | ||
| 1092 | else: | ||
| 1006 | print('Skipping update of local manifest project.') | 1093 | print('Skipping update of local manifest project.') |
| 1007 | elif not is_standalone_manifest: | ||
| 1008 | self._UpdateManifestProject(opt, mp, manifest_name) | ||
| 1009 | 1094 | ||
| 1010 | load_local_manifests = not manifest.HasLocalManifests | 1095 | superproject_logging_data = {} |
| 1011 | use_superproject = git_superproject.UseSuperproject(opt.use_superproject, manifest) | 1096 | self._UpdateProjectsRevisionId(opt, args, superproject_logging_data, |
| 1012 | if use_superproject and (manifest.IsMirror or manifest.IsArchive): | 1097 | manifest) |
| 1013 | # Don't use superproject, because we have no working tree. | ||
| 1014 | use_superproject = False | ||
| 1015 | if opt.use_superproject is not None: | ||
| 1016 | print('Defaulting to no-use-superproject because there is no working tree.') | ||
| 1017 | superproject_logging_data = { | ||
| 1018 | 'superproject': use_superproject, | ||
| 1019 | 'haslocalmanifests': bool(manifest.HasLocalManifests), | ||
| 1020 | 'hassuperprojecttag': bool(manifest.superproject), | ||
| 1021 | } | ||
| 1022 | if use_superproject: | ||
| 1023 | manifest_name = self._UpdateProjectsRevisionId( | ||
| 1024 | opt, args, load_local_manifests, superproject_logging_data, | ||
| 1025 | manifest) or opt.manifest_name | ||
| 1026 | 1098 | ||
| 1027 | if self.gitc_manifest: | 1099 | if self.gitc_manifest: |
| 1028 | gitc_manifest_projects = self.GetProjects(args, | 1100 | gitc_manifest_projects = self.GetProjects(args, missing_ok=True) |
| 1029 | missing_ok=True) | ||
| 1030 | gitc_projects = [] | 1101 | gitc_projects = [] |
| 1031 | opened_projects = [] | 1102 | opened_projects = [] |
| 1032 | for project in gitc_manifest_projects: | 1103 | for project in gitc_manifest_projects: |
| @@ -1059,9 +1130,12 @@ later is required to fix a server side protocol bug. | |||
| 1059 | for path in opened_projects] | 1130 | for path in opened_projects] |
| 1060 | if not args: | 1131 | if not args: |
| 1061 | return | 1132 | return |
| 1133 | |||
| 1062 | all_projects = self.GetProjects(args, | 1134 | all_projects = self.GetProjects(args, |
| 1063 | missing_ok=True, | 1135 | missing_ok=True, |
| 1064 | submodules_ok=opt.fetch_submodules) | 1136 | submodules_ok=opt.fetch_submodules, |
| 1137 | manifest=manifest, | ||
| 1138 | all_manifests=not opt.this_manifest_only) | ||
| 1065 | 1139 | ||
| 1066 | err_network_sync = False | 1140 | err_network_sync = False |
| 1067 | err_update_projects = False | 1141 | err_update_projects = False |
| @@ -1073,7 +1147,6 @@ later is required to fix a server side protocol bug. | |||
| 1073 | # Initialize the socket dir once in the parent. | 1147 | # Initialize the socket dir once in the parent. |
| 1074 | ssh_proxy.sock() | 1148 | ssh_proxy.sock() |
| 1075 | all_projects = self._FetchMain(opt, args, all_projects, err_event, | 1149 | all_projects = self._FetchMain(opt, args, all_projects, err_event, |
| 1076 | manifest_name, load_local_manifests, | ||
| 1077 | ssh_proxy, manifest) | 1150 | ssh_proxy, manifest) |
| 1078 | 1151 | ||
| 1079 | if opt.network_only: | 1152 | if opt.network_only: |
| @@ -1090,23 +1163,24 @@ later is required to fix a server side protocol bug. | |||
| 1090 | file=sys.stderr) | 1163 | file=sys.stderr) |
| 1091 | sys.exit(1) | 1164 | sys.exit(1) |
| 1092 | 1165 | ||
| 1093 | if manifest.IsMirror or manifest.IsArchive: | 1166 | for m in self.ManifestList(opt): |
| 1094 | # bail out now, we have no working tree | 1167 | if m.IsMirror or m.IsArchive: |
| 1095 | return | 1168 | # bail out now, we have no working tree |
| 1169 | continue | ||
| 1096 | 1170 | ||
| 1097 | if self.UpdateProjectList(opt, manifest): | 1171 | if self.UpdateProjectList(opt, m): |
| 1098 | err_event.set() | 1172 | err_event.set() |
| 1099 | err_update_projects = True | 1173 | err_update_projects = True |
| 1100 | if opt.fail_fast: | 1174 | if opt.fail_fast: |
| 1101 | print('\nerror: Local checkouts *not* updated.', file=sys.stderr) | 1175 | print('\nerror: Local checkouts *not* updated.', file=sys.stderr) |
| 1102 | sys.exit(1) | 1176 | sys.exit(1) |
| 1103 | 1177 | ||
| 1104 | err_update_linkfiles = not self.UpdateCopyLinkfileList(manifest) | 1178 | err_update_linkfiles = not self.UpdateCopyLinkfileList(m) |
| 1105 | if err_update_linkfiles: | 1179 | if err_update_linkfiles: |
| 1106 | err_event.set() | 1180 | err_event.set() |
| 1107 | if opt.fail_fast: | 1181 | if opt.fail_fast: |
| 1108 | print('\nerror: Local update copyfile or linkfile failed.', file=sys.stderr) | 1182 | print('\nerror: Local update copyfile or linkfile failed.', file=sys.stderr) |
| 1109 | sys.exit(1) | 1183 | sys.exit(1) |
| 1110 | 1184 | ||
| 1111 | err_results = [] | 1185 | err_results = [] |
| 1112 | # NB: We don't exit here because this is the last step. | 1186 | # NB: We don't exit here because this is the last step. |
| @@ -1114,10 +1188,14 @@ later is required to fix a server side protocol bug. | |||
| 1114 | if err_checkout: | 1188 | if err_checkout: |
| 1115 | err_event.set() | 1189 | err_event.set() |
| 1116 | 1190 | ||
| 1117 | # If there's a notice that's supposed to print at the end of the sync, print | 1191 | printed_notices = set() |
| 1118 | # it now... | 1192 | # If there's a notice that's supposed to print at the end of the sync, |
| 1119 | if manifest.notice: | 1193 | # print it now... But avoid printing duplicate messages, and preserve |
| 1120 | print(manifest.notice) | 1194 | # order. |
| 1195 | for m in sorted(self.ManifestList(opt), key=lambda x: x.path_prefix): | ||
| 1196 | if m.notice and m.notice not in printed_notices: | ||
| 1197 | print(m.notice) | ||
| 1198 | printed_notices.add(m.notice) | ||
| 1121 | 1199 | ||
| 1122 | # If we saw an error, exit with code 1 so that other scripts can check. | 1200 | # If we saw an error, exit with code 1 so that other scripts can check. |
| 1123 | if err_event.is_set(): | 1201 | if err_event.is_set(): |
