2220 Commits
Author SHA1 Message Date
Romaric Jodin 3656290156 upload: add --ignore-remote-commits
When uploading a branch that merges another remote-tracking branch (such
as an upstream branch into the destination branch), ReviewableBranch
only excludes the destination tracking branch (^base). As a result, git
rev-list walks the merged parent and counts all merged commits even
though they already exist on a remote branch, triggering the unusual
commit count warning in _VerifyPendingCommits.

Add --ignore-remote-commits to `repo upload` to pass --not --remotes to
git rev-list in ReviewableBranch so commits already reachable from
refs/remotes/* are excluded from the pending commit list.

Test: ./run_tests tests/test_project.py tests/test_subcmds_upload.py
Change-Id: Ib1fb864982729e20a621144580fe95daa478eaee
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/651284
Tested-by: Romaric Jodin <rjodin@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
Commit-Queue: Romaric Jodin <rjodin@google.com>
v2.72
2026-11-03 00:10:19 -08:00
Brian Gan b90c7cd8f9 docs: add Repology links for distro package versions
The Ubuntu and Debian release wiki pages added in
https://gerrit-review.googlesource.com/c/git-repo/+/649983 only list
distro release and EOL dates, not which versions of Python, Git, or
OpenSSH shipped in each distro release.

Add Repology package version links alongside the distro release pages
in python-support.md and requirements.json so maintainers can check
which versions shipped across historical Ubuntu and Debian releases.

Bug: 575551885
Change-Id: Ib256fd9b364074b52d3e15d185af519d8376cb28
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/650868
Reviewed-by: Gavin Mak <gavinmak@google.com>
Tested-by: Brian Gan <brgan@google.com>
Commit-Queue: Brian Gan <brgan@google.com>
2026-11-02 13:20:14 -08:00
Brian Gan c5340585b8 docs: release: update release process to match current practice
The documented process has drifted from how releases are actually done:
* Releases are now cut weekly by an automated pipeline, so the manual
  steps are only a fallback, and for rollbacks.
* Releases are tested (both updating an existing checkout and a fresh
  init) before pushing anything.
* The tag is pushed & announced first, and only promoted to stable after
  a day.
* Direct pushes to the stable branch are rejected, so it has to be
  deleted & recreated via the Gerrit REST API instead.

Bug: 575551885
Change-Id: Ib36df07811c225558aba1a925b9703f3b2017e6f
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/649984
Reviewed-by: Gavin Mak <gavinmak@google.com>
Tested-by: Brian Gan <brgan@google.com>
Commit-Queue: Brian Gan <brgan@google.com>
2026-10-27 12:29:45 -07:00
Brian Gan 86a7bec83d docs: release: remove stale Project References table
The table of git/python/ssh/distro versions hasn't been kept up to date
and duplicates information maintained upstream by the distros and
projects themselves.  Drop it, and point the places that referenced it
(python-support.md & requirements.json) at the Ubuntu & Debian release
pages instead.

Bug: 575551885
Change-Id: Id1cb2225b3852273ca717fc7a443449fb2fd006e
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/649983
Reviewed-by: Gavin Mak <gavinmak@google.com>
Tested-by: Brian Gan <brgan@google.com>
Commit-Queue: Brian Gan <brgan@google.com>
2026-10-27 10:39:40 -07:00
Mike Frysinger 338ddb7d83 style: use import git_refs everywhere
Align with Google style guides and `import git_refs` as a module
rather than import symbols out of it.

Change-Id: I4e33ebdf3b06acd94494f32cdf39aa58427cd4b2
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/648703
Reviewed-by: Brian Gan <brgan@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
v2.71
2026-10-27 02:00:11 -07:00
Gavin Mak 8c316d7c98 upload: suppress git push progress when quiet or non-TTY
`Project.UploadForReview()` unconditionally passed `--progress` to
`git push`, forcing client and remote progress meters (`Counting
objects`, `remote: Resolving deltas: 3%..100%`) even on non-TTY
stderr or when `-q`/`--quiet` was passed. Meanwhile, `repo upload`
ignored `opt.quiet` completely.

Move `--progress` injection for `push` into `GitCommand` alongside
`fetch` and `clone`, enabling it only when `sys.stderr.isatty()` and
none of `--progress`, `--no-progress`, `--quiet`, or `-q` are set.

Forward `opt.quiet` from `repo upload` to `Project.UploadForReview()`
and pass `--no-progress` to `git push` rather than `--quiet` so
Gerrit `remote: https://...` review URLs are still emitted and parsed
by `_FindGerritUrls()`. Also suppress the non-error `[OK]` summary
banner when `-q`/`--quiet` is set.

Bug: 578114287
Change-Id: I88b7b055dcca0db80dae6962886a693fe717c741
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/649663
Tested-by: Gavin Mak <gavinmak@google.com>
Commit-Queue: Gavin Mak <gavinmak@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
2026-10-26 14:51:52 -07:00
Brian Gan e3e8e8a3b0 tests: e2e: add tests for more repo init options
Cover `--reference` from a local mirror (with & without `--dissociate`),
`--standalone-manifest` with a manifest file served over HTTP, and
`--manifest-depth`.

Teach the server to serve static files (`GitHost.publish_file`), let
`manifest_xml` take an absolute `fetch` URL, and add `move_aside` to
make git dirs disappear mid-test (deleting them fails on Windows).

Bug: 566270944
Change-Id: Id60a19613a627f76d8d9125570dd5ce0cdfff9aa
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/648549
Reviewed-by: Gavin Mak <gavinmak@google.com>
Tested-by: Brian Gan <brgan@google.com>
Commit-Queue: Brian Gan <brgan@google.com>
2026-10-26 13:52:54 -07:00
Brian Gan cad9f591a4 tests: e2e: add tests for sync failures
Cover projects missing on the server (incl. `--fail-fast`), missing
project & manifest revisions, and local changes that conflict with an
incoming change.  The tests check that repo exits non-zero with a useful
error, leaves the rest of the tree usable, and recovers once the problem
is fixed.

Let `RepoClient.init` return failures instead of raising.

Bug: 566270944
Change-Id: I84e2b8c0bb6012678add77360b446d4bea010c78
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/648548
Reviewed-by: Gavin Mak <gavinmak@google.com>
Tested-by: Brian Gan <brgan@google.com>
Commit-Queue: Brian Gan <brgan@google.com>
2026-10-26 13:52:43 -07:00
Brian Gan 24197b8ae1 tests: e2e: add tests for manifest groups
Cover re-running `repo init -g` to add & remove projects,
`<include groups=...>`, `platform-*` groups & `--platform`, and groups
combined with a superproject.

Let `RepoClient.list_projects` pass args to `repo list`.

Bug: 566270944
Change-Id: Id333078fd18d38962d8b725ae9bd87f4976c3112
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/648547
Tested-by: Brian Gan <brgan@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
Commit-Queue: Brian Gan <brgan@google.com>
2026-10-26 13:52:38 -07:00
Brian Gan bfb9869b89 tests: e2e: add tests for partial clones & the Android setup
Cover the go/repo-init flags used across Android (superproject, `-c`,
`--partial-clone`, `--partial-clone-exclude` & `--clone-filter`)
followed by the go/sync flags, under Git 2 & Git 3 defaults: projects
are pinned to the superproject, filtered blobs stay on the server,
excluded projects are full clones, and incremental syncs skip projects
whose pin didn't move.  Also cover the default filter, and `sync -n`
then `sync -l` with a partial clone (where `-l` has to fetch blobs on
demand).

Add harness helpers to read a checkout's git config, list the repos a
client contacted, and create blobs that only exist in history.

Bug: 566270944
Change-Id: I77d2cabc1d4f5db2ea139c7825ba87638c6db1e7
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/648546
Commit-Queue: Brian Gan <brgan@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
Tested-by: Brian Gan <brgan@google.com>
2026-10-26 13:00:28 -07:00
Brian Gan 887f9a9014 tests: e2e: add tests for network-only & local-only syncs
Cover `repo sync -n` & `-l` on existing checkouts (interleaved &
phased), projects that were never fetched, and two-phase syncs with a
superproject.  `-l` must not touch the network, which the tests check by
taking the server offline.  Also cover tags (`--no-tags` & `sync-tags`),
`--prune`, `--force-sync`, `--force-remove-dirty` & `-d`.

Teach the harness to simulate outages (`GitHost.offline`) and to collect
the requests made during a block (`GitHost.watch_requests`), and add a
few `RepoClient` helpers.

Bug: 566270944
Change-Id: I96b4729a7d4e5b58bc57fb46a060beda35549979
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/648545
Tested-by: Brian Gan <brgan@google.com>
Commit-Queue: Brian Gan <brgan@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
2026-10-26 12:57:09 -07:00
Brian Gan dc1811ba23 tests: e2e: add tests for init, sync & common workflows
Cover the core `repo init` & `repo sync` options (current branch only,
clone bundles, shallow clones, groups, local manifests & manifest
names), multi-step workflows (two-phase syncs, mirrors, incremental
syncs, local work, switching manifest branches, selfupdate, ...), and
manifests that broke users in the past.  Some tests also run under Git 3
defaults.

Add `RepoClient` helpers to list remote-tracking branches & checkouts,
and document the test layout in the README.

Bug: 566270944
Change-Id: Iac333216e0f27e489e64f4eb853189f860a91f20
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/648544
Tested-by: Brian Gan <brgan@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
Commit-Queue: Brian Gan <brgan@google.com>
2026-10-26 12:53:32 -07:00
Brian Gan 9aac80dafc tests: e2e: fix harness on Windows, CI & inside git checkouts
Normalize the `\r\n` that Python on Windows writes to pipes in repo's
output so tests can match multi-line messages.  Pass a str to
`os.readlink`, which only accepts Path objects on Windows since Python
3.8.  Set `GIT_CEILING_DIRECTORIES` for the client so git never finds a
repo above the test dir (e.g. when running with `--basetemp=./tmp` from
a checkout).

Run the real git rather than a `git` wrapper that's first on PATH: the
real git's exec dir (from `git --exec-path`) has a copy of git, so put
it first on PATH.  LUCI's wrapper, for one, retries server errors for
minutes, which hangs tests that simulate them.

Bug: 566270944
Change-Id: Ia0ed5285852638e533632a7272f154239f1e834f
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/648543
Reviewed-by: Gavin Mak <gavinmak@google.com>
Tested-by: Brian Gan <brgan@google.com>
Commit-Queue: Brian Gan <brgan@google.com>
2026-10-26 12:50:26 -07:00
Mike Frysinger f4ce9572d1 style: use import git_command everywhere
Align with Google style guides and `import git_command` as a module
rather than import symbols out of it.

Change-Id: If80d95203e240dd6591e465ef75500c72401d2bf
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/648503
Commit-Queue: Mike Frysinger <vapier@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2026-10-23 17:00:18 -07:00
Mike Frysinger cc1f41d782 style: use import repo_logging everywhere
Align with Google style guides and `import repo_logging` as a module
rather than import symbols out of it.

Change-Id: Ie13c1f13be00dbf6dd3814a8780baf6453972237
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/647823
Tested-by: Mike Frysinger <vapier@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
2026-10-23 09:49:36 -07:00
Mike Frysinger f7d252f5dc style: use import repo_trace everywhere
Align with Google style guides and `import repo_trace` as a module
rather than import symbols out of it.

Change-Id: I6bea5e7a68775e93b6b7fcd218db666350aff690
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/647803
Tested-by: Mike Frysinger <vapier@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
2026-10-23 09:01:00 -07:00
Mike Frysinger f95e7cd899 style: use import ctypes everywhere
Align with Google style guides and `import ctypes` as a module rather
than import symbols out of it.

Change-Id: I256495f9aaf4566284c2e2209a0e40268ed1aa37
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/647603
Commit-Queue: Mike Frysinger <vapier@google.com>
Reviewed-by: Insaf Latypov <saferif@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
2026-10-22 17:44:42 -07:00
Mike Frysinger 2c04b98c60 style: use import error everywhere
Align with Google style guides and `import error` as a module rather
than import classes out of it.

Change-Id: I8686fbe7887bd6ceac7a07877af63934f0d0ddd2
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/647563
Commit-Queue: Mike Frysinger <vapier@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
Reviewed-by: Insaf Latypov <saferif@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2026-10-22 17:44:11 -07:00
Brian Gan 4212588c20 tests: e2e: add pytest fixtures & e2e marker
Add tests/e2e/conftest.py with fixtures for writing end-to-end tests: a
session-wide git server, the published code under test, a per-test
namespace of server repos, and a repo client with an isolated HOME &
git config.  Parametrize `git_defaults` to emulate Git 3 defaults
(reftable & `main` as the default branch) on older git.

Tests under tests/e2e/ are marked `e2e` and run after the unit tests in
`./run_tests`.  Use `-m e2e` or `-m 'not e2e'` to select them.  They're
skipped when `git http-backend` is unavailable, git is older than 2.28,
or not running from a git checkout.

Bug: 566270944
Change-Id: Ib61e4dd7acc41a65beec4d74f1635a25dce4e3be
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/647643
Commit-Queue: Brian Gan <brgan@google.com>
Tested-by: Brian Gan <brgan@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
2026-10-22 16:43:23 -07:00
Brian Gan be06f8dd01 tests: e2e: add a client to run repo against the local server
Add `RepoClient`, which runs a standalone copy of the `repo` launcher as
a subprocess the same way end users do, and `publish_repo_source`, which
publishes the code under test (the current checkout, including
uncommitted changes) as a repo on the server so `repo init` installs it
into .repo/repo/ over HTTP.

Also add `GIT_DEFAULTS` so tests can emulate Git 3 defaults (reftable &
`main` as the default branch) on older git.

Bug: 566270944
Change-Id: I01ef53362b7812f4cb3e012509350980413cf0a8

Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/647505
Tested-by: Brian Gan <brgan@google.com>
Commit-Queue: Brian Gan <brgan@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
2026-10-22 16:43:19 -07:00
Brian Gan 74d887ea86 tests: e2e: add a local smart HTTP git server
Add `GitHttpServer`, which serves the bare repositories under a
directory over smart HTTP by running `git http-backend` behind a small
threaded HTTP server on 127.0.0.1.  Like Gerrit/GoB, it also serves
static `<repo>/clone.bundle` files.  It records the requests it receives
so tests can check what clients fetched.

Add `GitHost`, which gives each test its own namespace of repos on a
shared server, with helpers to create & update a manifest repo.

Bug: 566270944
Change-Id: I35ff0b9ae743ed7a8d3c775525986e662ef03de0

Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/647504
Reviewed-by: Gavin Mak <gavinmak@google.com>
Tested-by: Brian Gan <brgan@google.com>
Commit-Queue: Brian Gan <brgan@google.com>
2026-10-22 16:43:14 -07:00
Brian Gan 29d644a5c0 tests: e2e: add helpers to create bare git repos
This is the first piece of a hermetic end-to-end test harness for
running the real `repo` against a local git server.

Add tests/e2e/harness.py with `ServerRepo`, which creates bare
repositories, commits (including gitlinks for superprojects), branches,
tags & clone bundles without needing a worktree.  Commits are written
with `git fast-import` using a fixed identity & a monotonic fake clock
so they're cheap & strictly ordered.  Also add helpers to run git with
the user's git environment stripped & to write git config files
directly.

Bug: 566270944
Change-Id: Ifa9cf84529a699987bf6b21bbe94bd43483d1e73

Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/647503
Reviewed-by: Gavin Mak <gavinmak@google.com>
Commit-Queue: Brian Gan <brgan@google.com>
Tested-by: Brian Gan <brgan@google.com>
2026-10-22 16:43:09 -07:00
Brian Gan a93741993b tests: fail skipped tests in CQ
A skip in CQ usually means the builder is missing a dependency (e.g. git
without reftable support), which silently drops coverage while the check
still passes.  Add a `--fail-on-skip` pytest option that turns skips
into failures, and have run_tests pass it in CI alongside the existing
`skip_cq` deselection.  Tests that shouldn't run in CQ keep using the
`skip_cq` marker.

Bug: 576728033
Change-Id: I2eb8ab168859a9a13d05ba7c771bb455c082f512
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/647626
Commit-Queue: Brian Gan <brgan@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
Tested-by: Brian Gan <brgan@google.com>
2026-10-22 16:43:05 -07:00
Insaf Latypov 9991aa6177 config: add subcommand to manage ~/.repoconfig/config
Per-user settings such as sync.smartsync live in ~/.repoconfig/config,
but reading or changing them required knowing the file location and
running `git config --file ~/.repoconfig/config ...`.

Add `repo config` as a thin wrapper around RepoConfig.ForUser(),
following the subcommand style of modern `git config`:
* `repo config get <name>` prints the value(s), exiting 1 if unset.
* `repo config set <name> <value>` sets it.
* `repo config unset <name>` removes it; a missing key is a no-op.
* `repo config list` shows all settings.

Values are stored as strings; `--type=bool|int` validates and
canonicalizes them on set and get, like `git config --type`.  `-z` makes
get and list NUL-terminated for scripting.  Setting names are validated
by `git config` itself when writing.

Factor the value parsing out of GitConfig.GetBoolean()/GetInt() into
ParseBoolean()/ParseInt() so the command and the readers agree, and
accept on/off/1/0 as booleans like git does.

Only the per-user file is handled; per-checkout settings in
.repo/manifests.git/config are out of scope.  Like other subcommands, it
runs from inside a repo checkout.

Update docs/repoconfig.md to use the new command in its examples and
add zsh completion and the man page.

Bug: 569927750
Test: ./run_tests
Change-Id: I940d0318549fe9d79f6f9173139f0b96a706f1bf
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/645727
Reviewed-by: Mike Frysinger <vapier@google.com>
Tested-by: Insaf Latypov <saferif@google.com>
Commit-Queue: Insaf Latypov <saferif@google.com>
2026-10-22 08:34:46 -07:00
Brian Gan d744eb15f3 project: accept v3 git bundles in _IsValidBundle
Git 2.29+ introduced v3 bundle headers (`# v3 git bundle`) for SHA-256
and filtered bundles. Allow both v2 and v3 bundle headers when
validating downloaded `clone.bundle` files.

Bug: 576377949
Change-Id: Ic5ac94bf535a801d948f8932213e62a6cd132cac
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/647123
Tested-by: Brian Gan <brgan@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
Commit-Queue: Brian Gan <brgan@google.com>
2026-10-21 16:04:30 -07:00
LaMont Jones f0124d0fd5 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>
2026-10-21 11:22:58 -07:00
Insaf Latypov 46e9866ca0 sync: Provide a CLI command to opt in/out of smartsync for a user.
Add a boolean `sync.smartsync` setting in the per-user repo config
(~/.repoconfig/config):
* true: smart sync by default, as if -s were passed.
* false: never smart sync by default, even if the manifest enables it.
* unset: follow the manifest default, as before.

Add docs/repoconfig.md as the user facing documentation for
~/.repoconfig/config and its settings, and point smart-sync.md and the
`repo sync` help at it.

Bug: 569927750
Test: ./run_tests
Change-Id: Ideb4119fcb5e90f8bb35c493d9e4f8bec7878b77
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/643264
Reviewed-by: Gavin Mak <gavinmak@google.com>
Commit-Queue: Insaf Latypov <saferif@google.com>
Tested-by: Insaf Latypov <saferif@google.com>
v2.70
2026-10-19 12:20:06 -07:00
Rahul Yadav 404aec7b53 upload: reject --fix with --ignore-hooks or --no-verify
--fix asks the pre-upload hook to apply its fixups, but:
* --no-verify skips the hook entirely, so --fix silently does nothing.
* --ignore-hooks uploads the original commits even if the hook fails,
  so any fixups applied to the working tree are not part of the
  upload. Whether --fix should then apply fixups or be ignored is
  ambiguous.

Reject both combinations up front, before any hook runs, instead of
picking an interpretation.

Bug: 562921767
Test: python3 -m pytest tests/test_subcmds_upload.py
Change-Id: Ib00ae69004642f2e763212b82e7c39f3b4da52eb
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/642664
Tested-by: Rahul Yadav <yadavrah@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
Commit-Queue: Rahul Yadav <yadavrah@google.com>
2026-10-16 00:18:33 -07:00
Insaf Latypov a0bc2b14a3 git_config: Fix bugs in processing RepoConfig.
- Automatically create all the parent directories for `git confing
  --file ...`
- Prevent `RepoConfig` from inheriting caches from `GitConfig`. These
  two are different files.

Bug: 569927750
Test: ./run_tests
Change-Id: I9c60cecff75c1fb62be3ff63425d9618c0f56b06
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/643263
Reviewed-by: Mike Frysinger <vapier@google.com>
Tested-by: Insaf Latypov <saferif@google.com>
Commit-Queue: Insaf Latypov <saferif@google.com>
v2.69
2026-10-14 07:49:21 -07:00
Rahul Yadav 3448df3954 sync: Add GetApprovedManifestV2 with named request options
Smart sync calls GetApprovedManifest(branch[, target]) over XML-RPC,
which only supports positional arguments.  Adding new request options
that way does not scale.

Add a GetApprovedManifestV2 method that takes a single struct of named
options and returns a struct:

  request:  {branch, target?, best_effort?}
  response: {success, manifest_xml?, error_message?}

Servers must ignore unknown options, so new options (e.g. criteria for
selecting a good build) can be added without another method.

The first new option is `best_effort`.  repo sets it when smart sync was
enabled implicitly by the manifest's sync-smartsync="true" default
rather than by -s.  The server may decline a best_effort request (e.g.
for rollout or cohort gating) by returning success=false.  The client
still owns the fallback policy: declined implicit requests fall back to
a regular sync, while explicit -s requests fail as before.

If the server does not implement GetApprovedManifestV2, repo falls back
to the legacy GetApprovedManifest call.

Bug: 545137090
Test: ./run_tests
Change-Id: I9297b728df26516012cb93dffc91d39c1fb0458f
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/636623
Reviewed-by: Mike Frysinger <vapier@google.com>
Commit-Queue: Rahul Yadav <yadavrah@google.com>
Tested-by: Rahul Yadav <yadavrah@google.com>
2026-10-14 03:30:36 -07:00
Brian Gan a110680ff3 repo: tolerate a transiently missing stable branch
The automated release process deletes the stable branch and then
recreates it. A client that fetches during that window can't find it:
`repo init` fails to resolve --repo-rev, and the daily self-update in
`repo sync` fails with "Cannot fetch repo tool".

In the launcher, if --repo-rev doesn't resolve after the initial fetch,
wait 10 seconds and refetch once before giving up. `resolve_repo_rev`
gains a `report_errors` flag so this first check doesn't print an error
that the refetch then fixes. Bump the launcher version to 2.69 so
existing users pick this up.

For fetches of the repo project itself (sync's self-update and
`repo selfupdate`), wait 10 seconds instead of 4 before retrying. The
delay is now a `RETRY_SLEEP_INITIAL_SEC` class attribute that
`RepoProject` overrides, so other projects keep the 4 second delay. This
replaces the unused `retry_sleep_initial_sec` parameter of
`_RemoteFetch`.

Bug: 566270786
Change-Id: I23cb810258522b5aa9eae9d7013dbb7904ebcad8
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/643265
Tested-by: Brian Gan <brgan@google.com>
Commit-Queue: Brian Gan <brgan@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
2026-10-13 13:55:40 -07:00
Rahul Yadav 178b66ee3e sync: keep smart sync override with -l
Splitting a sync into `repo sync -n` followed by `repo sync -l` should
end up in the same state as a single `repo sync`. With smart sync it
does not always: -n fetches the revisions pinned by the smart sync
manifest and saves it as smart_sync_override.xml, but the following -l
deletes that override and checks out ToT instead, unless the manifest
sets sync-smartsync="true". So `repo sync -s -n` + `repo sync -l` lands
on ToT, while `repo sync -s` lands on the pinned revisions.

Without an explicit -s or -t, -l does not contact the manifest server,
so it cannot choose new pins itself; the only consistent choice is to
keep the override the previous -n left behind. Do that regardless of
the manifest default.

Syncs that choose a manifest themselves still replace or remove the
override as before: any sync without -l, and -l combined with -s, -t,
-m, --superproject-revision or --no-smart-sync. Smart sync stays
non-sticky for regular syncs, and `repo sync -l --no-smart-sync` still
discards the override to check out ToT.

Bug: 569927750
Change-Id: Id06ff88e9f3183fae32e993e86630fc3e8de71a1
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/640965
Commit-Queue: Rahul Yadav <yadavrah@google.com>
Tested-by: Rahul Yadav <yadavrah@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
2026-10-12 02:14:30 -07:00
Gavin Mak beda65323e sync: skip clone.bundle when repo.fetchcmd is configured
In Sync_NetworkHalf, clone_bundle defaults to True on initial sync when
self.objdir does not exist yet, and _ApplyCloneBundle is called before
custom_fetch_configured is checked.

For remotes with HTTP/HTTPS URLs that serve /clone.bundle, this causes
repo sync to download and unpack the full clone.bundle into .git/objects
before invoking repo.fetchcmd.

Skip _ApplyCloneBundle when custom_fetch_configured is enabled so
repo.fetchcmd exclusively handles object fetching.

Bug: 543101585
Change-Id: If41a775a75589ad5a23106163f9932e2940b72d2
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/641685
Commit-Queue: Gavin Mak <gavinmak@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
Tested-by: Gavin Mak <gavinmak@google.com>
2026-10-09 14:09:50 -07:00
Gavin Mak 02e07525f9 project: peel annotated tags in GetRevisionId with cached refs
When all_refs (e.g. self.bare_ref.all in Sync_LocalHalf) is passed to
GetRevisionId, looking up a tag ref in all_refs returns the tag object
SHA for annotated tags rather than the peeled commit SHA.

In Sync_LocalHalf, this causes repo.reprojectcmd to receive a tag SHA in
REPO_TREV and DetachHead to fail with 'trying to write non-commit object
to branch HEAD', and causes standard checkouts to re-checkout on every
subsequent sync because HEAD (the commit SHA) never equals revid (the
tag object SHA).

Skip the all_refs fast path for refs/tags/* so tags always fall through
to bare_git.ResolveCommit, which peels to the underlying commit SHA.

Bug: 543101585
Change-Id: Ie4afa3cee9149e2a8438bd8fb4a8026a210848d8
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/641683
Commit-Queue: Gavin Mak <gavinmak@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
Tested-by: Gavin Mak <gavinmak@google.com>
2026-10-09 14:09:44 -07:00
Gavin Mak 2e8a3805bb sync: don't run git ls-remote before fetchcmd on unpinned refs
When a project's revision is an unpinned branch or tag and superprojects
are not used (so self.revisionId is unset), _CustomFetch previously ran
git ls-remote against the Git remote before invoking repo.fetchcmd just
to pre-populate REPO_TREV.

This added a per-project network round-trip before fetchcmd and forced
branch resolution against the Git remote rather than letting fetchcmd
resolve REPO_RREV from its own server (just as standard git fetch does
in _RemoteFetch).

Only populate REPO_TREV before fetchcmd when the target commit SHA is
already known (via self.revisionId from superproject or a SHA-pinned
revisionExpr). When REPO_RREV is an unpinned branch or tag, leave
REPO_TREV empty, let fetchcmd resolve REPO_RREV and update the local
tracking ref and FETCH_HEAD, and verify afterward that the tracking ref
and FETCH_HEAD resolve to the same valid commit in the object store.

Bug: 543101585
Change-Id: I482bf4c022d0e669e5620d4517581ac193983da0
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/640423
Reviewed-by: Brian Gan <brgan@google.com>
Commit-Queue: Gavin Mak <gavinmak@google.com>
Tested-by: Gavin Mak <gavinmak@google.com>
2026-10-09 14:09:37 -07:00
Becky Siegel 277759b9e1 agents: enable generic multi-perspective code review agent
Configure git-repo-code-review-agent with use_default_subagents: true in
agents/agent_configs.txtpb so groupagent-grev-review uses the generic
gerrit_reviewer multi-perspective review framework.

Bug: 555706086
Change-Id: I079681b00e71cb886dc2343692d88b01d58a51ea
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/641904
Reviewed-by: Brian Gan <brgan@google.com>
Tested-by: Becky Siegel <beckysiegel@google.com>
2026-10-09 13:10:58 -07:00
Brian Gan 9593a76fd1 sync: keep --superproject-revision across manifest reloads
When --superproject-revision moves `.repo/manifests`, the manifest is
reloaded, discarding the pinned superproject. _UpdateProjectsRevisionId
then read gitlinks from the superproject's default branch instead,
pinning failed, and projects synced unpinned.

Apply the revision in _ConfigureSuperproject so it is re-applied after
every reload.

Verified with https://paste.googleplex.com/5889974172516352

Bug: 571245807
Change-Id: I4d782d229b128c0f15081d11b722d8901709458c
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/641743
Reviewed-by: Gavin Mak <gavinmak@google.com>
Tested-by: Brian Gan <brgan@google.com>
Commit-Queue: Brian Gan <brgan@google.com>
2026-10-09 12:56:07 -07:00
Brian Gan 9293cda144 sync: roll back repo when stable is rewound
The documented way to roll back a bad release is to force push an older
release to stable, and docs/release-process.md says clients will then
automatically downgrade. _PostRepoFetch already supports switching to an
older commit, but it only runs when `RepoProject.HasChanges` is true,
and that used the `MetaProject` check of whether the remote has commits
that HEAD lacks. After a rewind it doesn't, so clients that had already
upgraded stayed on the bad release.

Make `RepoProject.HasChanges` true whenever the remote revision differs
from HEAD, in either direction. `ManifestProject` keeps the forward-only
check so local manifest commits are still rebased rather than dropped.

Bug: 571204396
Change-Id: I248507f434d2552ce11a9afabe9a6335cb24ddbd
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/640130
Reviewed-by: Gavin Mak <gavinmak@google.com>
Tested-by: Brian Gan <brgan@google.com>
Commit-Queue: Brian Gan <brgan@google.com>
2026-10-09 09:49:49 -07:00
Rahul Yadav 340b587e94 sync: Support SYNC_BRANCH to override the smart sync branch
`repo sync -s` always sends the manifest branch to the manifest server
as the `branch` argument of GetApprovedManifest. Some servers map one
manifest branch to several server-side (CI) branches, and the only way
to pick among them was indirectly through the target.

Honor a SYNC_BRANCH environment variable, mirroring SYNC_TARGET: if set
and non-empty, send it instead of the manifest branch. An empty value
is treated as unset. -t/--smart-tag is unaffected.

Bug: 568962967
Test: ./run_tests
Change-Id: I26700e8997c21487f83011258100fd91a5c87508
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/639123
Commit-Queue: Rahul Yadav <yadavrah@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
Tested-by: Rahul Yadav <yadavrah@google.com>
2026-10-09 07:00:47 -07:00
Rahul Yadav 0a4e68f9d2 sync: don't let --nmu affect smart sync
--no-manifest-update has always meant "use the existing manifest
checkout as-is": it skips updating .repo/manifests and nothing else.
Smart sync pins do not come from that checkout but from the manifest
server, and an explicit `-s --nmu` already works that way.

The manifest-driven default smart sync (sync-smartsync="true") instead
treated --nmu like -l: it disabled the implicit smart sync and kept an
existing smart_sync_override.xml. So on such manifests `repo sync --nmu`
fetched and checked out the previous pins (or ToT if there were none)
instead of doing what `repo sync` does minus the manifest checkout
update.

Make --nmu orthogonal to smart sync again: it no longer disables the
default smart sync, and it no longer keeps the override. Both have to
change together; otherwise a failed implicit smart sync under --nmu
would fall back to ToT while leaving the override on disk. Only -l,
which skips fetching, keeps the override.

Bug: 569927750
Change-Id: I33730363df485d72cd86ae99bf5eb8399b58e81a
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/641264
Reviewed-by: Brian Gan <brgan@google.com>
Commit-Queue: Rahul Yadav <yadavrah@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
Tested-by: Rahul Yadav <yadavrah@google.com>
2026-10-09 07:00:22 -07:00
Mike Frysinger 7bba4ee47e vpython: update to uv spec format
Change-Id: I18dca6f8c9c1f9234cfee640f780f1f2e4462ab8
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/635623
Commit-Queue: Mike Frysinger <vapier@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2026-10-05 10:40:31 -07:00
Rahul Yadav d53a4278f5 sync: Support manifest-driven default smart sync
Add support for enabling smart sync by default via the
sync-smartsync="true" attribute on the manifest <default> element.

When sync-smartsync is set to true in the manifest defaults:
- Plain `repo sync` triggers Smart Sync automatically.
- If that implicit Smart Sync fails (manifest server unreachable, or
  the returned manifest cannot be parsed), repo silently falls back to
  a regular ToT sync. The reason is logged with --verbose.
- `--no-smart-sync` CLI flag overrides the manifest default and
  syncs to ToT.
- Passing explicit `-s` / `--smart-sync` forces Smart Sync as before,
  and its failures are still fatal.
- `-t`, `--smart-tag`, `-m`, `--manifest-name`, and
  `--superproject-revision` disable the default smart sync.
- `-l` / `--local-only` and `--no-manifest-update` skip the manifest
  server and reuse the existing smart_sync_override.xml, if any.

Update docs, completion, regenerate man pages, and add tests for XML
parsing, serialization, CLI option resolution, and the fallback and
reuse paths.

Bug: 545137090
Change-Id: If75569c58dd525d170e9801e70ccbf02206a52f2
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/617641
Tested-by: Rahul Yadav <yadavrah@google.com>
Commit-Queue: Rahul Yadav <yadavrah@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
2026-10-01 03:13:33 -07:00
Victor Pushkarev 5d4149f32e gc: add --keep-manifest-projects
By default, `repo gc` treats projects excluded by the configured
manifest groups as unused. This matches the active project set, but it
can remove cached Git data for projects that might be used again after
changing groups.

Add `--keep-manifest-projects` to keep Git data for projects that are
still in the manifests, even if the current groups exclude them or their
checkout is missing. Git data for projects no longer in the manifests
can still be removed.

Change-Id: I63ae18ce1c6acc2463be86f81921476b12fb27d7
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/629741
Reviewed-by: Gavin Mak <gavinmak@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
Tested-by: Victor Pushkarev <corvinus.v@gmail.com>
Commit-Queue: Victor Pushkarev <corvinus.v@gmail.com>
2026-09-30 01:11:40 -07:00
Ram Peri cf499e312a sync: record superproject sync analysis state again
Since the multi-manifest change (bdcba7d), _UpdateProjectsRevisionId
rebinds its superproject_logging_data parameter to a new local dict.
The caller keeps its own empty dict and passes it to
UpdateSyncAnalysisState, so repo.syncstate.superproject.* is never
written to the manifest config or logged to trace2.

Drop the rebinding so the caller's dict is populated.

Also record superproject, haslocalmanifests and hassuperprojecttag
when no manifest declares a superproject. Before bdcba7d these keys
were logged on every sync. SyncAnalysisState does not remove old
keys, so without this a checkout that moves to a manifest without a
superproject keeps reporting the values from its last superproject
sync.

Bug: 565957530
Test: ./run_tests
Change-Id: I8796e3a34b9cf4786383d25ecc3ebf0c5409caa3
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/634843
Reviewed-by: Gavin Mak <gavinmak@google.com>
Commit-Queue: Ram Peri <ramperi@google.com>
Tested-by: Ram Peri <ramperi@google.com>
2026-09-28 15:34:54 -07:00
Mike Frysinger cc0546bc71 isort: print diff on failures
This should help users figure out how to fix problems.

Change-Id: I6346e163d06f9a0e52147689c5b329fe7f1366d2
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/635343
Tested-by: Mike Frysinger <vapier@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
2026-09-28 10:55:16 -07:00
Victor Pushkarev ccf9ce39b8 sync: keep local sync state paths relative to repo root
`LocalSyncState` uses `Project.relpath` to identify projects, but that
path is relative to each project's own manifest. Projects in different
manifests can have the same relpath, so their fetch and checkout
timestamps overwrite each other. This can make a later partial sync look
like a full sync.

Pruning has a related problem. It treats the stored paths as relative to
the current manifest's topdir, so when sync starts from the outermost
manifest it can look for submanifest projects in the wrong place and
remove valid state.

Use `Project.RelPath(local=False)` to identify projects in local sync
state and check stored paths from the repo root when pruning.

Add tests for same-relpath projects, partial-sync detection, and pruning
when sync starts from either the outermost manifest or a submanifest.

Change-Id: I24485c315f1277a14913443674245cedd20820fe
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/632421
Reviewed-by: Gavin Mak <gavinmak@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
Tested-by: Victor Pushkarev <corvinus.v@gmail.com>
Commit-Queue: Victor Pushkarev <corvinus.v@gmail.com>
2026-09-26 01:17:45 -07:00
Ram Peri 9066409c2d init: don't suggest --no-use-superproject on failure
When the superproject can't be fetched, repo init warns and tells users
to re-run repo init with --no-use-superproject. That choice is saved in
the checkout config (repo.superproject), so following it disables the
superproject for that checkout until it is re-inited, even though these
failures are often transient.

Drop the recommendation and keep the rest of the warning.

This is the repo init counterpart of reverting
https://gerrit-review.googlesource.com/c/git-repo/+/305622 for repo sync
(https://gerrit-review.googlesource.com/c/git-repo/+/634804).

Bug: 565845573
Change-Id: I91a6e682ef1d1c6dee07bc7969de88a681e1d239
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/634784
Tested-by: Ram Peri <ramperi@google.com>
Reviewed-by: Sam Saccone <samccone@google.com>
Reviewed-by: Arif Kasim <arifkasim@google.com>
Commit-Queue: Ram Peri <ramperi@google.com>
2026-09-24 13:54:06 -07:00
Ram Peri 2908f596c5 Revert "sync: Recommend using --no-use-superproject if sync fails."
This reverts commit f907ced0fe.
Original change: https://gerrit-review.googlesource.com/c/git-repo/+/305622

Reason for revert: the hint was added when a superproject failure made
repo sync exit with an error. Since 8db30d6 the failure is non-fatal
and sync falls back to fetching normally, and these failures are often
transient (e.g. on 2026-09-23 a manifest change added
external/slackhq/compose-lints before the superproject had a commit
for it, until the change was reverted ~2h later). Following the hint
means users keep passing --no-use-superproject and bypass the
superproject even after the failure is gone.

The revert does not apply cleanly after the black reformat, so the
conflict was resolved by restoring the original message text.

Bug: 565845573
Change-Id: I5efadedd4d3d0002df50493fa29554ba9626fe82
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/634804
Commit-Queue: Ram Peri <ramperi@google.com>
Reviewed-by: Sam Saccone <samccone@google.com>
Tested-by: Ram Peri <ramperi@google.com>
2026-09-24 13:53:54 -07:00
Gavin Mak e1e215a14e project: don't plan a stateless prune without a worktree
Skip stateless prune planning when a project's worktree directory
does not exist, preventing fetch failures on subsequent syncs.

Also run _LsRemote() bare so it does not depend on worktree
existence.

Bug: 565047698
Change-Id: I385cba4e06813d9113ec7ddc963e8499acffaec5
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/634426
Tested-by: Gavin Mak <gavinmak@google.com>
Commit-Queue: Gavin Mak <gavinmak@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
v2.68.1
2026-09-23 13:27:06 -07:00
Gavin Mak 175198b0aa sync: skip the bloat check for projects without a worktree
Skip shallow clone bloat checks during --network-only syncs and
filter out projects whose worktree directory does not exist on disk.

Also return None quietly from _GetStatusSnapshot() when a project
lacks an existing worktree directory.

Bug: 565047698
Change-Id: Ia4c7db36a2bd78bc89e7b72f7a492b901b50efa7
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/634425
Commit-Queue: Gavin Mak <gavinmak@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
Tested-by: Gavin Mak <gavinmak@google.com>
2026-09-23 13:27:01 -07:00