diff options
-rw-r--r-- | command.py | 11 | ||||
-rwxr-xr-x | main.py | 3 | ||||
-rw-r--r-- | project.py | 61 | ||||
-rw-r--r-- | subcmds/init.py | 5 | ||||
-rw-r--r-- | subcmds/sync.py | 274 |
5 files changed, 247 insertions, 107 deletions
@@ -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: |
@@ -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: |
@@ -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 | ||
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(): |