diff --git a/docs/manifest-format.md b/docs/manifest-format.md index f0149dd80..42fb1bfe2 100644 --- a/docs/manifest-format.md +++ b/docs/manifest-format.md @@ -73,18 +73,19 @@ following DTD: project*, copyfile*, linkfile*)> - - - - - - - - - - - - + + + + + + + + + + + + + @@ -389,6 +390,22 @@ rather than the `name` attribute. This attribute only applies to the local mirrors syncing, it will be ignored when syncing the projects in a client working directory. +Attribute `sync-strategy`: Set the sync strategy used when fetching this +project. Currently the only supported value is `stateless`. When set to +`stateless`, repo will run a reflog expiration and aggressive garbage collection +at the end of the sync process. This is useful for projects that contain +large binary files and use `clone-depth="1"`, where garbage can accumulate +as binaries are added, deleted, or modified across successive syncs. + +During a stateless sync, repo checks the following before cleaning up: +1. The project does not share an object directory with other projects. +2. The working tree is clean (no uncommitted changes, no untracked files). +3. There are no unpushed local commits. +4. There is no Git stash. + +If any of these conditions are not met, repo falls back to a standard +sync without garbage collection. + ### Element extend-project Modify the attributes of the named project. diff --git a/man/repo-manifest.1 b/man/repo-manifest.1 index 4d74fde89..75c9fa9e1 100644 --- a/man/repo-manifest.1 +++ b/man/repo-manifest.1 @@ -1,5 +1,5 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man. -.TH REPO "1" "March 2026" "repo manifest" "Repo Manual" +.TH REPO "1" "April 2026" "repo manifest" "Repo Manual" .SH NAME repo \- repo manifest - manual page for repo manifest .SH SYNOPSIS @@ -165,15 +165,32 @@ IDREF #IMPLIED> .TP +.TP + +.TP + +.TP + +.TP + +.TP + +.TP + +.TP + +.TP + .IP - - - - - - - - + .IP @@ -469,6 +486,21 @@ mirror repository according to its `path` attribute (if supplied) rather than the `name` attribute. This attribute only applies to the local mirrors syncing, it will be ignored when syncing the projects in a client working directory. .PP +Attribute `sync\-strategy`: Set the sync strategy used when fetching this +project. Currently the only supported value is `stateless`. When set to +`stateless`, repo will run a reflog expiration and aggressive garbage collection +at the end of the sync process. This is useful for projects that contain large +binary files and use `clone\-depth="1"`, where garbage can accumulate as binaries +are added, deleted, or modified across successive syncs. +.PP +During a stateless sync, repo checks the following before cleaning up: 1. The +project does not share an object directory with other projects. 2. The working +tree is clean (no uncommitted changes, no untracked files). 3. There are no +unpushed local commits. 4. There is no Git stash. +.PP +If any of these conditions are not met, repo falls back to a standard sync +without garbage collection. +.PP Element extend\-project .PP Modify the attributes of the named project. diff --git a/manifest_xml.py b/manifest_xml.py index c9bc6848b..5dc9d2fe9 100644 --- a/manifest_xml.py +++ b/manifest_xml.py @@ -759,6 +759,9 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md if p.clone_depth: e.setAttribute("clone-depth", str(p.clone_depth)) + if p.sync_strategy: + e.setAttribute("sync-strategy", str(p.sync_strategy)) + self._output_manifest_project_extras(p, e) if p.subprojects: @@ -1938,6 +1941,8 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md % (self.manifestFile, clone_depth) ) + sync_strategy = node.getAttribute("sync-strategy") or None + dest_branch = ( node.getAttribute("dest-branch") or self._default.destBranchExpr ) @@ -1984,6 +1989,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md sync_s=sync_s, sync_tags=sync_tags, clone_depth=clone_depth, + sync_strategy=sync_strategy, upstream=upstream, parent=parent, dest_branch=dest_branch, diff --git a/project.py b/project.py index 11b53c33c..1766c9a07 100644 --- a/project.py +++ b/project.py @@ -558,6 +558,7 @@ class Project: sync_s=False, sync_tags=True, clone_depth=None, + sync_strategy=None, upstream=None, parent=None, use_git_worktrees=False, @@ -610,6 +611,7 @@ class Project: self.sync_s = sync_s self.sync_tags = sync_tags self.clone_depth = clone_depth + self.sync_strategy = sync_strategy self.upstream = upstream self.parent = parent # NB: Do not use this setting in __init__ to change behavior so that the diff --git a/tests/test_manifest_xml.py b/tests/test_manifest_xml.py index 473f781ba..c7352f89a 100644 --- a/tests/test_manifest_xml.py +++ b/tests/test_manifest_xml.py @@ -732,6 +732,29 @@ class TestProjectElement: "" ) + def test_sync_strategy(self, repo_client: RepoClient) -> None: + """Check setting of project's sync_strategy.""" + manifest = repo_client.get_xml_manifest( + """ + + + + + +""" + ) + assert len(manifest.projects) == 1 + project = manifest.projects[0] + assert project.sync_strategy == "stateless" + assert ( + sort_attributes(manifest.ToXml().toxml()) + == '' + '' + '' + '' + "" + ) + def test_trailing_slash(self, repo_client: RepoClient) -> None: """Check handling of trailing slashes in attributes."""