summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaMont Jones <lamontjones@google.com>2022-04-11 22:50:11 +0000
committerLaMont Jones <lamontjones@google.com>2022-05-26 00:03:37 +0000
commitbdcba7dc36f1c8e6041681eb5b3b5229c93c7c5c (patch)
treeef0dbd149d7e5cd35c4d007a5052ba42bcc1c881
parent1d00a7e2ae64b6c08aff60c2e7ed5c2d89caf8d6 (diff)
downloadgit-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>
-rw-r--r--command.py11
-rwxr-xr-xmain.py3
-rw-r--r--project.py61
-rw-r--r--subcmds/init.py5
-rw-r--r--subcmds/sync.py274
5 files changed, 247 insertions, 107 deletions
diff --git a/command.py b/command.py
index 12fe4172..bd6d0817 100644
--- a/command.py
+++ b/command.py
@@ -144,11 +144,10 @@ class Command(object):
144 help=f'number of jobs to run in parallel (default: {default})') 144 help=f'number of jobs to run in parallel (default: {default})')
145 145
146 m = p.add_option_group('Multi-manifest options') 146 m = p.add_option_group('Multi-manifest options')
147 m.add_option('--outer-manifest', action='store_true', 147 m.add_option('--outer-manifest', action='store_true', default=None,
148 help='operate starting at the outermost manifest') 148 help='operate starting at the outermost manifest')
149 m.add_option('--no-outer-manifest', dest='outer_manifest', 149 m.add_option('--no-outer-manifest', dest='outer_manifest',
150 action='store_false', default=None, 150 action='store_false', help='do not operate on outer manifests')
151 help='do not operate on outer manifests')
152 m.add_option('--this-manifest-only', action='store_true', default=None, 151 m.add_option('--this-manifest-only', action='store_true', default=None,
153 help='only operate on this (sub)manifest') 152 help='only operate on this (sub)manifest')
154 m.add_option('--no-this-manifest-only', '--all-manifests', 153 m.add_option('--no-this-manifest-only', '--all-manifests',
@@ -186,6 +185,10 @@ class Command(object):
186 """Validate common options.""" 185 """Validate common options."""
187 opt.quiet = opt.output_mode is False 186 opt.quiet = opt.output_mode is False
188 opt.verbose = opt.output_mode is True 187 opt.verbose = opt.output_mode is True
188 if opt.outer_manifest is None:
189 # By default, treat multi-manifest instances as a single manifest from
190 # the user's perspective.
191 opt.outer_manifest = True
189 192
190 def ValidateOptions(self, opt, args): 193 def ValidateOptions(self, opt, args):
191 """Validate the user options & arguments before executing. 194 """Validate the user options & arguments before executing.
@@ -385,7 +388,7 @@ class Command(object):
385 opt: The command options. 388 opt: The command options.
386 """ 389 """
387 top = self.outer_manifest 390 top = self.outer_manifest
388 if opt.outer_manifest is False or opt.this_manifest_only: 391 if not opt.outer_manifest or opt.this_manifest_only:
389 top = self.manifest 392 top = self.manifest
390 yield top 393 yield top
391 if not opt.this_manifest_only: 394 if not opt.this_manifest_only:
diff --git a/main.py b/main.py
index 34dfb777..c54f9281 100755
--- a/main.py
+++ b/main.py
@@ -294,8 +294,7 @@ class _Repo(object):
294 cmd.ValidateOptions(copts, cargs) 294 cmd.ValidateOptions(copts, cargs)
295 295
296 this_manifest_only = copts.this_manifest_only 296 this_manifest_only = copts.this_manifest_only
297 # If not specified, default to using the outer manifest. 297 outer_manifest = copts.outer_manifest
298 outer_manifest = copts.outer_manifest is not False
299 if cmd.MULTI_MANIFEST_SUPPORT or this_manifest_only: 298 if cmd.MULTI_MANIFEST_SUPPORT or this_manifest_only:
300 result = cmd.Execute(copts, cargs) 299 result = cmd.Execute(copts, cargs)
301 elif outer_manifest and repo_client.manifest.is_submanifest: 300 elif outer_manifest and repo_client.manifest.is_submanifest:
diff --git a/project.py b/project.py
index faa6b32b..8668bae9 100644
--- a/project.py
+++ b/project.py
@@ -3467,6 +3467,67 @@ class ManifestProject(MetaProject):
3467 """Return the name of the platform.""" 3467 """Return the name of the platform."""
3468 return platform.system().lower() 3468 return platform.system().lower()
3469 3469
3470 def SyncWithPossibleInit(self, submanifest, verbose=False,
3471 current_branch_only=False, tags='', git_event_log=None):
3472 """Sync a manifestProject, possibly for the first time.
3473
3474 Call Sync() with arguments from the most recent `repo init`. If this is a
3475 new sub manifest, then inherit options from the parent's manifestProject.
3476
3477 This is used by subcmds.Sync() to do an initial download of new sub
3478 manifests.
3479
3480 Args:
3481 submanifest: an XmlSubmanifest, the submanifest to re-sync.
3482 verbose: a boolean, whether to show all output, rather than only errors.
3483 current_branch_only: a boolean, whether to only fetch the current manifest
3484 branch from the server.
3485 tags: a boolean, whether to fetch tags.
3486 git_event_log: an EventLog, for git tracing.
3487 """
3488 # TODO(lamontjones): when refactoring sync (and init?) consider how to
3489 # better get the init options that we should use when syncing uncovers a new
3490 # submanifest.
3491 git_event_log = git_event_log or EventLog()
3492 spec = submanifest.ToSubmanifestSpec()
3493 # Use the init options from the existing manifestProject, or the parent if
3494 # it doesn't exist.
3495 #
3496 # Today, we only support changing manifest_groups on the sub-manifest, with
3497 # no supported-for-the-user way to change the other arguments from those
3498 # specified by the outermost manifest.
3499 #
3500 # TODO(lamontjones): determine which of these should come from the outermost
3501 # manifest and which should come from the parent manifest.
3502 mp = self if self.Exists else submanifest.parent.manifestProject
3503 return self.Sync(
3504 manifest_url=spec.manifestUrl,
3505 manifest_branch=spec.revision,
3506 standalone_manifest=mp.standalone_manifest_url,
3507 groups=mp.manifest_groups,
3508 platform=mp.manifest_platform,
3509 mirror=mp.mirror,
3510 dissociate=mp.dissociate,
3511 reference=mp.reference,
3512 worktree=mp.use_worktree,
3513 submodules=mp.submodules,
3514 archive=mp.archive,
3515 partial_clone=mp.partial_clone,
3516 clone_filter=mp.clone_filter,
3517 partial_clone_exclude=mp.partial_clone_exclude,
3518 clone_bundle=mp.clone_bundle,
3519 git_lfs=mp.git_lfs,
3520 use_superproject=mp.use_superproject,
3521 verbose=verbose,
3522 current_branch_only=current_branch_only,
3523 tags=tags,
3524 depth=mp.depth,
3525 git_event_log=git_event_log,
3526 manifest_name=spec.manifestName,
3527 this_manifest_only=True,
3528 outer_manifest=False,
3529 )
3530
3470 def Sync(self, _kwargs_only=(), manifest_url='', manifest_branch=None, 3531 def Sync(self, _kwargs_only=(), manifest_url='', manifest_branch=None,
3471 standalone_manifest=False, groups='', mirror=False, reference='', 3532 standalone_manifest=False, groups='', mirror=False, reference='',
3472 dissociate=False, worktree=False, submodules=False, archive=False, 3533 dissociate=False, worktree=False, submodules=False, archive=False,
diff --git a/subcmds/init.py b/subcmds/init.py
index 6e3951c9..cced44d5 100644
--- a/subcmds/init.py
+++ b/subcmds/init.py
@@ -89,11 +89,10 @@ to update the working directory files.
89 def _Options(self, p, gitc_init=False): 89 def _Options(self, p, gitc_init=False):
90 Wrapper().InitParser(p, gitc_init=gitc_init) 90 Wrapper().InitParser(p, gitc_init=gitc_init)
91 m = p.add_option_group('Multi-manifest') 91 m = p.add_option_group('Multi-manifest')
92 m.add_option('--outer-manifest', action='store_true', 92 m.add_option('--outer-manifest', action='store_true', default=True,
93 help='operate starting at the outermost manifest') 93 help='operate starting at the outermost manifest')
94 m.add_option('--no-outer-manifest', dest='outer_manifest', 94 m.add_option('--no-outer-manifest', dest='outer_manifest',
95 action='store_false', default=None, 95 action='store_false', help='do not operate on outer manifests')
96 help='do not operate on outer manifests')
97 m.add_option('--this-manifest-only', action='store_true', default=None, 96 m.add_option('--this-manifest-only', action='store_true', default=None,
98 help='only operate on this (sub)manifest') 97 help='only operate on this (sub)manifest')
99 m.add_option('--no-this-manifest-only', '--all-manifests', 98 m.add_option('--no-this-manifest-only', '--all-manifests',
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
15import collections
15import functools 16import functools
16import http.cookiejar as cookielib 17import http.cookiejar as cookielib
17import io 18import io
@@ -66,7 +67,7 @@ _ONE_DAY_S = 24 * 60 * 60
66class Sync(Command, MirrorSafeCommand): 67class 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():