mirror of
https://gerrit.googlesource.com/git-repo
synced 2026-10-22 13:18:42 +00:00
sync, init: support repo.smartsync config and --head alias
Allow users to configure Smart Sync as the default for a checkout:
* Add `ManifestProject.smart_sync` backed by
`self.config.GetBoolean("repo.smartsync")`.
* Add `-s`/`--smart-sync` and `--no-smart-sync`/`--head` to `repo init`
to persist `repo.smartsync` in the manifest project config.
* Add `--head` as an alias for `--no-smart-sync` in `repo sync` and
`repo init`.
* Update `Sync._ResolveSmartSyncOption` so `ManifestProject.smart_sync`
takes precedence over `<default sync-smartsync="true" />` while
remaining overridable by per-invocation `repo sync` CLI flags.
Bug: 569927750
Test: pytest tests/test_project.py tests/test_subcmds_init.py tests/test_subcmds_sync.py
Change-Id: Ib40efc530336efb59a28acfed3d582713e9d67b2
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/643303
Reviewed-by: Mike Frysinger <vapier@google.com>
Commit-Queue: LaMont Jones <lamontjones@google.com>
Tested-by: LaMont Jones <lamontjones@google.com>
This commit is contained in:
1 parent
46e9866ca0
commit
f0124d0fd5
12 files changed
+158
-14
No files matched your search
@@ -236,6 +236,9 @@ _repo() {
|
||||
'--clone-filter=[Clone filter]:filter:' \
|
||||
'--use-superproject[Use superproject]' \
|
||||
'--no-use-superproject[Do not use superproject]' \
|
||||
'(-s --smart-sync)'{-s,--smart-sync}'[Default to smart sync]' \
|
||||
'--no-smart-sync[Do not default to smart sync]' \
|
||||
'--head[Do not default to smart sync]' \
|
||||
'--clone-bundle[Use clone bundle]' \
|
||||
'--no-clone-bundle[Do not use clone bundle]' \
|
||||
'--git-lfs[Use git lfs]' \
|
||||
@@ -338,6 +341,7 @@ _repo() {
|
||||
'--no-auto-gc[Do not run auto gc]' \
|
||||
'(-s --smart-sync)'{-s,--smart-sync}'[Smart sync]' \
|
||||
'--no-smart-sync[Do not smart sync]' \
|
||||
'--head[Do not smart sync]' \
|
||||
'(-t --smart-tag)'{-t,--smart-tag=}'[Smart tag]:tag:' \
|
||||
'--no-repo-verify[Do not verify repo]' \
|
||||
'--no-verify[Do not verify]' \
|
||||
|
||||
@@ -176,6 +176,7 @@ User controlled settings are initialized when running `repo init`.
|
||||
| repo.partialclone | `--partial-clone` | Create [partial git clones] |
|
||||
| repo.partialcloneexclude | `--partial-clone-exclude` | Comma-delimited list of project names (not paths) to exclude while using [partial git clones] |
|
||||
| repo.reference | `--reference` | Reference repo client checkout |
|
||||
| repo.smartsync | `--smart-sync` | Default to [Smart Sync](./smart-sync.md) when syncing |
|
||||
| repo.submodules | `--submodules` | Sync git submodules |
|
||||
| repo.superproject | `--use-superproject` | Sync [superproject] |
|
||||
| repo.worktree | `--worktree` | Use [git worktree] for checkouts |
|
||||
|
||||
+25
-3
@@ -182,6 +182,28 @@ affect Smart Sync: the default Smart Sync from `sync-smartsync` (see below)
|
||||
still runs, and an existing `smart_sync_override.xml` is replaced or removed as
|
||||
in a regular sync.
|
||||
|
||||
### `repo init --[no-]smart-sync`
|
||||
|
||||
Users can configure Smart Sync as the default for a checkout by passing
|
||||
`-s`/`--smart-sync` (or `--no-smart-sync`/`--head`) to `repo init` (this can
|
||||
also be re-run in an existing checkout to change the setting).
|
||||
|
||||
When resolving whether to perform a Smart Sync by default, `repo sync` uses the
|
||||
following precedence order (highest to lowest):
|
||||
|
||||
1. Per-invocation CLI flags (`-s`/`--smart-sync`, `--no-smart-sync`/`--head`,
|
||||
or target selection flags like `-t`, `-m`, `--superproject-revision`, `-l`).
|
||||
2. Checkout `repo init` setting (`repo init --[no-]smart-sync`).
|
||||
3. [Per-user `sync.smartsync` setting](#Per_user-default-sync_smartsync).
|
||||
4. Manifest [`sync-smartsync`](#sync-smartsync-manifest-attribute) setting.
|
||||
|
||||
Running `repo init --no-smart-sync` (or `repo init --head`) disables default
|
||||
Smart Sync for the checkout even when enabled by the user setting or manifest.
|
||||
As with the [manifest setting](#sync-smartsync-manifest-attribute), a
|
||||
checkout-enabled default Smart Sync falls back to a regular ToT sync if the
|
||||
manifest does not define a `<manifest-server>` or the manifest server cannot
|
||||
provide a usable manifest.
|
||||
|
||||
### sync-smartsync (Manifest Attribute)
|
||||
|
||||
The manifest can enable Smart Sync by default for all `repo sync` invocations
|
||||
@@ -230,10 +252,10 @@ match the settings Android build environments automatically setup.
|
||||
3. `${TARGET_PRODUCT}-${TARGET_BUILD_VARIANT}`: If these variables are all
|
||||
defined, then they are merged with `-` and used.
|
||||
|
||||
### --no-smart-sync
|
||||
### --no-smart-sync / --head
|
||||
|
||||
Explicitly disables Smart Sync, overriding any `sync-smartsync="true"` setting
|
||||
declared in the manifest `<default>` element.
|
||||
Explicitly disables Smart Sync, overriding any `repo.smartsync` git config or
|
||||
`sync-smartsync="true"` setting declared in the manifest `<default>` element.
|
||||
|
||||
### Per-user default (sync.smartsync)
|
||||
|
||||
|
||||
@@ -103,6 +103,12 @@ use the manifest superproject to sync projects; implies \fB\-c\fR
|
||||
\fB\-\-no\-use\-superproject\fR
|
||||
disable use of manifest superprojects
|
||||
.TP
|
||||
\fB\-s\fR, \fB\-\-smart\-sync\fR
|
||||
default to smart sync when syncing projects
|
||||
.TP
|
||||
\fB\-\-no\-smart\-sync\fR, \fB\-\-head\fR
|
||||
do not default to smart sync when syncing projects
|
||||
.TP
|
||||
\fB\-\-clone\-bundle\fR
|
||||
enable use of \fI\,/clone.bundle\/\fP on HTTP/HTTPS (default if not \fB\-\-partial\-clone\fR)
|
||||
.TP
|
||||
|
||||
+1
-1
@@ -125,7 +125,7 @@ do not run garbage collection on any projects (default)
|
||||
\fB\-s\fR, \fB\-\-smart\-sync\fR
|
||||
smart sync using manifest from the latest known good build
|
||||
.TP
|
||||
\fB\-\-no\-smart\-sync\fR
|
||||
\fB\-\-no\-smart\-sync\fR, \fB\-\-head\fR
|
||||
disable smart sync and sync to ToT instead
|
||||
.TP
|
||||
\fB\-t\fR SMART_TAG, \fB\-\-smart\-tag\fR=\fI\,SMART_TAG\/\fR
|
||||
|
||||
+13
@@ -5607,6 +5607,11 @@ class ManifestProject(MetaProject):
|
||||
"""Whether we use superproject."""
|
||||
return self.config.GetBoolean("repo.superproject")
|
||||
|
||||
@property
|
||||
def smart_sync(self) -> Optional[bool]:
|
||||
"""Whether we use smart sync by default."""
|
||||
return self.config.GetBoolean("repo.smartsync")
|
||||
|
||||
@property
|
||||
def partial_clone(self):
|
||||
"""Whether this is a partial clone."""
|
||||
@@ -5701,6 +5706,7 @@ class ManifestProject(MetaProject):
|
||||
clone_bundle=mp.clone_bundle,
|
||||
git_lfs=mp.git_lfs,
|
||||
use_superproject=mp.use_superproject,
|
||||
smart_sync=mp.smart_sync,
|
||||
verbose=verbose,
|
||||
current_branch_only=current_branch_only,
|
||||
tags=tags,
|
||||
@@ -5732,6 +5738,7 @@ class ManifestProject(MetaProject):
|
||||
clone_bundle=None,
|
||||
git_lfs=None,
|
||||
use_superproject=None,
|
||||
smart_sync: Optional[bool] = None,
|
||||
verbose=False,
|
||||
current_branch_only=False,
|
||||
git_event_log=None,
|
||||
@@ -5773,6 +5780,7 @@ class ManifestProject(MetaProject):
|
||||
git_lfs: a boolean, whether to enable git LFS support.
|
||||
use_superproject: a boolean, whether to use the manifest
|
||||
superproject to sync projects.
|
||||
smart_sync: a boolean, whether to default to smart sync.
|
||||
verbose: a boolean, whether to show all output, rather than only
|
||||
errors.
|
||||
current_branch_only: a boolean, whether to only fetch the current
|
||||
@@ -5820,6 +5828,7 @@ class ManifestProject(MetaProject):
|
||||
clone_bundle=clone_bundle,
|
||||
git_lfs=git_lfs,
|
||||
use_superproject=use_superproject,
|
||||
smart_sync=smart_sync,
|
||||
verbose=verbose,
|
||||
current_branch_only=current_branch_only,
|
||||
tags=tags,
|
||||
@@ -6090,6 +6099,9 @@ class ManifestProject(MetaProject):
|
||||
if use_superproject is not None:
|
||||
self.config.SetBoolean("repo.superproject", use_superproject)
|
||||
|
||||
if smart_sync is not None:
|
||||
self.config.SetBoolean("repo.smartsync", smart_sync)
|
||||
|
||||
if not standalone_manifest:
|
||||
success = self.Sync_NetworkHalf(
|
||||
is_new=is_new,
|
||||
@@ -6173,6 +6185,7 @@ class ManifestProject(MetaProject):
|
||||
clone_bundle=clone_bundle,
|
||||
git_lfs=git_lfs,
|
||||
use_superproject=use_superproject,
|
||||
smart_sync=smart_sync,
|
||||
verbose=verbose,
|
||||
current_branch_only=current_branch_only,
|
||||
tags=tags,
|
||||
|
||||
@@ -129,7 +129,7 @@ if not REPO_REV:
|
||||
BUG_URL = "https://issues.gerritcodereview.com/issues/new?component=1370071"
|
||||
|
||||
# increment this whenever we make important changes to this script
|
||||
VERSION = (2, 69)
|
||||
VERSION = (2, 71)
|
||||
|
||||
# increment this if the MAINTAINER_KEYS block is modified
|
||||
KEYRING_VERSION = (2, 3)
|
||||
@@ -443,6 +443,20 @@ def InitParser(parser):
|
||||
dest="use_superproject",
|
||||
help="disable use of manifest superprojects",
|
||||
)
|
||||
group.add_option(
|
||||
"-s",
|
||||
"--smart-sync",
|
||||
action="store_true",
|
||||
default=None,
|
||||
help="default to smart sync when syncing projects",
|
||||
)
|
||||
group.add_option(
|
||||
"--no-smart-sync",
|
||||
"--head",
|
||||
action="store_false",
|
||||
dest="smart_sync",
|
||||
help="do not default to smart sync when syncing projects",
|
||||
)
|
||||
group.add_option(
|
||||
"--clone-bundle",
|
||||
action="store_true",
|
||||
|
||||
@@ -164,6 +164,7 @@ to update the working directory files.
|
||||
clone_bundle=opt.clone_bundle,
|
||||
git_lfs=opt.git_lfs,
|
||||
use_superproject=opt.use_superproject,
|
||||
smart_sync=opt.smart_sync,
|
||||
verbose=opt.verbose,
|
||||
current_branch_only=opt.current_branch_only,
|
||||
tags=opt.tags,
|
||||
|
||||
+20
-8
@@ -839,6 +839,7 @@ later is required to fix a server side protocol bug.
|
||||
)
|
||||
p.add_option(
|
||||
"--no-smart-sync",
|
||||
"--head",
|
||||
dest="smart_sync",
|
||||
action="store_false",
|
||||
help="disable smart sync and sync to ToT instead",
|
||||
@@ -2527,16 +2528,20 @@ later is required to fix a server side protocol bug.
|
||||
def _ResolveSmartSyncOption(
|
||||
self, opt: optparse.Values, manifest: XmlManifest
|
||||
) -> bool:
|
||||
"""Resolve opt.smart_sync from CLI flags, user config and manifest.
|
||||
"""Resolve opt.smart_sync from CLI flags, config, and manifest.
|
||||
|
||||
Precedence: CLI flags > per-user settings > per-manifest settings.
|
||||
Precedence: CLI flags > per-checkout settings > per-user settings >
|
||||
per-manifest settings.
|
||||
See docs/repoconfig.md and docs/smart-sync.md for details.
|
||||
|
||||
Returns:
|
||||
True if smart_sync was enabled implicitly by the manifest default,
|
||||
False otherwise. Smart sync enabled via per-user settings counts
|
||||
as an explicit user request, not implicit.
|
||||
True if smart_sync was enabled implicitly by checkout or manifest
|
||||
default, False otherwise. Smart sync enabled via per-user settings
|
||||
counts as an explicit user request, not implicit.
|
||||
"""
|
||||
checkout_pref = getattr(manifest.manifestProject, "smart_sync", None)
|
||||
if not isinstance(checkout_pref, bool):
|
||||
checkout_pref = None
|
||||
user_pref = RepoConfig.ForUser().GetBoolean("sync.smartsync")
|
||||
default_allowed = (
|
||||
opt.smart_sync is None
|
||||
@@ -2545,13 +2550,20 @@ later is required to fix a server side protocol bug.
|
||||
and not opt.superproject_revision
|
||||
and not opt.local_only
|
||||
)
|
||||
default_smart_sync = (
|
||||
checkout_pref
|
||||
if checkout_pref is not None
|
||||
else getattr(manifest.default, "sync_smartsync", False) is True
|
||||
)
|
||||
implicit = (
|
||||
default_allowed
|
||||
and user_pref is None
|
||||
and getattr(manifest.default, "sync_smartsync", False) is True
|
||||
and (checkout_pref is not None or user_pref is None)
|
||||
and default_smart_sync
|
||||
)
|
||||
if opt.smart_sync is None:
|
||||
if user_pref is False:
|
||||
if checkout_pref is not None:
|
||||
opt.smart_sync = implicit
|
||||
elif user_pref is False:
|
||||
opt.smart_sync = False
|
||||
elif user_pref is True:
|
||||
opt.smart_sync = default_allowed
|
||||
|
||||
@@ -1822,6 +1822,9 @@ class ManifestPropertiesFetchedCorrectly(unittest.TestCase):
|
||||
fakeproj.config.SetBoolean("repo.superproject", False)
|
||||
self.assertFalse(fakeproj.use_superproject)
|
||||
|
||||
fakeproj.config.SetBoolean("repo.smartsync", False)
|
||||
self.assertFalse(fakeproj.smart_sync)
|
||||
|
||||
fakeproj.config.SetBoolean("repo.partialclone", False)
|
||||
self.assertFalse(fakeproj.partial_clone)
|
||||
|
||||
|
||||
@@ -23,7 +23,13 @@ from subcmds import init
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"argv",
|
||||
([],),
|
||||
(
|
||||
[],
|
||||
["-s"],
|
||||
["--smart-sync"],
|
||||
["--no-smart-sync"],
|
||||
["--head"],
|
||||
),
|
||||
)
|
||||
def test_cli_parser_good(argv: List[str]) -> None:
|
||||
"""Check valid command line options."""
|
||||
|
||||
@@ -465,6 +465,8 @@ def test_cli_jobs_sync_j_max(
|
||||
(["--smart-sync"], True, True, False),
|
||||
(["--no-smart-sync"], True, False, False),
|
||||
(["--no-smart-sync"], False, False, False),
|
||||
(["--head"], True, False, False),
|
||||
(["--head"], False, False, False),
|
||||
(["-t", "tag123"], True, False, False),
|
||||
(["--smart-tag=tag123"], True, False, False),
|
||||
(["-m", "other.xml"], True, False, False),
|
||||
@@ -491,6 +493,7 @@ def test_cli_smart_sync(
|
||||
"""
|
||||
manifest = mock.MagicMock()
|
||||
manifest.default.sync_smartsync = sync_smartsync_manifest
|
||||
manifest.manifestProject.smart_sync = None
|
||||
|
||||
cmd = sync.Sync(manifest=manifest)
|
||||
opts, args = cmd.OptionParser.parse_args(argv)
|
||||
@@ -500,6 +503,65 @@ def test_cli_smart_sync(
|
||||
assert implicit == expected_implicit
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"argv, config_smart_sync, user_pref, sync_smartsync_manifest, "
|
||||
"expected_smart_sync, expected_implicit",
|
||||
[
|
||||
# Config True overrides manifest False/None and user_pref False.
|
||||
([], True, None, False, True, True),
|
||||
([], True, None, None, True, True),
|
||||
([], True, False, False, True, True),
|
||||
# Config False overrides manifest True and user_pref True.
|
||||
([], False, None, True, False, False),
|
||||
([], False, True, True, False, False),
|
||||
# Config None falls back to user_pref, then manifest.
|
||||
([], None, True, False, True, False),
|
||||
([], None, False, True, False, False),
|
||||
([], None, None, True, True, True),
|
||||
([], None, None, False, False, False),
|
||||
# CLI flags override config.
|
||||
(["-s"], False, None, False, True, False),
|
||||
(["--smart-sync"], False, None, True, True, False),
|
||||
(["--no-smart-sync"], True, None, True, False, False),
|
||||
(["--no-smart-sync"], True, None, False, False, False),
|
||||
(["--head"], True, None, True, False, False),
|
||||
(["--head"], True, None, False, False, False),
|
||||
# Conflicting flags suppress implicit smart sync from config.
|
||||
(["-t", "tag123"], True, None, False, False, False),
|
||||
(["-m", "other.xml"], True, None, False, False, False),
|
||||
(["-l"], True, None, False, False, False),
|
||||
(["--nmu"], True, None, False, True, True),
|
||||
(["--superproject-revision=abc"], True, None, False, False, False),
|
||||
(["-s", "-l"], True, None, False, True, False),
|
||||
],
|
||||
)
|
||||
def test_cli_smart_sync_with_config(
|
||||
argv: List[str],
|
||||
config_smart_sync: Optional[bool],
|
||||
user_pref: Optional[bool],
|
||||
sync_smartsync_manifest: Optional[bool],
|
||||
expected_smart_sync: bool,
|
||||
expected_implicit: bool,
|
||||
) -> None:
|
||||
"""Tests repo.smartsync config precedence between CLI, user, and
|
||||
manifest.
|
||||
"""
|
||||
manifest = mock.MagicMock()
|
||||
manifest.default.sync_smartsync = sync_smartsync_manifest
|
||||
manifest.manifestProject.smart_sync = config_smart_sync
|
||||
|
||||
user_cfg = mock.MagicMock()
|
||||
user_cfg.GetBoolean.return_value = user_pref
|
||||
|
||||
cmd = sync.Sync(manifest=manifest)
|
||||
opts, args = cmd.OptionParser.parse_args(argv)
|
||||
cmd.ValidateOptions(opts, args)
|
||||
with mock.patch.object(sync.RepoConfig, "ForUser", return_value=user_cfg):
|
||||
implicit = cmd._ResolveSmartSyncOption(opts, manifest)
|
||||
assert opts.smart_sync == expected_smart_sync
|
||||
assert implicit == expected_implicit
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"argv, user_pref, sync_smartsync_manifest, expected_smart_sync, "
|
||||
"expected_implicit",
|
||||
|
||||
Reference in new issue
Block a user