init: add multi-manifest support
This moves more of the manifest project handling into ManifestProject.
Change-Id: Iecdafbec18cccdfd8e625753c3bd1bcddf2b227f
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/334520
Tested-by: LaMont Jones <lamontjones@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
diff --git a/project.py b/project.py
index 2989e09..6d8784e 100644
--- a/project.py
+++ b/project.py
@@ -34,7 +34,8 @@
ID_RE
from error import GitError, UploadError, DownloadError
from error import ManifestInvalidRevisionError, ManifestInvalidPathError
-from error import NoManifestException
+from error import NoManifestException, ManifestParseError
+import git_superproject
import platform_utils
import progress
from repo_trace import IsTrace, Trace
@@ -3443,7 +3444,8 @@
partial_clone=None, depth=None, clone_filter='blob:none',
partial_clone_exclude=None, clone_bundle=None, git_lfs=None,
use_superproject=None, verbose=False, current_branch_only=False,
- platform='', tags=''):
+ platform='', tags='', manifest_name='default.xml',
+ this_manifest_only=False, outer_manifest=True):
"""Sync the manifest and all submanifests.
Args:
@@ -3477,12 +3479,45 @@
platform: a string, restrict the checkout to projects with the specified
platform group.
tags: a boolean, whether to fetch tags.,
+ manifest_name: a string, the name of the manifest file to use.
+ this_manifest_only: a boolean, whether to only operate on the current sub
+ manifest.
+ outer_manifest: a boolean, whether to start at the outermost manifest.
Returns:
a boolean, whether the sync was successful.
"""
assert _kwargs_only == (), 'Sync only accepts keyword arguments.'
+ if outer_manifest and self.manifest.is_submanifest:
+ # In a multi-manifest checkout, use the outer manifest unless we are told
+ # not to.
+ return self.client.outer_manifest.manifestProject.Sync(
+ manifest_url=manifest_url,
+ manifest_branch=manifest_branch,
+ standalone_manifest=standalone_manifest,
+ groups=groups,
+ platform=platform,
+ mirror=mirror,
+ dissociate=dissociate,
+ reference=reference,
+ worktree=worktree,
+ submodules=submodules,
+ archive=archive,
+ partial_clone=partial_clone,
+ clone_filter=clone_filter,
+ partial_clone_exclude=partial_clone_exclude,
+ clone_bundle=clone_bundle,
+ git_lfs=git_lfs,
+ use_superproject=use_superproject,
+ verbose=verbose,
+ current_branch_only=current_branch_only,
+ tags=tags,
+ depth=depth,
+ manifest_name=manifest_name,
+ this_manifest_only=this_manifest_only,
+ outer_manifest=False)
+
# If repo has already been initialized, we take -u with the absence of
# --standalone-manifest to mean "transition to a standard repo set up",
# which necessitates starting fresh.
@@ -3508,7 +3543,7 @@
print('fatal: manifest url is required.', file=sys.stderr)
return False
- if not quiet:
+ if verbose:
print('Downloading manifest from %s' %
(GitConfig.ForUser().UrlInsteadOf(manifest_url),),
file=sys.stderr)
@@ -3700,6 +3735,65 @@
print('fatal: cannot create default in manifest', file=sys.stderr)
return False
+ if not manifest_name:
+ print('fatal: manifest name (-m) is required.', file=sys.stderr)
+ return False
+
+ try:
+ self.manifest.Link(manifest_name)
+ except ManifestParseError as e:
+ print("fatal: manifest '%s' not available" % manifest_name,
+ file=sys.stderr)
+ print('fatal: %s' % str(e), file=sys.stderr)
+ return False
+
+ # Lastly, clone the superproject.
+ superproject = git_superproject.Superproject(self.manifest,
+ self.repodir,
+ self.git_event_log,
+ quiet=not verbose)
+ sync_result = superproject.Sync()
+ if not sync_result.success:
+ print('warning: git update of superproject failed, repo sync will not '
+ 'use superproject to fetch source; while this error is not fatal, '
+ 'and you can continue to run repo sync, please run repo init with '
+ 'the --no-use-superproject option to stop seeing this warning',
+ file=sys.stderr)
+ if sync_result.fatal and use_superproject is not None:
+ return False
+
+ if this_manifest_only:
+ return True
+
+ for submanifest in self.manifest.submanifests.values():
+ spec = submanifest.ToSubmanifestSpec(root=self.manifest.outer_client)
+ submanifest.repo_client.manifestProject.Sync(
+ manifest_url=spec.manifestUrl,
+ manifest_branch=spec.revision,
+ standalone_manifest=standalone_manifest,
+ groups=self.manifest_groups,
+ platform=platform,
+ mirror=mirror,
+ dissociate=dissociate,
+ reference=reference,
+ worktree=worktree,
+ submodules=submodules,
+ archive=archive,
+ partial_clone=partial_clone,
+ clone_filter=clone_filter,
+ partial_clone_exclude=partial_clone_exclude,
+ clone_bundle=clone_bundle,
+ git_lfs=git_lfs,
+ use_superproject=use_superproject,
+ verbose=verbose,
+ current_branch_only=current_branch_only,
+ tags=tags,
+ depth=depth,
+ manifest_name=spec.manifestName,
+ this_manifest_only=False,
+ outer_manifest=False,
+ )
+
return True
def _ConfigureDepth(self, depth):
diff --git a/subcmds/init.py b/subcmds/init.py
index 13085fa..2cb3ff3 100644
--- a/subcmds/init.py
+++ b/subcmds/init.py
@@ -32,7 +32,7 @@
class Init(InteractiveCommand, MirrorSafeCommand):
COMMON = True
- MULTI_MANIFEST_SUPPORT = False
+ MULTI_MANIFEST_SUPPORT = True
helpSummary = "Initialize a repo client checkout in the current directory"
helpUsage = """
%prog [options] [manifest url]
@@ -107,26 +107,6 @@
return {'REPO_MANIFEST_URL': 'manifest_url',
'REPO_MIRROR_LOCATION': 'reference'}
- def _CloneSuperproject(self, opt):
- """Clone the superproject based on the superproject's url and branch.
-
- Args:
- opt: Program options returned from optparse. See _Options().
- """
- superproject = git_superproject.Superproject(self.manifest,
- self.repodir,
- self.git_event_log,
- quiet=opt.quiet)
- sync_result = superproject.Sync()
- if not sync_result.success:
- print('warning: git update of superproject failed, repo sync will not '
- 'use superproject to fetch source; while this error is not fatal, '
- 'and you can continue to run repo sync, please run repo init with '
- 'the --no-use-superproject option to stop seeing this warning',
- file=sys.stderr)
- if sync_result.fatal and opt.use_superproject is not None:
- sys.exit(1)
-
def _SyncManifest(self, opt):
"""Call manifestProject.Sync with arguments from opt.
@@ -154,19 +134,8 @@
verbose=opt.verbose,
current_branch_only=opt.current_branch_only,
tags=opt.tags,
- depth=opt.depth):
- sys.exit(1)
-
- def _LinkManifest(self, name):
- if not name:
- print('fatal: manifest name (-m) is required.', file=sys.stderr)
- sys.exit(1)
-
- try:
- self.manifest.Link(name)
- except ManifestParseError as e:
- print("fatal: manifest '%s' not available" % name, file=sys.stderr)
- print('fatal: %s' % str(e), file=sys.stderr)
+ depth=opt.depth,
+ manifest_name=opt.manifest_name):
sys.exit(1)
def _Prompt(self, prompt, value):
@@ -343,10 +312,6 @@
git_require((2, 15, 0), fail=True, msg='git gc worktree corruption')
self._SyncManifest(opt)
- self._LinkManifest(opt.manifest_name)
-
- if self.manifest.manifestProject.use_superproject:
- self._CloneSuperproject(opt)
if os.isatty(0) and os.isatty(1) and not self.manifest.IsMirror:
if opt.config_name or self._ShouldConfigureUser(opt):