sync: Add CLI flag for globally disabling submodule fetch A global setting for disabling fetching of submodules is useful since this can currently otherwise only be done by modifying the manifest, or by explicitly providing projects on command line. Add this setting as --no-fetch-submodules to mirror the existing --fetch-submodules. Change-Id: Ic727c54f11a594aa52315751284b87138cf246bb Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/607641 Commit-Queue: Josef Malmstrom <Josef.Malmstrom@arm.com> Reviewed-by: Gavin Mak <gavinmak@google.com> Tested-by: Josef Malmstrom <Josef.Malmstrom@arm.com> Reviewed-by: Mike Frysinger <vapier@google.com>
diff --git a/command.py b/command.py index 7da063a..bfafcd4 100644 --- a/command.py +++ b/command.py
@@ -17,6 +17,7 @@ import optparse import os import re +from typing import TYPE_CHECKING from error import InvalidProjectGroupsError from error import NoSuchProjectError @@ -25,6 +26,10 @@ import progress +if TYPE_CHECKING: + from project import Project + + # Are we generating man-pages? GENERATE_MANPAGES = os.environ.get("_REPO_GENERATE_MANPAGES_") == " indeed! " @@ -375,7 +380,7 @@ manifest=None, groups="", missing_ok=False, - submodules_ok=False, + submodules_ok=None, all_manifests=False, ): """A list of projects that match the arguments. @@ -385,7 +390,9 @@ manifest: an XmlManifest, the manifest to use, or None for default. groups: a string, the manifest groups in use. missing_ok: a boolean, whether to allow missing projects. - submodules_ok: a boolean, whether to allow submodules. + submodules_ok: whether to allow submodules. True allows them for + all projects, False disallows them for all projects, and None + defers to each project's sync-s setting. all_manifests: a boolean, if True then all manifests and submanifests are used. If False, then only the local (sub)manifest is used. @@ -403,6 +410,11 @@ all_projects_list = manifest.projects result = [] + def should_include_submodules(project: "Project") -> bool: + if submodules_ok is None: + return project.sync_s + return submodules_ok + if not groups: groups = manifest.GetManifestGroupsStr() groups = [x for x in re.split(r"[,\s]+", groups) if x] @@ -410,7 +422,7 @@ if not args: derived_projects = {} for project in all_projects_list: - if submodules_ok or project.sync_s: + if should_include_submodules(project): derived_projects.update( (p.RelPath(local=False), p) for p in project.GetDerivedSubprojects() @@ -452,7 +464,7 @@ if ( project and not project.Derived - and (submodules_ok or project.sync_s) + and should_include_submodules(project) ): search_again = False for subproject in project.GetDerivedSubprojects():
diff --git a/completion.zsh b/completion.zsh index 507ed2b..8c0322f 100644 --- a/completion.zsh +++ b/completion.zsh
@@ -323,6 +323,7 @@ '(-u --manifest-server-username)'{-u,--manifest-server-username=}'[Username for manifest server]:username:' \ '(-p --manifest-server-password)'{-p,--manifest-server-password=}'[Password for manifest server]:password:' \ '--fetch-submodules[Fetch submodules]' \ + '--no-fetch-submodules[Do not fetch submodules]' \ '--use-superproject[Use superproject]' \ '--no-use-superproject[Do not use superproject]' \ '--tags[Sync tags]' \
diff --git a/man/repo-smartsync.1 b/man/repo-smartsync.1 index ef4c112..07bab53 100644 --- a/man/repo-smartsync.1 +++ b/man/repo-smartsync.1
@@ -83,6 +83,9 @@ \fB\-\-fetch\-submodules\fR fetch submodules from server .TP +\fB\-\-no\-fetch\-submodules\fR +don't fetch submodules from server +.TP \fB\-\-use\-superproject\fR use the manifest superproject to sync projects; implies \fB\-c\fR .TP
diff --git a/man/repo-sync.1 b/man/repo-sync.1 index 43d9595..68d1e5e 100644 --- a/man/repo-sync.1 +++ b/man/repo-sync.1
@@ -1,5 +1,5 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man. -.TH REPO "1" "June 2026" "repo sync" "Repo Manual" +.TH REPO "1" "July 2026" "repo sync" "Repo Manual" .SH NAME repo \- repo sync - manual page for repo sync .SH SYNOPSIS @@ -83,6 +83,9 @@ \fB\-\-fetch\-submodules\fR fetch submodules from server .TP +\fB\-\-no\-fetch\-submodules\fR +don't fetch submodules from server +.TP \fB\-\-use\-superproject\fR use the manifest superproject to sync projects; implies \fB\-c\fR .TP @@ -212,8 +215,9 @@ delivery network. This may be necessary if there are problems with the local Python HTTP client or proxy configuration, but the Git binary works. .PP -The \fB\-\-fetch\-submodules\fR option enables fetching Git submodules of a project from -server. +The \fB\-\-fetch\-submodules\fR option enables fetching Git submodules of all projects +from the server. The \fB\-\-no\-fetch\-submodules\fR option disables fetching Git +submodules, even when a project has sync\-s="true" in the manifest. .PP The \fB\-c\fR/\-\-current\-branch option can be used to only fetch objects that are on the branch specified by a project's revision.
diff --git a/subcmds/sync.py b/subcmds/sync.py index 2b9cafe..5a635fa 100644 --- a/subcmds/sync.py +++ b/subcmds/sync.py
@@ -379,7 +379,8 @@ HTTP client or proxy configuration, but the Git binary works. The --fetch-submodules option enables fetching Git submodules -of a project from server. +of all projects from the server. The --no-fetch-submodules option disables +fetching Git submodules, even when a project has sync-s="true" in the manifest. The -c/--current-branch option can be used to only fetch objects that are on the branch specified by a project's revision. @@ -574,6 +575,12 @@ help="fetch submodules from server", ) p.add_option( + "--no-fetch-submodules", + dest="fetch_submodules", + action="store_false", + help="don't fetch submodules from server", + ) + p.add_option( "--use-superproject", action="store_true", help="use the manifest superproject to sync projects; implies -c",
diff --git a/tests/test_command.py b/tests/test_command.py index bd2a47f..d7938c5 100644 --- a/tests/test_command.py +++ b/tests/test_command.py
@@ -14,6 +14,8 @@ """Unittests for the command.py module.""" +import pytest + from command import Command @@ -86,3 +88,32 @@ projects = cmd.GetProjects([]) assert set(projects) == {project_a, project_b, submodule_a, submodule_b} + + +@pytest.mark.parametrize( + "submodules_ok, sync_s, includes_submodule", + [ + (None, False, False), + (None, True, True), + (True, False, True), + (True, True, True), + (False, False, False), + (False, True, False), + ], +) +def test_get_projects_submodule_override( + submodules_ok, sync_s, includes_submodule +): + """The CLI override takes precedence over a project's sync-s setting.""" + submodule = FakeProject("submodule", "project/submodule") + project = FakeProject( + "project", + "project", + derived_subprojects=[submodule], + sync_s=sync_s, + ) + cmd = Command(manifest=FakeManifest([project])) + + projects = cmd.GetProjects([], submodules_ok=submodules_ok) + + assert (submodule in projects) is includes_submodule
diff --git a/tests/test_subcmds_sync.py b/tests/test_subcmds_sync.py index f858846..1fb462a 100644 --- a/tests/test_subcmds_sync.py +++ b/tests/test_subcmds_sync.py
@@ -31,6 +31,23 @@ @pytest.mark.parametrize( + "cli_args, expected", + [ + ([], None), + (["--fetch-submodules"], True), + (["--no-fetch-submodules"], False), + ], +) +def test_fetch_submodules_option(cli_args, expected): + """The fetch-submodules flags preserve an unset manifest-driven state.""" + cmd = sync.Sync() + + opts, _ = cmd.OptionParser.parse_args(cli_args) + + assert opts.fetch_submodules is expected + + +@pytest.mark.parametrize( "use_superproject, cli_args, result", [ (True, ["--current-branch"], True),