mirror of
https://gerrit.googlesource.com/git-repo
synced 2026-07-16 21:57:00 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1729aaebae | |||
| 978adb7ea5 | |||
| 0398c6718e | |||
| 3bb4871c44 |
@@ -84,9 +84,14 @@ def _Color(fg=None, bg=None, attr=None):
|
|||||||
|
|
||||||
DEFAULT = None
|
DEFAULT = None
|
||||||
|
|
||||||
|
|
||||||
|
class _CheckConsoleSentinel:
|
||||||
|
"""Sentinel for checking console coloring."""
|
||||||
|
|
||||||
|
|
||||||
# Placholder value that indicates we need to check if the user is in an
|
# Placholder value that indicates we need to check if the user is in an
|
||||||
# interactive terminal session to determine if we turn on color or not.
|
# interactive terminal session to determine if we turn on color or not.
|
||||||
_CHECK_CONSOLE = object()
|
_CHECK_CONSOLE = _CheckConsoleSentinel()
|
||||||
|
|
||||||
# https://git-scm.com/docs/git-config#Documentation/git-config.txt-colorui
|
# https://git-scm.com/docs/git-config#Documentation/git-config.txt-colorui
|
||||||
_CONFIG_TO_COLOR_SETTING = {
|
_CONFIG_TO_COLOR_SETTING = {
|
||||||
|
|||||||
+16
-4
@@ -17,6 +17,7 @@ import multiprocessing
|
|||||||
import optparse
|
import optparse
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from error import InvalidProjectGroupsError
|
from error import InvalidProjectGroupsError
|
||||||
from error import NoSuchProjectError
|
from error import NoSuchProjectError
|
||||||
@@ -25,6 +26,10 @@ from event_log import EventLog
|
|||||||
import progress
|
import progress
|
||||||
|
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from project import Project
|
||||||
|
|
||||||
|
|
||||||
# Are we generating man-pages?
|
# Are we generating man-pages?
|
||||||
GENERATE_MANPAGES = os.environ.get("_REPO_GENERATE_MANPAGES_") == " indeed! "
|
GENERATE_MANPAGES = os.environ.get("_REPO_GENERATE_MANPAGES_") == " indeed! "
|
||||||
|
|
||||||
@@ -375,7 +380,7 @@ class Command:
|
|||||||
manifest=None,
|
manifest=None,
|
||||||
groups="",
|
groups="",
|
||||||
missing_ok=False,
|
missing_ok=False,
|
||||||
submodules_ok=False,
|
submodules_ok=None,
|
||||||
all_manifests=False,
|
all_manifests=False,
|
||||||
):
|
):
|
||||||
"""A list of projects that match the arguments.
|
"""A list of projects that match the arguments.
|
||||||
@@ -385,7 +390,9 @@ class Command:
|
|||||||
manifest: an XmlManifest, the manifest to use, or None for default.
|
manifest: an XmlManifest, the manifest to use, or None for default.
|
||||||
groups: a string, the manifest groups in use.
|
groups: a string, the manifest groups in use.
|
||||||
missing_ok: a boolean, whether to allow missing projects.
|
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
|
all_manifests: a boolean, if True then all manifests and
|
||||||
submanifests are used. If False, then only the local
|
submanifests are used. If False, then only the local
|
||||||
(sub)manifest is used.
|
(sub)manifest is used.
|
||||||
@@ -403,6 +410,11 @@ class Command:
|
|||||||
all_projects_list = manifest.projects
|
all_projects_list = manifest.projects
|
||||||
result = []
|
result = []
|
||||||
|
|
||||||
|
def should_include_submodules(project: "Project") -> bool:
|
||||||
|
if submodules_ok is None:
|
||||||
|
return project.sync_s
|
||||||
|
return submodules_ok
|
||||||
|
|
||||||
if not groups:
|
if not groups:
|
||||||
groups = manifest.GetManifestGroupsStr()
|
groups = manifest.GetManifestGroupsStr()
|
||||||
groups = [x for x in re.split(r"[,\s]+", groups) if x]
|
groups = [x for x in re.split(r"[,\s]+", groups) if x]
|
||||||
@@ -410,7 +422,7 @@ class Command:
|
|||||||
if not args:
|
if not args:
|
||||||
derived_projects = {}
|
derived_projects = {}
|
||||||
for project in all_projects_list:
|
for project in all_projects_list:
|
||||||
if submodules_ok or project.sync_s:
|
if should_include_submodules(project):
|
||||||
derived_projects.update(
|
derived_projects.update(
|
||||||
(p.RelPath(local=False), p)
|
(p.RelPath(local=False), p)
|
||||||
for p in project.GetDerivedSubprojects()
|
for p in project.GetDerivedSubprojects()
|
||||||
@@ -452,7 +464,7 @@ class Command:
|
|||||||
if (
|
if (
|
||||||
project
|
project
|
||||||
and not project.Derived
|
and not project.Derived
|
||||||
and (submodules_ok or project.sync_s)
|
and should_include_submodules(project)
|
||||||
):
|
):
|
||||||
search_again = False
|
search_again = False
|
||||||
for subproject in project.GetDerivedSubprojects():
|
for subproject in project.GetDerivedSubprojects():
|
||||||
|
|||||||
@@ -323,6 +323,7 @@ _repo() {
|
|||||||
'(-u --manifest-server-username)'{-u,--manifest-server-username=}'[Username for manifest server]:username:' \
|
'(-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:' \
|
'(-p --manifest-server-password)'{-p,--manifest-server-password=}'[Password for manifest server]:password:' \
|
||||||
'--fetch-submodules[Fetch submodules]' \
|
'--fetch-submodules[Fetch submodules]' \
|
||||||
|
'--no-fetch-submodules[Do not fetch submodules]' \
|
||||||
'--use-superproject[Use superproject]' \
|
'--use-superproject[Use superproject]' \
|
||||||
'--no-use-superproject[Do not use superproject]' \
|
'--no-use-superproject[Do not use superproject]' \
|
||||||
'--tags[Sync tags]' \
|
'--tags[Sync tags]' \
|
||||||
|
|||||||
@@ -83,6 +83,9 @@ password to authenticate with the manifest server
|
|||||||
\fB\-\-fetch\-submodules\fR
|
\fB\-\-fetch\-submodules\fR
|
||||||
fetch submodules from server
|
fetch submodules from server
|
||||||
.TP
|
.TP
|
||||||
|
\fB\-\-no\-fetch\-submodules\fR
|
||||||
|
don't fetch submodules from server
|
||||||
|
.TP
|
||||||
\fB\-\-use\-superproject\fR
|
\fB\-\-use\-superproject\fR
|
||||||
use the manifest superproject to sync projects; implies \fB\-c\fR
|
use the manifest superproject to sync projects; implies \fB\-c\fR
|
||||||
.TP
|
.TP
|
||||||
|
|||||||
+7
-3
@@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" 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
|
.SH NAME
|
||||||
repo \- repo sync - manual page for repo sync
|
repo \- repo sync - manual page for repo sync
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -83,6 +83,9 @@ password to authenticate with the manifest server
|
|||||||
\fB\-\-fetch\-submodules\fR
|
\fB\-\-fetch\-submodules\fR
|
||||||
fetch submodules from server
|
fetch submodules from server
|
||||||
.TP
|
.TP
|
||||||
|
\fB\-\-no\-fetch\-submodules\fR
|
||||||
|
don't fetch submodules from server
|
||||||
|
.TP
|
||||||
\fB\-\-use\-superproject\fR
|
\fB\-\-use\-superproject\fR
|
||||||
use the manifest superproject to sync projects; implies \fB\-c\fR
|
use the manifest superproject to sync projects; implies \fB\-c\fR
|
||||||
.TP
|
.TP
|
||||||
@@ -212,8 +215,9 @@ bootstrap a new Git repository from a resumeable bundle file on a content
|
|||||||
delivery network. This may be necessary if there are problems with the local
|
delivery network. This may be necessary if there are problems with the local
|
||||||
Python HTTP client or proxy configuration, but the Git binary works.
|
Python HTTP client or proxy configuration, but the Git binary works.
|
||||||
.PP
|
.PP
|
||||||
The \fB\-\-fetch\-submodules\fR option enables fetching Git submodules of a project from
|
The \fB\-\-fetch\-submodules\fR option enables fetching Git submodules of all projects
|
||||||
server.
|
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
|
.PP
|
||||||
The \fB\-c\fR/\-\-current\-branch option can be used to only fetch objects that are on the
|
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.
|
branch specified by a project's revision.
|
||||||
|
|||||||
+24
-6
@@ -2674,11 +2674,12 @@ class Project:
|
|||||||
# throws an error.
|
# throws an error.
|
||||||
revs = [f"{self.revisionExpr}^0"]
|
revs = [f"{self.revisionExpr}^0"]
|
||||||
upstream_rev = None
|
upstream_rev = None
|
||||||
|
use_superproject_for_upstream = self.upstream and (
|
||||||
|
self._UseSuperprojectForUpstream(use_superproject)
|
||||||
|
)
|
||||||
|
|
||||||
# Only check upstream when using superproject.
|
# Only check upstream when using superproject.
|
||||||
if self.upstream and git_superproject.UseSuperproject(
|
if use_superproject_for_upstream:
|
||||||
use_superproject, self.manifest
|
|
||||||
):
|
|
||||||
upstream_rev = self.GetRemote().ToLocal(self.upstream)
|
upstream_rev = self.GetRemote().ToLocal(self.upstream)
|
||||||
revs.append(upstream_rev)
|
revs.append(upstream_rev)
|
||||||
|
|
||||||
@@ -2692,9 +2693,7 @@ class Project:
|
|||||||
|
|
||||||
# Only verify upstream relationship for superproject scenarios
|
# Only verify upstream relationship for superproject scenarios
|
||||||
# without affecting plain usage.
|
# without affecting plain usage.
|
||||||
if self.upstream and git_superproject.UseSuperproject(
|
if use_superproject_for_upstream:
|
||||||
use_superproject, self.manifest
|
|
||||||
):
|
|
||||||
self.bare_git.merge_base(
|
self.bare_git.merge_base(
|
||||||
"--is-ancestor",
|
"--is-ancestor",
|
||||||
self.revisionExpr,
|
self.revisionExpr,
|
||||||
@@ -2723,6 +2722,16 @@ class Project:
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def _UseSuperprojectForUpstream(
|
||||||
|
self, use_superproject: Optional[bool] = None
|
||||||
|
) -> bool:
|
||||||
|
"""Whether to include upstream in the immutability check.
|
||||||
|
|
||||||
|
The upstream ancestry check is only meaningful for projects
|
||||||
|
that participate in a superproject relationship.
|
||||||
|
"""
|
||||||
|
return git_superproject.UseSuperproject(use_superproject, self.manifest)
|
||||||
|
|
||||||
def _FetchArchive(self, tarpath, cwd=None):
|
def _FetchArchive(self, tarpath, cwd=None):
|
||||||
cmd = ["archive", "-v", "-o", tarpath]
|
cmd = ["archive", "-v", "-o", tarpath]
|
||||||
cmd.append("--remote=%s" % self.remote.url)
|
cmd.append("--remote=%s" % self.remote.url)
|
||||||
@@ -4677,6 +4686,15 @@ class MetaProject(Project):
|
|||||||
self.revisionExpr = base
|
self.revisionExpr = base
|
||||||
self.revisionId = None
|
self.revisionId = None
|
||||||
|
|
||||||
|
def _UseSuperprojectForUpstream(
|
||||||
|
self, use_superproject: Optional[bool] = None
|
||||||
|
) -> bool:
|
||||||
|
# MetaProjects (the manifest repo and repo itself) never
|
||||||
|
# participate in a superproject relationship. Returning False
|
||||||
|
# here also avoids loading the manifest during `repo init`,
|
||||||
|
# before manifest.xml has been linked into .repo/.
|
||||||
|
return False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def HasChanges(self):
|
def HasChanges(self):
|
||||||
"""Has the remote received new commits not yet checked out?"""
|
"""Has the remote received new commits not yet checked out?"""
|
||||||
|
|||||||
+14
-1
@@ -16,7 +16,9 @@ import sys
|
|||||||
|
|
||||||
from color import Coloring
|
from color import Coloring
|
||||||
from command import Command
|
from command import Command
|
||||||
|
from error import GitError
|
||||||
from git_command import GitCommand
|
from git_command import GitCommand
|
||||||
|
from project import Project
|
||||||
from repo_logging import RepoLogger
|
from repo_logging import RepoLogger
|
||||||
|
|
||||||
|
|
||||||
@@ -30,6 +32,17 @@ class RebaseColoring(Coloring):
|
|||||||
self.fail = self.printer("fail", fg="red")
|
self.fail = self.printer("fail", fg="red")
|
||||||
|
|
||||||
|
|
||||||
|
def _ResolveOntoManifest(project: Project) -> str:
|
||||||
|
"""Resolve project's revisionExpr to a local tracking branch.
|
||||||
|
|
||||||
|
Falls back to the raw revisionExpr if ToLocal fails or raises GitError.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return project.GetRemote().ToLocal(project.revisionExpr)
|
||||||
|
except GitError:
|
||||||
|
return project.revisionExpr
|
||||||
|
|
||||||
|
|
||||||
class Rebase(Command):
|
class Rebase(Command):
|
||||||
COMMON = True
|
COMMON = True
|
||||||
helpSummary = "Rebase local branches on upstream branch"
|
helpSummary = "Rebase local branches on upstream branch"
|
||||||
@@ -162,7 +175,7 @@ branch but need to incorporate new upstream changes "underneath" them.
|
|||||||
args = common_args[:]
|
args = common_args[:]
|
||||||
if opt.onto_manifest:
|
if opt.onto_manifest:
|
||||||
args.append("--onto")
|
args.append("--onto")
|
||||||
args.append(project.revisionExpr)
|
args.append(_ResolveOntoManifest(project))
|
||||||
|
|
||||||
args.append(upbranch.LocalMerge)
|
args.append(upbranch.LocalMerge)
|
||||||
|
|
||||||
|
|||||||
+8
-1
@@ -379,7 +379,8 @@ may be necessary if there are problems with the local Python
|
|||||||
HTTP client or proxy configuration, but the Git binary works.
|
HTTP client or proxy configuration, but the Git binary works.
|
||||||
|
|
||||||
The --fetch-submodules option enables fetching Git submodules
|
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
|
The -c/--current-branch option can be used to only fetch objects that
|
||||||
are on the branch specified by a project's revision.
|
are on the branch specified by a project's revision.
|
||||||
@@ -573,6 +574,12 @@ later is required to fix a server side protocol bug.
|
|||||||
action="store_true",
|
action="store_true",
|
||||||
help="fetch submodules from server",
|
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(
|
p.add_option(
|
||||||
"--use-superproject",
|
"--use-superproject",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
"""Unittests for the command.py module."""
|
"""Unittests for the command.py module."""
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
from command import Command
|
from command import Command
|
||||||
|
|
||||||
|
|
||||||
@@ -86,3 +88,32 @@ def test_get_projects_keeps_derived_subprojects_for_repeated_repo():
|
|||||||
projects = cmd.GetProjects([])
|
projects = cmd.GetProjects([])
|
||||||
|
|
||||||
assert set(projects) == {project_a, project_b, submodule_a, submodule_b}
|
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
|
||||||
|
|||||||
@@ -716,6 +716,31 @@ class ManifestPropertiesFetchedCorrectly(unittest.TestCase):
|
|||||||
fakeproj.config.SetString("manifest.platform", "auto")
|
fakeproj.config.SetString("manifest.platform", "auto")
|
||||||
self.assertEqual(fakeproj.manifest_platform, "auto")
|
self.assertEqual(fakeproj.manifest_platform, "auto")
|
||||||
|
|
||||||
|
def test_check_immutable_revision_metaproject_skips_manifest_load(self):
|
||||||
|
"""MetaProjects must not parse manifest.xml during immutable check.
|
||||||
|
|
||||||
|
During `repo init` the manifestProject's own Sync_NetworkHalf runs
|
||||||
|
before manifest.xml has been linked into .repo/, so
|
||||||
|
_CheckForImmutableRevision must not touch it.
|
||||||
|
"""
|
||||||
|
|
||||||
|
with utils_for_test.TempGitTree() as tempdir:
|
||||||
|
fakeproj = self.setUpManifest(tempdir)
|
||||||
|
manifest_path = os.path.join(
|
||||||
|
tempdir, ".repo", manifest_xml.MANIFEST_FILE_NAME
|
||||||
|
)
|
||||||
|
self.assertFalse(os.path.exists(manifest_path))
|
||||||
|
|
||||||
|
fakeproj.revisionExpr = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
|
||||||
|
fakeproj.upstream = "refs/heads/main"
|
||||||
|
|
||||||
|
# Must return False without raising ManifestParseError, and
|
||||||
|
# must leave the absent manifest.xml untouched.
|
||||||
|
self.assertFalse(
|
||||||
|
fakeproj._CheckForImmutableRevision(use_superproject=None)
|
||||||
|
)
|
||||||
|
self.assertFalse(os.path.exists(manifest_path))
|
||||||
|
|
||||||
def test_sync_use_local_gitdirs_worktree_conflict(self):
|
def test_sync_use_local_gitdirs_worktree_conflict(self):
|
||||||
"""Test that --use-local-gitdirs conflicts with --worktree."""
|
"""Test that --use-local-gitdirs conflicts with --worktree."""
|
||||||
with utils_for_test.TempGitTree() as tempdir:
|
with utils_for_test.TempGitTree() as tempdir:
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
# Copyright (C) 2026 The Android Open Source Project
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
"""Unittests for the subcmds/rebase.py module."""
|
||||||
|
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
|
from error import GitError
|
||||||
|
from subcmds import rebase
|
||||||
|
|
||||||
|
|
||||||
|
def test_resolve_onto_manifest_success() -> None:
|
||||||
|
"""Test _ResolveOntoManifest when ToLocal succeeds."""
|
||||||
|
project = mock.MagicMock()
|
||||||
|
project.revisionExpr = "main"
|
||||||
|
|
||||||
|
remote = mock.MagicMock()
|
||||||
|
remote.ToLocal.return_value = "refs/remotes/goog/main"
|
||||||
|
project.GetRemote.return_value = remote
|
||||||
|
|
||||||
|
res = rebase._ResolveOntoManifest(project)
|
||||||
|
assert res == "refs/remotes/goog/main"
|
||||||
|
project.GetRemote.assert_called_once()
|
||||||
|
remote.ToLocal.assert_called_once_with("main")
|
||||||
|
|
||||||
|
|
||||||
|
def test_resolve_onto_manifest_fallback() -> None:
|
||||||
|
"""Test _ResolveOntoManifest when ToLocal raises GitError."""
|
||||||
|
project = mock.MagicMock()
|
||||||
|
project.revisionExpr = "main"
|
||||||
|
|
||||||
|
remote = mock.MagicMock()
|
||||||
|
remote.ToLocal.side_effect = GitError("Failed to resolve")
|
||||||
|
project.GetRemote.return_value = remote
|
||||||
|
|
||||||
|
res = rebase._ResolveOntoManifest(project)
|
||||||
|
assert res == "main"
|
||||||
|
project.GetRemote.assert_called_once()
|
||||||
|
remote.ToLocal.assert_called_once_with("main")
|
||||||
@@ -30,6 +30,23 @@ from project import SyncNetworkHalfResult
|
|||||||
from subcmds import sync
|
from subcmds import sync
|
||||||
|
|
||||||
|
|
||||||
|
@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(
|
@pytest.mark.parametrize(
|
||||||
"use_superproject, cli_args, result",
|
"use_superproject, cli_args, result",
|
||||||
[
|
[
|
||||||
|
|||||||
Reference in New Issue
Block a user