summaryrefslogtreecommitdiffstats
path: root/subcmds
Commit message (Collapse)AuthorAgeFilesLines
* info: reuse branch snapshots and combine history walksv2.68Gavin Mak2026-09-211-26/+58
| | | | | | | | | | | | | | Derive the current branch from GetBranches so attached HEAD and refs are resolved once, including overview reporting. Replace the two complementary rev-list calls in --all output with one --left-right symmetric-difference walk and partition its records in memory. Bug: 553599402 Change-Id: I01d5db804cbf591ecc0e08d6605971f0f5a38538 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/634005 Tested-by: Gavin Mak <gavinmak@google.com> Reviewed-by: Brian Gan <brgan@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com>
* project: make fast-forward merges explicitGavin Mak2026-09-211-1/+1
| | | | | | | | | | | | | Every caller expects _FastForward to reject a merge commit. Always pass --ff-only and remove the optional parameter so a violated ancestry assumption fails instead of silently creating a merge. Bug: 553599402 Change-Id: I04690b5ca675cb7d3062df08d5e20cd82f5b9e82 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/634003 Tested-by: Gavin Mak <gavinmak@google.com> Reviewed-by: Brian Gan <brgan@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com>
* sync: reuse status HEAD in the bloat scanGavin Mak2026-09-211-2/+15
| | | | | | | | | | | | | | | The shallow-project bloat check already needs dirty state. Request branch metadata in that same porcelain-v2 snapshot and use branch.oid instead of launching a separate rev-parse, with the existing calls retained as a fallback. Bug: 543851900 Bug: 553599402 Change-Id: I3e7068c2e14c025a53adf92bfe8483b876cfda9d Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/632145 Tested-by: Gavin Mak <gavinmak@google.com> Reviewed-by: Brian Gan <brgan@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com>
* command: preserve project filters in regex selectionVictor Pushkarev2026-09-162-3/+10
| | | | | | | | | | | | | | | | | | | | | | | | `FindProjects` gets its candidate projects from `GetProjects` and then applies regex matching. However, it only forwards `all_manifests`, so other project filters are lost on regex paths. As a result, `repo forall -r/-i --groups` falls back to the configured group selection instead of using the requested groups. Similarly, `repo list -r --groups` ignores the requested groups, and `repo list -r --all` still excludes projects without a checkout. Pass `groups` and `missing_ok` through `FindProjects`, and forward the existing options from `forall` and `list`. When no group override is given, keep using each manifest's effective groups. Add regression tests for `FindProjects` and both command paths. Change-Id: I5dfc22172fdd81de5312a84433867300a1342aec Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/631281 Reviewed-by: Mike Frysinger <vapier@google.com> Reviewed-by: Gavin Mak <gavinmak@google.com> Commit-Queue: Victor Pushkarev <corvinus.v@gmail.com> Tested-by: Victor Pushkarev <corvinus.v@gmail.com>
* sync: keep generated jobs-checkout help host-independentVictor Pushkarev2026-09-161-1/+3
| | | | | | | | | | | | | | | | | | | | | The default shown for `--jobs-checkout` comes from `DEFAULT_LOCAL_JOBS`, which depends on the host CPU count. As a result, regenerating the sync and smartsync manpages on a different machine can change their output even though repo's behavior has not changed. Use shared CPU-based help formatting for `--jobs` and `--jobs-checkout`. Interactive help still shows the actual default, while generated manpages describe it without including a host-specific value. Runtime job selection is unchanged. Add coverage for both help modes and regenerate the affected manpages. Change-Id: Ia60e6fcc17b6f4618c52a76217c128eddead8848 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/625381 Reviewed-by: Mike Frysinger <vapier@google.com> Commit-Queue: Victor Pushkarev <corvinus.v@gmail.com> Tested-by: Victor Pushkarev <corvinus.v@gmail.com> Reviewed-by: Gavin Mak <gavinmak@google.com>
* sync: implement reprojectcmd for the local halfGavin Mak2026-09-151-0/+47
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Add `repo.reprojectcmd`, the checkout counterpart to `repo.fetchcmd`. When set, `repo sync` runs this command instead of Git to materialize a project's index and worktree at the target tree, while `repo` handles ref updates directly via `git update-ref`. This replaces Git's tree materialization steps: detaching HEAD, fast-forwarding, and hard-resetting. Rebasing is not delegated, and the command is skipped if HEAD is already at the target, if HEAD is ahead of the target during fast-forward, or for MetaProjects. The command runs in a subshell with project environment variables (such as `REPO_TREV`). Before running, `repo` ensures no operation is in progress and no staged changes exist. Worktree collision detection is delegated to the command (preserving benign unstaged/untracked edits). Afterward, `repo` verifies that HEAD was untouched and that the index matches the target tree. Like `repo.fetchcmd`, this requires `repo.uselocalgitdirs`. Nested projects and submodules are unsupported; `repo sync` fails if the manifest contains any while `repo.reprojectcmd` is enabled. Verified end-to-end with repo init using local-gitdirs, repo.fetchcmd, and repo.reprojectcmd ('git -C $REPO_PATH read-tree -m -u $REPO_TREV'): * Verified detached HEAD checkout and correct reflog generation across projects. * Verified benign unstaged edits and untracked files survive checkout. * Verified conflicting untracked files fail with exit 128 without clobbering worktree. * Verified staged changes fail upfront before reprojectcmd is executed. Bug: 513329573 Change-Id: I964d24d22dccffc05a9b991ad69f3a7e93268c01 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/626281 Tested-by: Gavin Mak <gavinmak@google.com> Reviewed-by: Brian Gan <brgan@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com>
* upload: bypass branch editor with explicit branch and -yArif Kasim2026-09-091-0/+12
| | | | | | | | | | | | | | | | | | When uploading across multiple projects with --yes and an explicit branch specified (via --current-branch / -c or --branch / --br), repo previously still opened the interactive branch selection editor. If an explicit branch and --yes are provided, bypass the interactive editor and upload all matching pending branches directly. Bug: 553024110 Test: python3 -m pytest tests/ Test: flake8 subcmds/upload.py tests/test_subcmds_upload.py Test: isort --check subcmds/upload.py tests/test_subcmds_upload.py Change-Id: I104619603f6e0539d05b01d3eb0292a9145d58db Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/622661 Tested-by: Arif Kasim <arifkasim@google.com> Reviewed-by: Gavin Mak <gavinmak@google.com>
* upload: reuse the worker current-branch resultGavin Mak2026-09-021-3/+4
| | | | | | | | | | | | Carry the current branch through _GatherOne so the parent can report a failed current-branch upload without resolving HEAD a second time. Bug: 553599402 Change-Id: I3fc54be6c10c30470e14f792ff68c0a396519327 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/623905 Reviewed-by: Brian Gan <brgan@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com> Tested-by: Gavin Mak <gavinmak@google.com>
* version: read describe and date in one Git callGavin Mak2026-09-021-2/+20
| | | | | | | | | | | | | | Git 2.32 added the %(describe) pretty placeholder. Use one log format to retrieve both repo's describe string and commit date on newer clients, with the existing describe-plus-log path retained for older Git and untagged output. Bug: 553599402 Change-Id: I108346030677b2b90ef8bfb5acea1c45be2c85f2 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/623904 Tested-by: Gavin Mak <gavinmak@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com> Reviewed-by: Brian Gan <brgan@google.com>
* cherry_pick: resolve and read commits in one processGavin Mak2026-09-021-30/+45
| | | | | | | | | | | | | | Send a typed revision expression to cat-file --batch over stdin and parse its object header and exact byte length. This safely resolves the commit OID and retrieves its raw message in one Git process instead of separate rev-parse and cat-file calls. Bug: 553599402 Change-Id: I764894323ec28e134f2523bd1d5694738b6b52d0 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/623903 Reviewed-by: Brian Gan <brgan@google.com> Tested-by: Gavin Mak <gavinmak@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com>
* rebase: delegate automatic stashing to GitGavin Mak2026-09-021-19/+2
| | | | | | | | | | | | | | Git --autostash predates repo's minimum supported client. Pass it directly to rebase instead of probing the index and separately running stash and stash pop, reducing the dirty path from four Git processes to one and correctly covering staged-only changes. Bug: 553599402 Change-Id: I0d6d59b17996576310498e9378e49380d355236e Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/623902 Tested-by: Gavin Mak <gavinmak@google.com> Reviewed-by: Brian Gan <brgan@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com>
* sync: tell apart same-path submanifest projectskimhappy2026-09-011-4/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Interleaved sync remembers which projects are done and which ones are still pending by Project.relpath, and lists failing projects by it as well. That path is relative to the project's own (sub)manifest though, so once several manifests are synced together two projects can share it, and the sets no longer tell them apart. The damage is done when a project turns up in a later pass, e.g. a submodule that is only derived once its parent has been synced: its path is already recorded as finished, so it is left out of every pass that follows and never synced, while sync still reports success. With an outer manifest holding <project name="a" path="a" sync-s="true"/> where a carries a submodule at b, and a submanifest at sub/ holding <project name="sub-ab" path="a/b"/> a fresh `repo sync` checks out sub/a/b but never a/b. Failing projects are reported under the same ambiguous path, and the stall detection merges them too. Use RelPath(local=opt.this_manifest_only) instead, which is unique within the set of projects being synced and is what GetProjects() and the other subcommands already use. Spotted during the review of I30395b8a16a9154f60972e1f408a066af64ba77c. Change-Id: I5fa694b968774667be6060d9722cb57acbd2b579 Signed-off-by: kimhappy <hwanhee.kim@laplacian.cc> Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/622641 Reviewed-by: Gavin Mak <gavinmak@google.com> Reviewed-by: Brian Gan <brgan@google.com>
* project: carry current state from the ref snapshotGavin Mak2026-08-312-5/+10
| | | | | | | | | | | | | Attach the current marker computed by GetBranches to uploadable and prunable branches. Overview and prune reporting can then reuse that result instead of resolving HEAD once per displayed branch. Bug: 553599402 Change-Id: Ie3e23d08d0caf66c47cc12d7295ec4b6a834560c Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/623184 Commit-Queue: Gavin Mak <gavinmak@google.com> Reviewed-by: Brian Gan <brgan@google.com> Tested-by: Gavin Mak <gavinmak@google.com>
* project: centralize safe branch and commit resolutionGavin Mak2026-08-312-6/+4
| | | | | | | | | | | | | | | Resolve commit-ish values through one typed helper using rev-parse --verify --quiet and, on Git 2.30+, --end-of-options. Reject option-like revisions on older clients, reuse the helper for project and manifest resolution, and validate user branch names with check-ref-format --branch. Bug: 553599402 Change-Id: I2dda49ff3e781cec14d3b84263a8dace06b4073f Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/623182 Tested-by: Gavin Mak <gavinmak@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com> Reviewed-by: Brian Gan <brgan@google.com>
* upload: prune ref scans for untouched projects and specific branchesJames Hawkins2026-08-281-18/+11
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Benchmark (100 untouched projects): * GetUploadableBranches: 0.985s -> 0.0004s (2,200x faster) * repo upload (3,045 projects): saves ~2.5s of redundant ref scans During `repo upload`, `GetUploadableBranches()` currently scans `self._allrefs` across all projects in the workspace. In large manifests (e.g. Android with 3,000+ projects), `self._allrefs` executes `git for-each-ref`, `git symbolic-ref`, and full filesystem mtime traversals on thousands of projects where no local branch was ever started or modified. Any branch that can be uploaded for review must have upstream tracking configured via `[branch "..."]` sections in `.git/config` (otherwise `branch.LocalMerge` is None and `GetUploadableBranch` returns None). This patch introduces early-pruning fast paths: 1. When no branch subsections exist in `.git/config` (or only 2-part keys like `branch.autosetupmerge`), return [] immediately without touching `_allrefs`. 2. When a `selected_branch` is specified (e.g. `repo upload --br=...`), query `branch.LocalMerge`, `refs/heads/<branch>`, and `refs/published/<branch>` directly, skipping the whole-tree ref scan. 3. In `subcmds/upload.py`, optimize `_GetMergeBranch` to resolve the merge branch in-memory via `project.CurrentBranch` and `project.GetBranch()` instead of spawning two `GitCommand` processes. Test: ./run_tests tests/test_project.py tests/test_subcmds_upload.py Change-Id: I3c2c9d63a68a393d478e1fb50f548ec8b7d44639 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/623021 Reviewed-by: Brian Gan <brgan@google.com> Commit-Queue: James Hawkins <jhawkins@google.com> Tested-by: James Hawkins <jhawkins@google.com>
* sync: skip submodules removed from their parentkimhappy2026-08-271-4/+28
| | | | | | | | | | | | | | | | | | | | | | | | | | The submodules to sync are derived from their parent before it is fetched, so one that the parent's new revision no longer holds a gitlink for is still synced. Interleaved sync then fails to check it out, because `git submodule init` no longer knows that path: error: Cannot checkout a/c error: pathspec '.../a/c' did not match any file(s) known to git Report such submodules while the gitlinks are read again, and leave them out of the fetch and of the checkout, so the usual project list update removes them from the working tree. Phased sync already left them out of the checkout, but still fetched them. Nothing is reported as removed while the gitlinks of a parent cannot be read, since a missing gitlink cannot be told apart from a fetch that did not happen. Bug: 550074864 Change-Id: Ia429b35c12758a68e4df73665e5512a201af658a Signed-off-by: kimhappy <hwanhee.kim@laplacian.cc> Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/621681 Reviewed-by: Gavin Mak <gavinmak@google.com> Reviewed-by: Brian Gan <brgan@google.com>
* sync: fetch submodules after their parent repositorykimhappy2026-08-271-6/+58
| | | | | | | | | | | | | | | | | | | | | | Phased sync fetches every project at once, so a submodule is fetched at the gitlink that was read before its parent was fetched. With -c that stale revision is already present, the fetch is skipped as an immutable revision, and the checkout then fails on the revision the reloaded manifest resolved: error: Cannot checkout a/b fatal: bad object 5556dad99da5df7e53303c5732aacc8782493e03 Fetch in batches, holding a submodule back until the project holding its gitlink is fetched, and read the gitlinks again between batches. A manifest without submodules keeps its single batch. Bug: 550074864 Change-Id: I04c2eb1ca81ab25b4df2c03c5dc048d2e4ecdcb8 Signed-off-by: kimhappy <hwanhee.kim@laplacian.cc> Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/621663 Reviewed-by: Gavin Mak <gavinmak@google.com> Reviewed-by: Brian Gan <brgan@google.com>
* sync: check out submodules at the parent's new revisionkimhappy2026-08-271-1/+46
| | | | | | | | | | | | | | | | | | | | | Interleaved sync processes projects in hierarchical levels, so a submodule is only handled after the project holding its gitlink has been fetched and checked out. Its revision, however, is still the one read before that parent was fetched, so the submodule is synced to the revision of the previous sync and only catches up on the next one. Read the gitlinks again right before a level is dispatched. The parent is done by then, so its submodules are fetched and checked out at the revision the parent now points at. Sibling submodules are spread over several levels, so the gitlinks read for one level are carried over to the next ones and every project is only read once per pass. Bug: 550074864 Change-Id: I30395b8a16a9154f60972e1f408a066af64ba77c Signed-off-by: kimhappy <hwanhee.kim@laplacian.cc> Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/621662 Reviewed-by: Gavin Mak <gavinmak@google.com> Reviewed-by: Brian Gan <brgan@google.com>
* hooks: add --fix option to auto-apply hook fixesRahul Yadav2026-08-271-1/+1
| | | | | | | | | | | | | | | | | | | | Pass the --fix flag as a keyword argument "fix" to the hook main function. This allows hooks (such as git-repohooks) to decouple automated fix application from the -y/--yes flag so that -y can answer yes to upload confirmation prompts without triggering file mutations. Companion change in git-repohooks: https://gerrit-review.googlesource.com/c/git-repohooks/+/621761 Bug: 546510319 Test: python3 -m pytest tests/test_hooks.py Change-Id: If0288d4791fc0a2aba6e88854e3aa81b0923b664 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/619281 Commit-Queue: Rahul Yadav <yadavrah@google.com> Tested-by: Rahul Yadav <yadavrah@google.com> Reviewed-by: Gavin Mak <gavinmak@google.com>
* Add detailed upload context to Trace2 telemetryRam Peri2026-08-261-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This patch intercepts the output during a successful upload execution to capture the generated CL URLs. It logs a dynamically constructed "repo.uploadstate" data event to the active trace2 log containing: - Uploaded CL URLs - Target remote name - Source branch - Modified files Test: 1. ./run_tests 2. pytest tests/test_project.py 3. Manual verification: - Created a dummy branch `test_upload_branch` in a project with local file changes. - Invoked repo upload passing an explicit trace output directory: `repo --git-trace2-event-log=/tmp/trace2out upload --dry-run --no-verify art` - Verified the injected payload successfully appeared on disk within the generated log: ```json {"event":"data",..."key":"repo.uploadstate/cls","value":""} {"event":"data",..."key":"repo.uploadstate/remote","value":"goog"} {"event":"data",..."key":"repo.uploadstate/branch","value":"test_upload_branch"} {"event":"data",..."key":"repo.uploadstate/files","value":"dummy_file.txt"} ``` (cls is correctly blank on --dry-run but populates on real HTTP pushes) Bug: 543953499 Change-Id: I9c402a32d01d156d42cf24eaa2e60e22710b5e6f Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/616581 Reviewed-by: Gavin Mak <gavinmak@google.com> Tested-by: Ram Peri <ramperi@google.com> Commit-Queue: Ram Peri <ramperi@google.com>
* command: Respect smart sync override declaratively by defaultGavin Mak2026-08-046-6/+2
| | | | | | | | | | | | | | | | | | | | | | | Introduce a `RESPECT_SMART_SYNC_OVERRIDE` class attribute to the base `Command` class, defaulting to `True`. This allows subcommands to automatically respect the smart sync override manifest if it exists. The override is applied in `CommonValidateOptions` before any subcommand-specific validation or execution occurs. The `sync` and `init` commands explicitly opt out. This ensures all workspace-aware subcommands consistently align with the active smart sync override manifest. It also fixes a bug in multi-manifest setups where running a command from a submanifest would not apply the override to the outer manifest, causing inconsistency when resolving projects across all manifests. Bug: 279204331 Change-Id: I9426e90a13a77ce6bd94b4a82efda4d485cbe116 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/585081 Reviewed-by: Mike Frysinger <vapier@google.com> Tested-by: Gavin Mak <gavinmak@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com>
* sync: allow syncing groups with repo sync -g groupAndrew Chant2026-07-211-0/+11
| | | | | | | | | | | | | | Similar to how repo init -g can restrict repo syncs to a subset of the manifest globally, allow "repo sync -g" to only sync a subset of projects from the manifest when running that specific sync command. Change-Id: I4929aad109de05c73a7db42bb27fd8d47eea32fc Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/609481 Reviewed-by: Mike Frysinger <vapier@google.com> Commit-Queue: Andrew Chant <achant@google.com> Reviewed-by: Gavin Mak <gavinmak@google.com> Tested-by: Andrew Chant <achant@google.com>
* sync: Deprecate fetch-submodules flag namesJosef Malmström2026-07-211-12/+38
| | | | | | | | | | | | | | | | The names for flags --fetch-submodules / --no-fetch-submodules are misleading, since they impact the full sync operation (fetch and checkout), not just the fetching. Introduce new flags --recurse-submodules / --no-recurse-submodules and treat the old ones as deprecated aliases. Change-Id: I78339a3e0496a855c222c1869b27b578507886a7 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/608881 Commit-Queue: Josef Malmstrom <Josef.Malmstrom@arm.com> Reviewed-by: Gavin Mak <gavinmak@google.com> Reviewed-by: Mike Frysinger <vapier@google.com> Tested-by: Josef Malmstrom <Josef.Malmstrom@arm.com>
* sync: Add CLI flag for globally disabling submodule fetchJosef Malmström2026-07-161-1/+8
| | | | | | | | | | | | | | | | 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>
* rebase: Resolve revisionExpr to tracking branch for --onto-manifestGavin Mak2026-07-071-1/+14
| | | | | | | | | | | | | | | | | | When running `repo rebase -m` (`--onto-manifest`), the command uses the raw `revisionExpr` from the manifest (e.g. `main`) directly as the `--onto` target. This can fail or behave incorrectly if it should reference the local tracking branch (e.g. `refs/remotes/<remote>/main`). Resolve `project.revisionExpr` to its local tracking branch using `project.GetRemote().ToLocal()`. Fall back to using the raw `revisionExpr` value if the resolution fails (raising a `GitError`). Bug: 532028666 Change-Id: I4c1bca1374a5842688be227f6aa2afffcdad5397 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/604941 Reviewed-by: Brian Gan <brgan@google.com> Tested-by: Gavin Mak <gavinmak@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com>
* status: Show ahead/behind info for local branchesBrian Gan2026-06-301-0/+6
| | | | | | | | | | | | | | | | | When viewing `repo status`, it is difficult to distinguish between branches that have active unpushed changes and stale branches that are fully synced. Previously, developers had to run commands like `repo forall -c "git status"` to see their ahead/behind counts. This change updates Project.PrintWorkTreeStatus to automatically calculate and display the number of commits a branch is ahead and/or behind its upstream tracking branch. We use `git rev-list --left-right --count` to fetch this information natively and efficiently. If the branch is completely synced with upstream, no extra text is shown. Added tests for ahead-only, behind-only, diverged, no-tracking, and fully-synced branch states. Bug: 319412954 Change-Id: I23879b2d472c7a7e11d01b565428a84b1b4f09c1 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/602423 Reviewed-by: Gavin Mak <gavinmak@google.com> Tested-by: Brian Gan <brgan@google.com> Commit-Queue: Brian Gan <brgan@google.com>
* info: Parallelize project data gathering for JSON outputGavin Mak2026-06-301-2/+24
| | | | | | | | | | | | | | | | | | | | https://gerrit-review.googlesource.com/c/git-repo/+/581921 parallelized `repo info` for text output. This commit does the same for JSON output format. Benchmarked `repo info --format=json` on an Android workspace with ~3k projects (N=3): - Before (sequential): 1m 30s average - After (parallelized): 46s average (~2x speedup) Verified that the JSON output is identical before and after. Bug: 526685287 Change-Id: If573223aba584f8b932f87d29e34ed565c5c930a Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/601861 Commit-Queue: Gavin Mak <gavinmak@google.com> Reviewed-by: Brian Gan <brgan@google.com> Tested-by: Gavin Mak <gavinmak@google.com>
* info: Report actual checked-out HEAD revisionGavin Mak2026-06-291-2/+3
| | | | | | | | | | | | | | | | When `repo info` runs, the reported "Current revision" is resolved using the manifest's target branch tracking ref (e.g. refs/remotes/goog/main). Introduce Project.GetHeadRevisionId(), which gets the checked-out HEAD commit in the worktree, and use it in `repo info` with a fallback to the old behavior if the project is not checked out. Bug: 526685287 Change-Id: I72280ce27daa210cada27d722a94e365644f06e0 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/599481 Reviewed-by: Brian Gan <brgan@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com> Tested-by: Gavin Mak <gavinmak@google.com>
* sync: Support pluggable remote helpers for smart sync manifest server.Rahul Yadav2026-06-181-29/+146
| | | | | | | | | | | | | | Introduce support for pluggable remote helpers (declared via the optional 'helper' attribute in <manifest-server>) to dynamically resolve proxy addresses. Route the XML-RPC manifest server connection through the resolved proxy. Bug: b/517477903 Change-Id: I3b6b8ea2640bb077521df4b4a9e8a34a8c6ecdad Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/591642 Tested-by: Rahul Yadav <yadavrah@google.com> Commit-Queue: Rahul Yadav <yadavrah@google.com> Reviewed-by: Gavin Mak <gavinmak@google.com>
* project: Add REPO_PROJECT_FETCH_URL environment variableGavin Mak2026-06-161-0/+2
| | | | | | | | | | | | | Add REPO_PROJECT_FETCH_URL to Project.GetEnvVars(), which resolves to the remote fetch URL of the project. This is useful for exposing the URL to custom fetch commands or other external scripts. Bug: 513329573 Change-Id: Ic2b0a83493934d16bb1152366ee4e1a2c35ea2dc Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/596121 Tested-by: Gavin Mak <gavinmak@google.com> Reviewed-by: Mike Frysinger <vapier@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com>
* sync: do not init sibling submodules in parallelJosef Malmström2026-06-161-11/+27
| | | | | | | | | | | | | | | | | | | Initializing a submodule requires locking <parent>/.git/config. As the implementation was currently doing this in parallel for sibling submodules, it lead to a race condition causing intermittent errors like: error: could not lock config file .git/config: File exists This commit enforces that sibling submodules are initialized sequentially, eliminating the race condition. Change-Id: I5ffb3de90276ba43e262d0e279a3d34324220b63 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/591241 Tested-by: Josef Malmstrom <Josef.Malmstrom@arm.com> Commit-Queue: Josef Malmstrom <Josef.Malmstrom@arm.com> Reviewed-by: Mike Frysinger <vapier@google.com> Reviewed-by: Gavin Mak <gavinmak@google.com>
* project: Extract project envvar generation to GetEnvVarsGavin Mak2026-05-271-20/+2
| | | | | | | | | | | | Move project environment variable setup from subcmds/forall.py to a reusable Project.GetEnvVars() helper method. Bug: 513329573 Change-Id: I3b4b113aa5a086e5fa5eaf4461c7ce517d928610 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/583881 Tested-by: Gavin Mak <gavinmak@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com> Reviewed-by: Mike Frysinger <vapier@google.com>
* init: Add --use-local-gitdirs for standard Git layoutsGavin Mak2026-05-261-0/+1
| | | | | | | | | | | | | Introduce --use-local-gitdirs to bypass repo's symlink-based layouts in favor of standard local .git directories. Bug: 513329573 Bug: 508146070 Change-Id: I53d1602e61be0b86964529bcbea3dc801471f9c9 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/569001 Tested-by: Gavin Mak <gavinmak@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com> Reviewed-by: Dan Willemsen <dwillemsen@google.com>
* sync: Add --superproject-rev flag to sync to specific revisionv2.64Gavin Mak2026-05-201-7/+78
| | | | | | | | | | | | | | | | | Allow syncing the outer manifest to a state defined by a specific superproject revision. It updates the superproject, reads the manifest commit from .supermanifest, and checks out the outer manifest project to that commit. Submanifests are then processed normally, allowing them to be updated to the revisions specified in the new outer manifest state. Bug: 416589884 Change-Id: I304c37a2b8794f9b74cb7e5e209a8a93762bdb52 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/576321 Commit-Queue: Gavin Mak <gavinmak@google.com> Tested-by: Gavin Mak <gavinmak@google.com> Reviewed-by: Mike Frysinger <vapier@google.com>
* abandon/start/info: Make them respect smart sync overrideGavin Mak2026-05-143-0/+4
| | | | | | | | | | | | | | | | Call TryOverrideManifestWithSmartSync in start, abandon, and info commands. This ensures they pick up the pinned revisions from the smart sync override manifest if it exists, rather than falling back to ToT from the default manifest. Bug: 279204331 Change-Id: I637f054a77773805daf0bf9cf5a712d82a5959b4 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/582503 Reviewed-by: Mike Frysinger <vapier@google.com> Tested-by: Gavin Mak <gavinmak@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com>
* command: Move smart sync override logic to Command base classGavin Mak2026-05-142-10/+2
| | | | | | | | | | | | | Deduplicate the logic for loading `smart_sync_override.xml` by moving it from `forall.py` to the `Command` base class. This allows other commands to reuse it to respect smart tags. Bug: 279204331 Change-Id: I6f2f03995266c2a68c3225cacb92b2f580a89178 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/582502 Tested-by: Gavin Mak <gavinmak@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com> Reviewed-by: Mike Frysinger <vapier@google.com>
* linkfile: Handle directory-to-symlink transitions safelyCarlos Fernandez2026-05-121-7/+27
| | | | | | | | | | | | | | | | | | | | | | | | | | When a manifest changes from individual linkfiles inside a directory (e.g. dest=".llms/rules", dest=".llms/skills") to a single linkfile for the whole directory (e.g. dest=".llms", src="dot-llms"), two things need to happen: 1. __linkIt must replace a real directory with a symlink. Use os.rmdir() instead of platform_utils.remove() for real directories. rmdir only removes empty directories, so user-created content is never deleted. 2. UpdateCopyLinkfileList must handle the cleanup correctly: - Use os.rmdir() for directories (safe for non-empty) - Remove empty parent directories after cleaning old dests - Retry _CopyAndLinkFiles for all projects, since in interleaved sync mode _CopyAndLinkFiles runs before cleanup and may have failed because the directory was not yet empty Change-Id: I0437b80beab98bce064cea81c11c47d699be91aa Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/569243 Tested-by: Carlos Fernandez <carlosfsanz@meta.com> Reviewed-by: Mike Frysinger <vapier@google.com> Reviewed-by: Gavin Mak <gavinmak@google.com> Commit-Queue: Carlos Fernandez <carlosfsanz@meta.com>
* sync: Re-raise KeyboardInterrupt in main processGavin Mak2026-05-121-0/+8
| | | | | | | | | | | | | | | | When running sync -j1, worker functions run directly in the main process. Swallowing KeyboardInterrupt causes the loop to continue to the next project instead of aborting. Re-raise KeyboardInterrupt if running in the MainProcess, while maintaining the suppression of stack traces in worker processes. Bug: 468170157 Change-Id: I156d66bc209a265f7fa25eea0eb88737d1b51a34 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/581342 Commit-Queue: Gavin Mak <gavinmak@google.com> Reviewed-by: Mike Frysinger <vapier@google.com> Tested-by: Gavin Mak <gavinmak@google.com>
* info: Parallelize repo info to improve performanceGreg Edelston2026-05-121-93/+177
| | | | | | | | | | | | | | | | | | | | | For a large checkout like chromiumos or android, `repo info` takes a really long time! On my machine it took ~6 minutes. On a randomly selected ChromiumOS cq-orchestrator build it took 4.1 minutes: https://ci.chromium.org/b/8682060180498819729. This adds up to a lot of wasted runtime for both humans and bots. The problem is that `repo info` was single-threaded, which causes poor performance when the checkout has 1000+ projects. We already have a pattern for parallelization; let's use it. BUG=None TEST=Manually run, ensure no diff Change-Id: I6b82b9495eb2a0e602a142dd3a16f09217871e1b Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/581921 Tested-by: Greg Edelston <gredelston@google.com> Commit-Queue: Greg Edelston <gredelston@google.com> Reviewed-by: Mike Frysinger <vapier@google.com>
* sync: Exclude stateless sync pruned projects from bloat checkGavin Mak2026-05-111-1/+5
| | | | | | | | | | | | If a project has been pruned for stateless sync, it has already undergone aggressive garbage collection. There should be no bloat to check for. Change-Id: I9233a4611e05b7a0b7c097827d6f408144f7380d Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/581841 Tested-by: Gavin Mak <gavinmak@google.com> Reviewed-by: Becky Siegel <beckysiegel@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com>
* sync: Suggest "git repack -a -d" in bloat warningGavin Mak2026-05-081-2/+2
| | | | | | | | | | | | | | | | | | The warning suggests running "repo sync --auto-gc" which runs "git gc --auto". Git may decide not to repack if its internal thresholds are not met, leaving the warning active even after running the suggested command. "git repack -a -d" forces all reachable objects into a single pack and deletes redundant packs, reducing the pack count to 1. This guarantees that the warning (which triggers when pack count exceeds 10) goes away. Bug: 505755299 Change-Id: I10163ef8efb7f3b7c5055378ad95051974d11b88 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/580821 Reviewed-by: Becky Siegel <beckysiegel@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com> Tested-by: Gavin Mak <gavinmak@google.com>
* forall: Document REPO_UPSTREAM and REPO_DEST_BRANCH envvarsGavin Mak2026-05-071-0/+6
| | | | | | | Change-Id: I74365295152f8828587c6b4ed93029efc6000881 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/580761 Tested-by: Gavin Mak <gavinmak@google.com> Reviewed-by: Mike Frysinger <vapier@google.com>
* info: add --format and --include-summary/--include-projects optionsCarlos Fernandez2026-05-071-19/+131
| | | | | | | | | | | | | | | | | | | Add --format={text,json} to produce machine-readable output, and boolean options to control which sections are displayed: --include-summary / --no-include-summary (default: on) --include-projects / --no-include-projects (default: on) The JSON output respects the include flags, so callers can request only the fields they need (e.g. `repo info --format=json --no-include-projects` for manifest metadata only). Change-Id: I9641bc4023b630d9c61c5170eb86e5f3b787236f Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/569203 Commit-Queue: Carlos Fernandez <carlosfsanz@meta.com> Reviewed-by: Mike Frysinger <vapier@google.com> Reviewed-by: Gavin Mak <gavinmak@google.com> Reviewed-by: Carlos Fernandez <carlosfsanz@meta.com> Tested-by: Carlos Fernandez <carlosfsanz@meta.com>
* Add timing keyword argument for hooksRam Peri2026-04-211-3/+8
| | | | | | | | | | | | | | | | | | | | | Measure the duration of the sync operation in the Execute method of the Sync command and pass it to post-sync hooks as a standard keyword argument (`sync_duration_seconds`). Updates based on code review: - Update _API_ARGS in hooks.py to allow sync_duration_seconds for post-sync hooks. - Do not cast sync_duration_seconds to int for better granularity. - Update docs/repo-hooks.md to document sync_duration_seconds. - Add unit test for argument validation in test_hooks.py. Test: Ran run_tests using venv python, all 554 tests passed. Bug: TBD Change-Id: Ie29e002a5d283460d993ad96c224dbf4b6d7985c Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/575021 Tested-by: Arif Kasim <arifkasim@google.com> Commit-Queue: Ram Peri <ramperi@google.com> Reviewed-by: Arif Kasim <arifkasim@google.com> Reviewed-by: Gavin Mak <gavinmak@google.com>
* sync: Refactor to use _RunOneGC and fix config leakagev2.63Gavin Mak2026-04-201-8/+23
| | | | | | | | | | | | | | | | Extract _RunOneGC to handle GC on a single project. This refactoring makes it easier to invoke GC from parallel worker tasks. Also, avoid modifying the passed-in config dictionary in _RunOneGC by creating a local copy, preventing unintended side effects on other commands sharing the same config. Bug: 498290329 Change-Id: I7b77ed6629b14b5ee3322870b9c6c8ce2bfd6ea2 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/574923 Reviewed-by: Becky Siegel <beckysiegel@google.com> Tested-by: Gavin Mak <gavinmak@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com>
* sync: Switch to using self._bloated_projectsGavin Mak2026-04-201-11/+11
| | | | | | | | | | | | Store bloated projects in self._bloated_projects and print warnings at the end of execution. This sets up for moving the check to workers. Bug: 498290329 Change-Id: I993f1fd741db2994d480994861588eb18f6c5503 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/574922 Reviewed-by: Becky Siegel <beckysiegel@google.com> Tested-by: Gavin Mak <gavinmak@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com>
* upload: Clarify partial sync message on hook failureMarty Heavey2026-04-201-3/+4
| | | | | | | | | | | | | | | Demote the partial sync warning from error to info and rephrase it to be a tip rather than an error. This prevents users from thinking that a partial sync is the cause of their hook failures when it is often a linting failure. The message now suggests that a full sync might help if there are cross-project dependencies, instead of implying it will fix any issue. Change-Id: I5d8c52b53ac315aa9f145ed069798bf201fa0815 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/574262 Tested-by: Marty Heavey <mheavey@google.com> Commit-Queue: Marty Heavey <mheavey@google.com> Reviewed-by: Gavin Mak <gavinmak@google.com>
* sync: Provide feedback during post-sync operationsGavin Mak2026-04-171-0/+3
| | | | | | | | | | | | | After the main sync progress bar finishes, there's a pause while some post-sync operations run. Print something to provide feedback so the user doesn't think repo has hung. Bug: 503869525 Change-Id: I695fd560e60dcb394e6844a56c8a336ca1f71c74 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/574425 Commit-Queue: Gavin Mak <gavinmak@google.com> Reviewed-by: Becky Siegel <beckysiegel@google.com> Tested-by: Gavin Mak <gavinmak@google.com>
* gc: Fix hang during repack in partial clonesGavin Mak2026-04-081-4/+13
| | | | | | | | | | | | | | | | | | | Add `--missing=allow-promisor` to `git rev-list` calls in `repack_projects`. This prevents Git from auto-fetching missing objects from the promisor remote, which can cause stalls due to sequential network requests. Also add a Git version check to ensure Git is at least 2.17.0 before running `--repack`, as `--missing=allow-promisor` was introduced in that version. Bug: 500133631 Change-Id: I2dcf9b46fac4c6a53a3c2a46f06f61d6aec40f2f Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/570361 Reviewed-by: Mike Frysinger <vapier@google.com> Tested-by: Gavin Mak <gavinmak@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com> Reviewed-by: Sam Saccone <samccone@google.com>
* Fix all flake8 warnings from newer flake8-bugbear and flake8-comprehensionsCarlos Fernandez2026-04-033-8/+6
| | | | | | | | | | | | | | | | | | | | | | | Address warnings introduced by flake8-bugbear 24.12.12 and flake8-comprehensions 3.16.0: - C408: Replace dict()/list() calls with literal {} and [] - C413: Remove unnecessary list() around sorted() - C414: Remove unnecessary list() inside sorted() - C419: Suppress intentional list comprehension in all() (noqa) - B001: Replace bare except with except Exception - B006: Replace mutable default arguments with None - B010: Replace setattr() with direct attribute assignment - B017: Use RuntimeError instead of Exception in tests - B019: Suppress lru_cache on methods for long-lived objects (noqa) - B033: Remove duplicate item in set literal Change-Id: If4693d3e946200bbc22f689f7b94da604addcb80 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/566321 Tested-by: Carlos Fernandez <carlosfsanz@meta.com> Commit-Queue: Carlos Fernandez <carlosfsanz@meta.com> Reviewed-by: Mike Frysinger <vapier@google.com> Reviewed-by: Gavin Mak <gavinmak@google.com>