diff options
| author | Jason Chang <jasonnc@google.com> | 2023-05-23 13:06:55 -0700 |
|---|---|---|
| committer | Jason Chang <jasonnc@google.com> | 2023-05-25 22:37:04 +0000 |
| commit | 17833322d9e0c650310e55f806d5e3545c265c2a (patch) | |
| tree | 67cd339bede0227bd43bd1e6fb9cc66fcb83d6b4 | |
| parent | 04cba4add52b11a27d09d73c2cbfebcd67a1f2cc (diff) | |
| download | git-repo-17833322d9e0c650310e55f806d5e3545c265c2a.tar.gz | |
Add envar to replace shallow clones with partial
An investigation go/git-repo-shallow shows a number of problems
when doing a shallow git fetch/clone. This change introduces an
environment variable REPO_ALLOW_SHALLOW. When this environment variable
is set to 1 during a repo init or repo sync all shallow git fetch
commands are replaced with partial fetch commands. Any shallow
repository needing update is unshallowed. This behavior continues until
a subsequent repo sync command is run with REPO_ALLOW_SHALLOW set to 1.
Bug: b/274340522
Change-Id: I1c3188270629359e52449788897d9d4988ebf280
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/374754
Reviewed-by: Josip Sokcevic <sokcevic@google.com>
Tested-by: Jason Chang <jasonnc@google.com>
| -rw-r--r-- | manifest_xml.py | 6 | ||||
| -rw-r--r-- | project.py | 30 | ||||
| -rw-r--r-- | subcmds/init.py | 6 | ||||
| -rw-r--r-- | subcmds/sync.py | 13 |
4 files changed, 55 insertions, 0 deletions
diff --git a/manifest_xml.py b/manifest_xml.py index 14b03a30..555bf736 100644 --- a/manifest_xml.py +++ b/manifest_xml.py | |||
| @@ -982,6 +982,12 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md | |||
| 982 | return None | 982 | return None |
| 983 | 983 | ||
| 984 | @property | 984 | @property |
| 985 | def CloneFilterForDepth(self): | ||
| 986 | if self.manifestProject.clone_filter_for_depth: | ||
| 987 | return self.manifestProject.clone_filter_for_depth | ||
| 988 | return None | ||
| 989 | |||
| 990 | @property | ||
| 985 | def PartialCloneExclude(self): | 991 | def PartialCloneExclude(self): |
| 986 | exclude = self.manifest.manifestProject.partial_clone_exclude or "" | 992 | exclude = self.manifest.manifestProject.partial_clone_exclude or "" |
| 987 | return set(x.strip() for x in exclude.split(",")) | 993 | return set(x.strip() for x in exclude.split(",")) |
| @@ -1186,6 +1186,7 @@ class Project(object): | |||
| 1186 | ssh_proxy=None, | 1186 | ssh_proxy=None, |
| 1187 | clone_filter=None, | 1187 | clone_filter=None, |
| 1188 | partial_clone_exclude=set(), | 1188 | partial_clone_exclude=set(), |
| 1189 | clone_filter_for_depth=None, | ||
| 1189 | ): | 1190 | ): |
| 1190 | """Perform only the network IO portion of the sync process. | 1191 | """Perform only the network IO portion of the sync process. |
| 1191 | Local working directory/branch state is not affected. | 1192 | Local working directory/branch state is not affected. |
| @@ -1295,6 +1296,10 @@ class Project(object): | |||
| 1295 | else: | 1296 | else: |
| 1296 | depth = self.manifest.manifestProject.depth | 1297 | depth = self.manifest.manifestProject.depth |
| 1297 | 1298 | ||
| 1299 | if depth and clone_filter_for_depth: | ||
| 1300 | depth = None | ||
| 1301 | clone_filter = clone_filter_for_depth | ||
| 1302 | |||
| 1298 | # See if we can skip the network fetch entirely. | 1303 | # See if we can skip the network fetch entirely. |
| 1299 | remote_fetched = False | 1304 | remote_fetched = False |
| 1300 | if not ( | 1305 | if not ( |
| @@ -3885,6 +3890,11 @@ class ManifestProject(MetaProject): | |||
| 3885 | return self.config.GetString("repo.partialcloneexclude") | 3890 | return self.config.GetString("repo.partialcloneexclude") |
| 3886 | 3891 | ||
| 3887 | @property | 3892 | @property |
| 3893 | def clone_filter_for_depth(self): | ||
| 3894 | """Replace shallow clone with partial clone.""" | ||
| 3895 | return self.config.GetString("repo.clonefilterfordepth") | ||
| 3896 | |||
| 3897 | @property | ||
| 3888 | def manifest_platform(self): | 3898 | def manifest_platform(self): |
| 3889 | """The --platform argument from `repo init`.""" | 3899 | """The --platform argument from `repo init`.""" |
| 3890 | return self.config.GetString("manifest.platform") | 3900 | return self.config.GetString("manifest.platform") |
| @@ -3961,6 +3971,7 @@ class ManifestProject(MetaProject): | |||
| 3961 | manifest_name=spec.manifestName, | 3971 | manifest_name=spec.manifestName, |
| 3962 | this_manifest_only=True, | 3972 | this_manifest_only=True, |
| 3963 | outer_manifest=False, | 3973 | outer_manifest=False, |
| 3974 | clone_filter_for_depth=mp.clone_filter_for_depth, | ||
| 3964 | ) | 3975 | ) |
| 3965 | 3976 | ||
| 3966 | def Sync( | 3977 | def Sync( |
| @@ -3991,6 +4002,7 @@ class ManifestProject(MetaProject): | |||
| 3991 | tags="", | 4002 | tags="", |
| 3992 | this_manifest_only=False, | 4003 | this_manifest_only=False, |
| 3993 | outer_manifest=True, | 4004 | outer_manifest=True, |
| 4005 | clone_filter_for_depth=None, | ||
| 3994 | ): | 4006 | ): |
| 3995 | """Sync the manifest and all submanifests. | 4007 | """Sync the manifest and all submanifests. |
| 3996 | 4008 | ||
| @@ -4035,6 +4047,8 @@ class ManifestProject(MetaProject): | |||
| 4035 | current sub manifest. | 4047 | current sub manifest. |
| 4036 | outer_manifest: a boolean, whether to start at the outermost | 4048 | outer_manifest: a boolean, whether to start at the outermost |
| 4037 | manifest. | 4049 | manifest. |
| 4050 | clone_filter_for_depth: a string, when specified replaces shallow | ||
| 4051 | clones with partial. | ||
| 4038 | 4052 | ||
| 4039 | Returns: | 4053 | Returns: |
| 4040 | a boolean, whether the sync was successful. | 4054 | a boolean, whether the sync was successful. |
| @@ -4297,6 +4311,9 @@ class ManifestProject(MetaProject): | |||
| 4297 | file=sys.stderr, | 4311 | file=sys.stderr, |
| 4298 | ) | 4312 | ) |
| 4299 | 4313 | ||
| 4314 | if clone_filter_for_depth is not None: | ||
| 4315 | self.ConfigureCloneFilterForDepth(clone_filter_for_depth) | ||
| 4316 | |||
| 4300 | if use_superproject is not None: | 4317 | if use_superproject is not None: |
| 4301 | self.config.SetBoolean("repo.superproject", use_superproject) | 4318 | self.config.SetBoolean("repo.superproject", use_superproject) |
| 4302 | 4319 | ||
| @@ -4311,6 +4328,7 @@ class ManifestProject(MetaProject): | |||
| 4311 | submodules=submodules, | 4328 | submodules=submodules, |
| 4312 | clone_filter=clone_filter, | 4329 | clone_filter=clone_filter, |
| 4313 | partial_clone_exclude=self.manifest.PartialCloneExclude, | 4330 | partial_clone_exclude=self.manifest.PartialCloneExclude, |
| 4331 | clone_filter_for_depth=self.manifest.CloneFilterForDepth, | ||
| 4314 | ).success | 4332 | ).success |
| 4315 | if not success: | 4333 | if not success: |
| 4316 | r = self.GetRemote() | 4334 | r = self.GetRemote() |
| @@ -4415,6 +4433,18 @@ class ManifestProject(MetaProject): | |||
| 4415 | 4433 | ||
| 4416 | return True | 4434 | return True |
| 4417 | 4435 | ||
| 4436 | def ConfigureCloneFilterForDepth(self, clone_filter_for_depth): | ||
| 4437 | """Configure clone filter to replace shallow clones. | ||
| 4438 | |||
| 4439 | Args: | ||
| 4440 | clone_filter_for_depth: a string or None, e.g. 'blob:none' will | ||
| 4441 | disable shallow clones and replace with partial clone. None will | ||
| 4442 | enable shallow clones. | ||
| 4443 | """ | ||
| 4444 | self.config.SetString( | ||
| 4445 | "repo.clonefilterfordepth", clone_filter_for_depth | ||
| 4446 | ) | ||
| 4447 | |||
| 4418 | def _ConfigureDepth(self, depth): | 4448 | def _ConfigureDepth(self, depth): |
| 4419 | """Configure the depth we'll sync down. | 4449 | """Configure the depth we'll sync down. |
| 4420 | 4450 | ||
diff --git a/subcmds/init.py b/subcmds/init.py index 9946466d..6d7fd857 100644 --- a/subcmds/init.py +++ b/subcmds/init.py | |||
| @@ -20,6 +20,8 @@ from command import InteractiveCommand, MirrorSafeCommand | |||
| 20 | from git_command import git_require, MIN_GIT_VERSION_SOFT, MIN_GIT_VERSION_HARD | 20 | from git_command import git_require, MIN_GIT_VERSION_SOFT, MIN_GIT_VERSION_HARD |
| 21 | from wrapper import Wrapper | 21 | from wrapper import Wrapper |
| 22 | 22 | ||
| 23 | _REPO_ALLOW_SHALLOW = os.environ.get("REPO_ALLOW_SHALLOW") | ||
| 24 | |||
| 23 | 25 | ||
| 24 | class Init(InteractiveCommand, MirrorSafeCommand): | 26 | class Init(InteractiveCommand, MirrorSafeCommand): |
| 25 | COMMON = True | 27 | COMMON = True |
| @@ -125,6 +127,9 @@ to update the working directory files. | |||
| 125 | # manifest project is special and is created when instantiating the | 127 | # manifest project is special and is created when instantiating the |
| 126 | # manifest which happens before we parse options. | 128 | # manifest which happens before we parse options. |
| 127 | self.manifest.manifestProject.clone_depth = opt.manifest_depth | 129 | self.manifest.manifestProject.clone_depth = opt.manifest_depth |
| 130 | clone_filter_for_depth = ( | ||
| 131 | "blob:none" if (_REPO_ALLOW_SHALLOW == "0") else None | ||
| 132 | ) | ||
| 128 | if not self.manifest.manifestProject.Sync( | 133 | if not self.manifest.manifestProject.Sync( |
| 129 | manifest_url=opt.manifest_url, | 134 | manifest_url=opt.manifest_url, |
| 130 | manifest_branch=opt.manifest_branch, | 135 | manifest_branch=opt.manifest_branch, |
| @@ -140,6 +145,7 @@ to update the working directory files. | |||
| 140 | partial_clone=opt.partial_clone, | 145 | partial_clone=opt.partial_clone, |
| 141 | clone_filter=opt.clone_filter, | 146 | clone_filter=opt.clone_filter, |
| 142 | partial_clone_exclude=opt.partial_clone_exclude, | 147 | partial_clone_exclude=opt.partial_clone_exclude, |
| 148 | clone_filter_for_depth=clone_filter_for_depth, | ||
| 143 | clone_bundle=opt.clone_bundle, | 149 | clone_bundle=opt.clone_bundle, |
| 144 | git_lfs=opt.git_lfs, | 150 | git_lfs=opt.git_lfs, |
| 145 | use_superproject=opt.use_superproject, | 151 | use_superproject=opt.use_superproject, |
diff --git a/subcmds/sync.py b/subcmds/sync.py index a44ed5b4..9ae8a4ce 100644 --- a/subcmds/sync.py +++ b/subcmds/sync.py | |||
| @@ -79,6 +79,8 @@ _ONE_DAY_S = 24 * 60 * 60 | |||
| 79 | _REPO_AUTO_GC = "REPO_AUTO_GC" | 79 | _REPO_AUTO_GC = "REPO_AUTO_GC" |
| 80 | _AUTO_GC = os.environ.get(_REPO_AUTO_GC) == "1" | 80 | _AUTO_GC = os.environ.get(_REPO_AUTO_GC) == "1" |
| 81 | 81 | ||
| 82 | _REPO_ALLOW_SHALLOW = os.environ.get("REPO_ALLOW_SHALLOW") | ||
| 83 | |||
| 82 | 84 | ||
| 83 | class _FetchOneResult(NamedTuple): | 85 | class _FetchOneResult(NamedTuple): |
| 84 | """_FetchOne return value. | 86 | """_FetchOne return value. |
| @@ -638,6 +640,7 @@ later is required to fix a server side protocol bug. | |||
| 638 | ssh_proxy=self.ssh_proxy, | 640 | ssh_proxy=self.ssh_proxy, |
| 639 | clone_filter=project.manifest.CloneFilter, | 641 | clone_filter=project.manifest.CloneFilter, |
| 640 | partial_clone_exclude=project.manifest.PartialCloneExclude, | 642 | partial_clone_exclude=project.manifest.PartialCloneExclude, |
| 643 | clone_filter_for_depth=project.manifest.CloneFilterForDepth, | ||
| 641 | ) | 644 | ) |
| 642 | success = sync_result.success | 645 | success = sync_result.success |
| 643 | remote_fetched = sync_result.remote_fetched | 646 | remote_fetched = sync_result.remote_fetched |
| @@ -1440,6 +1443,7 @@ later is required to fix a server side protocol bug. | |||
| 1440 | submodules=mp.manifest.HasSubmodules, | 1443 | submodules=mp.manifest.HasSubmodules, |
| 1441 | clone_filter=mp.manifest.CloneFilter, | 1444 | clone_filter=mp.manifest.CloneFilter, |
| 1442 | partial_clone_exclude=mp.manifest.PartialCloneExclude, | 1445 | partial_clone_exclude=mp.manifest.PartialCloneExclude, |
| 1446 | clone_filter_for_depth=mp.manifest.CloneFilterForDepth, | ||
| 1443 | ) | 1447 | ) |
| 1444 | finish = time.time() | 1448 | finish = time.time() |
| 1445 | self.event_log.AddSync( | 1449 | self.event_log.AddSync( |
| @@ -1589,6 +1593,15 @@ later is required to fix a server side protocol bug. | |||
| 1589 | _PostRepoUpgrade(manifest, quiet=opt.quiet) | 1593 | _PostRepoUpgrade(manifest, quiet=opt.quiet) |
| 1590 | 1594 | ||
| 1591 | mp = manifest.manifestProject | 1595 | mp = manifest.manifestProject |
| 1596 | |||
| 1597 | if _REPO_ALLOW_SHALLOW is not None: | ||
| 1598 | if _REPO_ALLOW_SHALLOW == "1": | ||
| 1599 | mp.ConfigureCloneFilterForDepth(None) | ||
| 1600 | elif ( | ||
| 1601 | _REPO_ALLOW_SHALLOW == "0" and mp.clone_filter_for_depth is None | ||
| 1602 | ): | ||
| 1603 | mp.ConfigureCloneFilterForDepth("blob:none") | ||
| 1604 | |||
| 1592 | if opt.mp_update: | 1605 | if opt.mp_update: |
| 1593 | self._UpdateAllManifestProjects(opt, mp, manifest_name) | 1606 | self._UpdateAllManifestProjects(opt, mp, manifest_name) |
| 1594 | else: | 1607 | else: |
