diff options
author | LaMont Jones <lamontjones@google.com> | 2022-04-05 21:21:56 +0000 |
---|---|---|
committer | LaMont Jones <lamontjones@google.com> | 2022-04-06 17:02:40 +0000 |
commit | 409407a73172b31efcee947db66ae099515eeaab (patch) | |
tree | e050cf2c69364be9642e2e2fd9a611caf97efb3d | |
parent | d82be3e672986cf1b490248a0ae4e6e42ec6fbd3 (diff) | |
download | git-repo-409407a73172b31efcee947db66ae099515eeaab.tar.gz |
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>
-rw-r--r-- | project.py | 100 | ||||
-rw-r--r-- | subcmds/init.py | 41 |
2 files changed, 100 insertions, 41 deletions
@@ -34,7 +34,8 @@ from git_config import GitConfig, IsId, GetSchemeFromUrl, GetUrlCookieFile, \ | |||
34 | ID_RE | 34 | ID_RE |
35 | from error import GitError, UploadError, DownloadError | 35 | from error import GitError, UploadError, DownloadError |
36 | from error import ManifestInvalidRevisionError, ManifestInvalidPathError | 36 | from error import ManifestInvalidRevisionError, ManifestInvalidPathError |
37 | from error import NoManifestException | 37 | from error import NoManifestException, ManifestParseError |
38 | import git_superproject | ||
38 | import platform_utils | 39 | import platform_utils |
39 | import progress | 40 | import progress |
40 | from repo_trace import IsTrace, Trace | 41 | from repo_trace import IsTrace, Trace |
@@ -3443,7 +3444,8 @@ class ManifestProject(MetaProject): | |||
3443 | partial_clone=None, depth=None, clone_filter='blob:none', | 3444 | partial_clone=None, depth=None, clone_filter='blob:none', |
3444 | partial_clone_exclude=None, clone_bundle=None, git_lfs=None, | 3445 | partial_clone_exclude=None, clone_bundle=None, git_lfs=None, |
3445 | use_superproject=None, verbose=False, current_branch_only=False, | 3446 | use_superproject=None, verbose=False, current_branch_only=False, |
3446 | platform='', tags=''): | 3447 | platform='', tags='', manifest_name='default.xml', |
3448 | this_manifest_only=False, outer_manifest=True): | ||
3447 | """Sync the manifest and all submanifests. | 3449 | """Sync the manifest and all submanifests. |
3448 | 3450 | ||
3449 | Args: | 3451 | Args: |
@@ -3477,12 +3479,45 @@ class ManifestProject(MetaProject): | |||
3477 | platform: a string, restrict the checkout to projects with the specified | 3479 | platform: a string, restrict the checkout to projects with the specified |
3478 | platform group. | 3480 | platform group. |
3479 | tags: a boolean, whether to fetch tags., | 3481 | tags: a boolean, whether to fetch tags., |
3482 | manifest_name: a string, the name of the manifest file to use. | ||
3483 | this_manifest_only: a boolean, whether to only operate on the current sub | ||
3484 | manifest. | ||
3485 | outer_manifest: a boolean, whether to start at the outermost manifest. | ||
3480 | 3486 | ||
3481 | Returns: | 3487 | Returns: |
3482 | a boolean, whether the sync was successful. | 3488 | a boolean, whether the sync was successful. |
3483 | """ | 3489 | """ |
3484 | assert _kwargs_only == (), 'Sync only accepts keyword arguments.' | 3490 | assert _kwargs_only == (), 'Sync only accepts keyword arguments.' |
3485 | 3491 | ||
3492 | if outer_manifest and self.manifest.is_submanifest: | ||
3493 | # In a multi-manifest checkout, use the outer manifest unless we are told | ||
3494 | # not to. | ||
3495 | return self.client.outer_manifest.manifestProject.Sync( | ||
3496 | manifest_url=manifest_url, | ||
3497 | manifest_branch=manifest_branch, | ||
3498 | standalone_manifest=standalone_manifest, | ||
3499 | groups=groups, | ||
3500 | platform=platform, | ||
3501 | mirror=mirror, | ||
3502 | dissociate=dissociate, | ||
3503 | reference=reference, | ||
3504 | worktree=worktree, | ||
3505 | submodules=submodules, | ||
3506 | archive=archive, | ||
3507 | partial_clone=partial_clone, | ||
3508 | clone_filter=clone_filter, | ||
3509 | partial_clone_exclude=partial_clone_exclude, | ||
3510 | clone_bundle=clone_bundle, | ||
3511 | git_lfs=git_lfs, | ||
3512 | use_superproject=use_superproject, | ||
3513 | verbose=verbose, | ||
3514 | current_branch_only=current_branch_only, | ||
3515 | tags=tags, | ||
3516 | depth=depth, | ||
3517 | manifest_name=manifest_name, | ||
3518 | this_manifest_only=this_manifest_only, | ||
3519 | outer_manifest=False) | ||
3520 | |||
3486 | # If repo has already been initialized, we take -u with the absence of | 3521 | # If repo has already been initialized, we take -u with the absence of |
3487 | # --standalone-manifest to mean "transition to a standard repo set up", | 3522 | # --standalone-manifest to mean "transition to a standard repo set up", |
3488 | # which necessitates starting fresh. | 3523 | # which necessitates starting fresh. |
@@ -3508,7 +3543,7 @@ class ManifestProject(MetaProject): | |||
3508 | print('fatal: manifest url is required.', file=sys.stderr) | 3543 | print('fatal: manifest url is required.', file=sys.stderr) |
3509 | return False | 3544 | return False |
3510 | 3545 | ||
3511 | if not quiet: | 3546 | if verbose: |
3512 | print('Downloading manifest from %s' % | 3547 | print('Downloading manifest from %s' % |
3513 | (GitConfig.ForUser().UrlInsteadOf(manifest_url),), | 3548 | (GitConfig.ForUser().UrlInsteadOf(manifest_url),), |
3514 | file=sys.stderr) | 3549 | file=sys.stderr) |
@@ -3700,6 +3735,65 @@ class ManifestProject(MetaProject): | |||
3700 | print('fatal: cannot create default in manifest', file=sys.stderr) | 3735 | print('fatal: cannot create default in manifest', file=sys.stderr) |
3701 | return False | 3736 | return False |
3702 | 3737 | ||
3738 | if not manifest_name: | ||
3739 | print('fatal: manifest name (-m) is required.', file=sys.stderr) | ||
3740 | return False | ||
3741 | |||
3742 | try: | ||
3743 | self.manifest.Link(manifest_name) | ||
3744 | except ManifestParseError as e: | ||
3745 | print("fatal: manifest '%s' not available" % manifest_name, | ||
3746 | file=sys.stderr) | ||
3747 | print('fatal: %s' % str(e), file=sys.stderr) | ||
3748 | return False | ||
3749 | |||
3750 | # Lastly, clone the superproject. | ||
3751 | superproject = git_superproject.Superproject(self.manifest, | ||
3752 | self.repodir, | ||
3753 | self.git_event_log, | ||
3754 | quiet=not verbose) | ||
3755 | sync_result = superproject.Sync() | ||
3756 | if not sync_result.success: | ||
3757 | print('warning: git update of superproject failed, repo sync will not ' | ||
3758 | 'use superproject to fetch source; while this error is not fatal, ' | ||
3759 | 'and you can continue to run repo sync, please run repo init with ' | ||
3760 | 'the --no-use-superproject option to stop seeing this warning', | ||
3761 | file=sys.stderr) | ||
3762 | if sync_result.fatal and use_superproject is not None: | ||
3763 | return False | ||
3764 | |||
3765 | if this_manifest_only: | ||
3766 | return True | ||
3767 | |||
3768 | for submanifest in self.manifest.submanifests.values(): | ||
3769 | spec = submanifest.ToSubmanifestSpec(root=self.manifest.outer_client) | ||
3770 | submanifest.repo_client.manifestProject.Sync( | ||
3771 | manifest_url=spec.manifestUrl, | ||
3772 | manifest_branch=spec.revision, | ||
3773 | standalone_manifest=standalone_manifest, | ||
3774 | groups=self.manifest_groups, | ||
3775 | platform=platform, | ||
3776 | mirror=mirror, | ||
3777 | dissociate=dissociate, | ||
3778 | reference=reference, | ||
3779 | worktree=worktree, | ||
3780 | submodules=submodules, | ||
3781 | archive=archive, | ||
3782 | partial_clone=partial_clone, | ||
3783 | clone_filter=clone_filter, | ||
3784 | partial_clone_exclude=partial_clone_exclude, | ||
3785 | clone_bundle=clone_bundle, | ||
3786 | git_lfs=git_lfs, | ||
3787 | use_superproject=use_superproject, | ||
3788 | verbose=verbose, | ||
3789 | current_branch_only=current_branch_only, | ||
3790 | tags=tags, | ||
3791 | depth=depth, | ||
3792 | manifest_name=spec.manifestName, | ||
3793 | this_manifest_only=False, | ||
3794 | outer_manifest=False, | ||
3795 | ) | ||
3796 | |||
3703 | return True | 3797 | return True |
3704 | 3798 | ||
3705 | def _ConfigureDepth(self, depth): | 3799 | def _ConfigureDepth(self, depth): |
diff --git a/subcmds/init.py b/subcmds/init.py index 13085fae..2cb3ff38 100644 --- a/subcmds/init.py +++ b/subcmds/init.py | |||
@@ -32,7 +32,7 @@ from wrapper import Wrapper | |||
32 | 32 | ||
33 | class Init(InteractiveCommand, MirrorSafeCommand): | 33 | class Init(InteractiveCommand, MirrorSafeCommand): |
34 | COMMON = True | 34 | COMMON = True |
35 | MULTI_MANIFEST_SUPPORT = False | 35 | MULTI_MANIFEST_SUPPORT = True |
36 | helpSummary = "Initialize a repo client checkout in the current directory" | 36 | helpSummary = "Initialize a repo client checkout in the current directory" |
37 | helpUsage = """ | 37 | helpUsage = """ |
38 | %prog [options] [manifest url] | 38 | %prog [options] [manifest url] |
@@ -107,26 +107,6 @@ to update the working directory files. | |||
107 | return {'REPO_MANIFEST_URL': 'manifest_url', | 107 | return {'REPO_MANIFEST_URL': 'manifest_url', |
108 | 'REPO_MIRROR_LOCATION': 'reference'} | 108 | 'REPO_MIRROR_LOCATION': 'reference'} |
109 | 109 | ||
110 | def _CloneSuperproject(self, opt): | ||
111 | """Clone the superproject based on the superproject's url and branch. | ||
112 | |||
113 | Args: | ||
114 | opt: Program options returned from optparse. See _Options(). | ||
115 | """ | ||
116 | superproject = git_superproject.Superproject(self.manifest, | ||
117 | self.repodir, | ||
118 | self.git_event_log, | ||
119 | quiet=opt.quiet) | ||
120 | sync_result = superproject.Sync() | ||
121 | if not sync_result.success: | ||
122 | print('warning: git update of superproject failed, repo sync will not ' | ||
123 | 'use superproject to fetch source; while this error is not fatal, ' | ||
124 | 'and you can continue to run repo sync, please run repo init with ' | ||
125 | 'the --no-use-superproject option to stop seeing this warning', | ||
126 | file=sys.stderr) | ||
127 | if sync_result.fatal and opt.use_superproject is not None: | ||
128 | sys.exit(1) | ||
129 | |||
130 | def _SyncManifest(self, opt): | 110 | def _SyncManifest(self, opt): |
131 | """Call manifestProject.Sync with arguments from opt. | 111 | """Call manifestProject.Sync with arguments from opt. |
132 | 112 | ||
@@ -154,19 +134,8 @@ to update the working directory files. | |||
154 | verbose=opt.verbose, | 134 | verbose=opt.verbose, |
155 | current_branch_only=opt.current_branch_only, | 135 | current_branch_only=opt.current_branch_only, |
156 | tags=opt.tags, | 136 | tags=opt.tags, |
157 | depth=opt.depth): | 137 | depth=opt.depth, |
158 | sys.exit(1) | 138 | manifest_name=opt.manifest_name): |
159 | |||
160 | def _LinkManifest(self, name): | ||
161 | if not name: | ||
162 | print('fatal: manifest name (-m) is required.', file=sys.stderr) | ||
163 | sys.exit(1) | ||
164 | |||
165 | try: | ||
166 | self.manifest.Link(name) | ||
167 | except ManifestParseError as e: | ||
168 | print("fatal: manifest '%s' not available" % name, file=sys.stderr) | ||
169 | print('fatal: %s' % str(e), file=sys.stderr) | ||
170 | sys.exit(1) | 139 | sys.exit(1) |
171 | 140 | ||
172 | def _Prompt(self, prompt, value): | 141 | def _Prompt(self, prompt, value): |
@@ -343,10 +312,6 @@ to update the working directory files. | |||
343 | git_require((2, 15, 0), fail=True, msg='git gc worktree corruption') | 312 | git_require((2, 15, 0), fail=True, msg='git gc worktree corruption') |
344 | 313 | ||
345 | self._SyncManifest(opt) | 314 | self._SyncManifest(opt) |
346 | self._LinkManifest(opt.manifest_name) | ||
347 | |||
348 | if self.manifest.manifestProject.use_superproject: | ||
349 | self._CloneSuperproject(opt) | ||
350 | 315 | ||
351 | if os.isatty(0) and os.isatty(1) and not self.manifest.IsMirror: | 316 | if os.isatty(0) and os.isatty(1) and not self.manifest.IsMirror: |
352 | if opt.config_name or self._ShouldConfigureUser(opt): | 317 | if opt.config_name or self._ShouldConfigureUser(opt): |