2272 Commits
Author SHA1 Message Date
Gavin Mak 1702d7fb55 project: avoid git spawns in custom fetch ref checks
During _CustomFetch, GetEnvVars resolves REPO_LREV via GetRevisionId
before fetchcmd runs, and postcondition checks afterward run ResolveRef
on the tracking ref and FETCH_HEAD. On cold clones, missing branches, or
packed-refs tracking refs, GetRevisionId fell back to ResolveCommit,
spawning `git rev-parse <rev>^{commit}` and peeling objects from lazily
populated object stores such as ABFS.

Resolve non-tag refs/* in GetRevisionId via GitRefs.TryResolveRef and
authoritative files snapshots so loose, packed, and missing refs resolve
without spawning git or reading .git/objects. In _CustomFetch,
invalidate bare_ref after fetchcmd runs, resolve tracking refs through
bare_ref to warm the snapshot for _InitMRef and Sync_LocalHalf, and read
FETCH_HEAD's leading object ID directly when unambiguous.

Bug: 543101585
Change-Id: Ifb5c0f182e539a2836672a47da348fbeb41e5068
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/655964
Tested-by: Gavin Mak <gavinmak@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
Commit-Queue: Gavin Mak <gavinmak@google.com>
2026-11-12 16:10:31 -08:00
Gavin Mak 7cbd9d1762 project: only unset core.bare when it is true
When creating a gitdir, _InitGitDir spawned `git config --unset-all
core.bare` for every non-mirror project. That is needed when `git init`
wrote `core.bare = true`, as it does for a gitdir under
.repo/project-objects. For a local worktree gitdir (<worktree>/.git, as
with --use-local-gitdirs) `git init` already writes `core.bare = false`,
so the spawn only removed a setting that was already correct. Checked
on git 1.9.1 (the oldest version repo supports), 2.7.4, 2.20.1 and
2.56.

Unset core.bare on non-mirror repositories only when it is currently
true. Local worktree gitdirs now keep the `core.bare = false` that
`git init` wrote.

Bug: 543101585
Change-Id: I662ffce61dc68ebca921941c1a5e5ebce2d22338
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/655965
Tested-by: Gavin Mak <gavinmak@google.com>
Commit-Queue: Gavin Mak <gavinmak@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
2026-11-12 16:07:48 -08:00
Hung-Wei Chen f01eb8774f git_config, project: coalesce SetString writes in BatchWrites
This change attempts to skip sequential git config calls in order to
further speed up git-repo's performance for VFS integration. On
git-main we currently call git config 26K+ times, causing roughly 5~6
seconds of latency (see b/543101585#comment23's TRACE_FILE for data).
Given the expected time of VFS integration is targeting 30s, 6 seconds
makes a huge difference.

During an initial `repo sync`, initializing each project (`_InitGitDir`
and `_InitRemote`) invokes `SetString` multiple times per project, and
`SyncAnalysisState` writes `repo.syncstate.*` keys once per sync.
Because the `git config` CLI has no batch-write mode to set multiple
keys in a single invocation, each `SetString` call previously spawned a
separate `git config` subprocess and rewrote `.repo_config.json` per key
(see b/543101585#comment23 and b/543101585#comment25 for trace profiles
and benchmark data).

Bug: 543101585
Bug: 564817989
Change-Id: Ia1d4613266fb6b7742e8db637039e72ed26a13a2
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/657083
Tested-by: Gavin Mak <gavinmak@google.com>
Commit-Queue: Gavin Mak <gavinmak@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
2026-11-12 15:37:33 -08:00
Gavin Mak 2aca835f1f sync: warm init.templateDir cache for sync workers
When initializing missing project object directories in parallel, each
sync worker cold-misses the init.templateDir lookup cache and spawns
`git config --get init.templatedir`. Relying on parent process memory
alone also misses workers started via `spawn` or `forkserver`.

Resolve the init.templateDir lookup once in the parent process when
parallel sync workers may initialize an object directory (either
because an objdir is missing or `--force-sync` is active), pass the
cached entry through `parallel_context`, and seed it in `InitWorker`.

Bug: 543101585
Change-Id: I6bac2352a9fd4b62d25ed2a89b670ac21aa70f4e
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/657084
Tested-by: Gavin Mak <gavinmak@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
Commit-Queue: Gavin Mak <gavinmak@google.com>
2026-11-12 15:33:07 -08:00
Gavin Mak c9cfb541aa sync: trim preciousObjects work
Only set preciousObjects when objdir differs from gitdir, check actual
objdir sharing in _GetPreciousObjectsState, and skip post-sync
preciousObjects scans on unshared --use-local-gitdirs projects.

Bug: 543101585
Change-Id: I5077aed128f22cf19f520c7866cfd62f0c2724be
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/652266
Tested-by: Gavin Mak <gavinmak@google.com>
Commit-Queue: Gavin Mak <gavinmak@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
2026-11-12 14:51:41 -08:00
Mike Frysinger c85e5ff8a5 pyrefly: initial support
This suppresses a lot of findings in most files so we can run pyrefly
by default and prevent new findings from showing up.  This will need
time to slowly chip away file by file.

Concretely, it's enabled for ~60% of files, and disabled for the other
~40% files.  Not the worst start.

I've opted for disabling files completely at this point rather than
using a baseline because the generated baseline is >200KiB in size.
I think we need to get through a good chunk of that before we switch.

We're going with pyrefly because it's what Google has adopted, and it
evaluated alternatives including mypy, pyright, and its own pytype.

Change-Id: Ib73752dd240a9a84ce0f56059a82292141b6af66
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/656364
Commit-Queue: Mike Frysinger <vapier@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2026-11-12 11:33:10 -08:00
Mike Frysinger ba7bc573ad typing: fix various errors caught by pyrefly
These should be fairly straightforward and not require much thought.
I've punted the more complicated typing changes.

Change-Id: I79167f07e0ec259586520104f07e4cee096a382e
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/656663
Tested-by: Mike Frysinger <vapier@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
2026-11-12 11:23:08 -08:00
Mike Frysinger f74f219954 project: fix invalid logger call
This used to be a print() call, but the migration was incomplete.

Change-Id: If17e5108aa3d2a2948c4834e9c6ed895d3809f91
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/656724
Tested-by: Mike Frysinger <vapier@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
2026-11-12 09:17:39 -08:00
Mike Frysinger f9a1895400 project: fix Project.HasChanges API mismatches
The base Project class defined HasChanges as a function, but the
MetaProject & RepoProject subclasses defined it as a property.
Obviously this is bad & confusing, so standardize it.

Change-Id: Ia3ac9d0592307366296b8ef991dc5d7bb2204490
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/656723
Reviewed-by: Brian Gan <brgan@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2026-11-12 09:17:27 -08:00
Brian Gan 13fe1b9d84 pytest: only keep temp dirs of failed tests
By default, pytest keeps the temp dirs of every test for the last 3
sessions.  Each e2e test clones & checks out a snapshot of the tree
under its `tmp_path`, so these add up, and /tmp is often a tmpfs.

Set `tmp_path_retention_policy` to `failed` so a test's `tmp_path` is
removed as soon as the test passes, and the session's temp dir is
removed when all tests pass.  The `tmp_path` of a failed test is still
kept for debugging.  Pass `-o tmp_path_retention_policy=all` to keep
the dirs of passing tests too.

Test: vpython3 run_tests
Change-Id: I2cf464b063d62f155ffdbfed24a12ea9774086d6
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/656093
Reviewed-by: Mike Frysinger <vapier@google.com>
Tested-by: Brian Gan <brgan@google.com>
Commit-Queue: Brian Gan <brgan@google.com>
2026-11-12 08:43:05 -08:00
Mike Frysinger b1a1cc603a tests: switch to mock.patch.object
Python style reviewers often point people to use mock.patch.object
since it can be statically checked better.  Migrate code, and update
the SKILL file to cover this too.

Change-Id: If7aa8e3ddcdb3d739187b12e3034de1de990a7df
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/656246
Reviewed-by: Brian Gan <brgan@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
2026-11-11 18:19:24 -08:00
Mike Frysinger 2b7969d1cf run_tests: turn into multicall program
Add shortcuts to easily run individual tools while re-using the embedded
vpython/UV script settings.

Change-Id: I4c63e7fd402666628a18cc77187c958d93910f80
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/656245
Tested-by: Mike Frysinger <vapier@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
2026-11-11 15:34:09 -08:00
Gavin Mak bb9b4c2b60 git_refs, project: read files-backend refs in Python
GitRefs._LoadAll spawns `git for-each-ref` to load HEAD and refs/*, and
Project._InitAnyMRef leaves warm snapshots stale after direct UpdateRef
writes. On virtualized checkouts with thousands of repositories, these
spawns add avoidable process overhead.

Read HEAD, packed-refs, and loose refs directly in GitRefs when the
repository uses a plain files ref backend, recording (mode, mtime, size,
inode) stat tuples during the single directory pass and rechecking
packed-refs afterward to guard against concurrent pack-refs updates.
The tuples leave out ctime, which backup agents and file system crawlers
move without changing a ref. Fall back to `git for-each-ref` when
GIT_DIR, GIT_COMMON_DIR, reftable, commondir, custom refStorage config,
symlinks, or lockfiles are present.

Also add GitRefs.TryResolveRef for single-ref lookups without scanning
all of refs/, GitRefs.Invalidate, and GitRefs.UpdateRef to keep cached
snapshots warm after _InitAnyMRef writes a direct ref.

Bug: 543101585
Change-Id: I804ac45712208e9f9e6437012661bc1de58b9825
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/655963
Tested-by: Gavin Mak <gavinmak@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
Commit-Queue: Gavin Mak <gavinmak@google.com>
2026-11-11 14:56:42 -08:00
Brian Gan 33aaf275be sync: handle smart sync when the manifest checkout has no branch
If the manifest checkout in `.repo/manifests` is on a detached HEAD, or
on a local branch without an upstream, `Sync._GetBranch` read a missing
`merge` config and crashed with `'NoneType' object has no attribute
'startswith'`. When smart sync is enabled by default, this broke plain
`repo sync` for such checkouts because `AttributeError` bypassed the
fallback to a regular ToT sync in `_ExecuteHelper`, which only catches
`SmartSyncError` and `ManifestParseError`. Pinning the manifest via
`repo init -b <sha>` or `repo init -b refs/tags/<tag>` also sent the
raw revision to the manifest server as a branch name.

Add `ManifestProject.GetMergeBranch(heads_only=...)` (shared with
`XmlManifest._Load`) to resolve the upstream ref of the current
manifest branch, returning `None` under `heads_only=True` unless it
tracks `refs/heads/*`, and raise `SmartSyncError` in `_SmartSyncSetup`
before running the remote helper or contacting the manifest server.
Implicit smart sync now falls back to a regular ToT sync, and explicit
smart sync fails early with an actionable error message.

Bug: 580004259
Test: vpython3 run_tests
Change-Id: Ice1f9bfe7ea8c923a283bcbd0ac7576cf33e42f6
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/655123
Tested-by: Brian Gan <brgan@google.com>
Commit-Queue: Brian Gan <brgan@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
2026-11-11 12:02:47 -08:00
Mike Frysinger f6523426b9 style: use from subcmds import sync everywhere
Align with Google style guides and `from subcmds import sync` as a
module rather than import symbols out of it.

Change-Id: Iac4ae43fc8f43304b6ffe381cf290378423cd133
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/655847
Tested-by: Mike Frysinger <vapier@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
2026-11-11 09:45:00 -08:00
Mike Frysinger d519ee40a9 style: use import hooks everywhere
Align with Google style guides and `import hooks` as a module
rather than import symbols out of it.

Change-Id: I85a071ee73f8904ac33eae437d7853785762ba71
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/655846
Reviewed-by: Brian Gan <brgan@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2026-11-11 09:40:37 -08:00
Mike Frysinger 9b774577cb pytest: enable xdist usage
The testsuite has grown in size quite a bit.  It takes ~3 min on
my cloudtop with ~48 cores.  Running it in parallel makes it take
~20 seconds.

I've capped it to 32 jobs because it seems to complete in the same
amount of time as 128 jobs, and there's startup cost to spinning
up each node.

Change-Id: I6daa456a92e9db213118c9d16c9dee646db448e0
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/655887
Tested-by: Mike Frysinger <vapier@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
2026-11-11 09:14:21 -08:00
Mike Frysinger 0714b7e434 run_tests: regen uv.lock
Since vpython no longer does this automatically, I upgraded flake8
incorrectly by only updating the script file.  Add a note to remind
people they need to regen the lock file themselves.

Change-Id: I7884714a110bbf843c76aca6e3a2ff14b932b943
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/655845
Reviewed-by: Gavin Mak <gavinmak@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
2026-11-11 05:56:58 -08:00
Mike Frysinger 96363629bd flake8: fix warnings with newer versions
The flake8 version hasn't updated properly due the uv.lock file
being out of date.  Fix newer warnings before unwedging that.

We have a lot of B042 errors that probably should be fixed by reworking
the code, but for now suppress them since we've been doing this for a
long time in repo.
error.py:25:5: B042 Exception class with `__init__` should pass all args to `super().__init__()` to work in edge cases of `pickle` and `copy.copy()`. It should also not take any kwargs.

The only other warning is fairly simple:
subcmds/sync.py:1154:9: B018 Found useless Call expression. Consider either assigning it to a variable or removing it.

Change-Id: I532000a66a5d8493a490fa30080b137aff5f706e
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/655844
Tested-by: Mike Frysinger <vapier@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
2026-11-10 17:59:34 -08:00
Mike Frysinger 11bf826a10 git_command: move _GetBasicEnv to module level
RepoSourceVersion() and _build_env() are module-level functions that
called GitCommand._GetBasicEnv(), while GitCommand itself never called
it directly.  When tests mock git_command.GitCommand before
RepoSourceVersion() has cached its result (such as running
test_upload_for_review_real_event_log in isolation), calling
GitCommand._GetBasicEnv() returned a MagicMock instead of an env dict,
causing subprocess.run to fail with ValueError.

Change-Id: Ib8b866b012602c549ce2d59105526d847b0d7d51
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/656383
Reviewed-by: Gavin Mak <gavinmak@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2026-11-10 17:58:35 -08:00
Brian Gan 1e88f21cb1 sync: remove obsolete projects before interleaved checkouts
In `_SyncInterleaved`, `_UpdateManifestLists` only ran after fetching
and checking out all projects. When a manifest replaced a parent project
`foo` with a nested child project `foo/bar`, `foo/bar` was checked out
inside the still-existing obsolete `foo` worktree before
`UpdateProjectList` deleted `foo`. Because `bar/` was tracked by `foo`,
`git status` in `foo` saw `foo/bar`'s newly checked-out files as
modified and untracked files belonging to `foo`, causing
`DeleteWorktree` to fail with `DeleteDirtyWorktreeError` (and similarly,
when `foo/bar` was merged back into `foo`, `foo`'s checkout collided
with the not-yet-deleted `foo/bar` worktree):

  error: foo: Cannot remove project: uncommitted changes are present.
  error: Unable to fully sync the tree
  error: Updating local project lists failed.

Split `_UpdateManifestLists` into `_UpdateProjectLists` and
`_UpdateCopyLinkfileLists`, and run `_UpdateProjectLists` before the
sync loop in `_SyncInterleaved` so obsolete manifest projects are
deleted before new project checkouts begin (and `--fail-fast` aborts
before fetching if an obsolete project cannot be removed). Run
`_UpdateProjectLists` again after the sync loop (passing the set of
paths that already failed removal pre-sync so they are not retried or
reported twice) together with `_UpdateCopyLinkfileLists` so derived
submodules discovered or dropped when `_ReloadManifest` runs during the
loop are updated in `project.list` and copyfiles/linkfiles are updated.

Because the pre-sync `_UpdateProjectLists` pass in `_SyncInterleaved`
runs before projects are fetched (unlike `_SyncPhased`, which runs it
after `_FetchMain`), a `sync-s="true"` parent project whose manifest
revision moved to an unfetched commit cannot derive its submodules yet
(`GetSubmoduleRevisions() is None`). Retain existing submodule checkouts
under such parents until a post-fetch pass can determine whether their
submodules were removed. Also continue past individual
`DeleteWorktreeError` failures in `UpdateProjectList` (skipping obsolete
ancestors of any retained child worktree) so remaining clean obsolete
projects are still removed while failed paths stay tracked in
`project.list`, and skip project list and copy/linkfile updates when
`--network-only` is set so `-n` does not mutate local worktrees.

Bug: 574048485
Test: vpython3 run_tests
Change-Id: I530337977f063173a9a8a48df3250627cd4bc57f
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/656283
Commit-Queue: Brian Gan <brgan@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
Tested-by: Brian Gan <brgan@google.com>
2026-11-10 15:25:06 -08:00
Mike Frysinger 4bb901eab0 style: use import command everywhere
Align with Google style guides and `import command` as a module
rather than import symbols out of it.

The help subcmd needed a minor rewrite as it had a "command"
variable already.

Change-Id: I9b465c85246670d63827df0744b00e59033e87b2
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/656243
Commit-Queue: Mike Frysinger <vapier@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
2026-11-10 12:59:38 -08:00
Mike Frysinger b2e30cef91 tests: delete buggy git_command tests
The Popen mocking is incomplete & buggy:
* It uses a nested class which hinders pickling.
* Nested classes should rarely be used in the first place, stylewise.
* It does not mock the full Popen API causing failures.

For example, this fails:
$ pytest -vvv tests/test_git_command.py::GitCommandWaitTest
...
FAILED tests/test_git_command.py::GitCommandWaitTest::test_default_returns_non_zero_result - AttributeError: 'MockPopen' object has no attribute 'returncode'
FAILED tests/test_git_command.py::GitCommandWaitTest::test_raises_when_verify_non_zero_result - AttributeError: 'MockPopen' object has no attribute 'returncode'
FAILED tests/test_git_command.py::GitCommandWaitTest::test_returns_when_no_verify_non_zero_result - AttributeError: 'MockPopen' object has no attribute 'returncode'
...

Delete the tests since they don't seem to add much value currently.

Bug: b/293344017
Change-Id: I3d613a84657e30cbc7eac0b363ebfcb46b95eb49
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/655886
Commit-Queue: Mike Frysinger <vapier@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2026-11-10 11:17:32 -08:00
Mike Frysinger 27402ddb25 style: use import main everywhere
Align with Google style guides and `import main` as a module
rather than import symbols out of it.

Change-Id: Iecfb3c89a14d01b24ebfb0aa4584d8d6a94f70fd
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/654821
Reviewed-by: Brian Gan <brgan@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2026-11-10 11:08:42 -08:00
Mike Frysinger 5b04e6e7c5 style: use import subcmds everywhere
Align with Google style guides and `import subcmds` as a module
rather than import symbols out of it.

Change-Id: If19503b977798f8a30e5d54cea9cd63a5c7b81d1
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/654820
Commit-Queue: Mike Frysinger <vapier@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2026-11-10 11:01:44 -08:00
Mike Frysinger eb668be30d style: use import command in unittests
Align with Google style guides and `import command` as a module
rather than import symbols out of it in the tests tree.

Change-Id: I5c151d22c9ed8f8c7ea762823c8b2e25225a2ac4
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/654819
Commit-Queue: Mike Frysinger <vapier@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
2026-11-10 10:45:58 -08:00
Mike Frysinger d7c431b996 style: use import progress everywhere
Align with Google style guides and `import progress` as a module
rather than import symbols out of it.

Change-Id: I3ef9109af8c6883ac0df7fa19bdb88bc6cdfd5e9
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/654818
Reviewed-by: Brian Gan <brgan@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
v2.73
2026-11-10 09:45:00 -08:00
Mike Frysinger 020767b9d3 style: use import wrapper everywhere
Align with Google style guides and `import wrapper` as a module
rather than import symbols out of it.

Change-Id: Ifc6165974a242a1ce38bd09b1b4226dc0ba943d5
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/654817
Reviewed-by: Brian Gan <brgan@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2026-11-10 07:24:10 -08:00
Mike Frysinger 0f83e19bbb style: use import git_trace2_event_log_base everywhere
Align with Google style guides and `import git_trace2_event_log_base` as
a module rather than import symbols out of it.

Change-Id: I98c68a9ddca06325a8e0a620346c408e1ff3b661
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/654816
Tested-by: Mike Frysinger <vapier@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
2026-11-10 07:13:59 -08:00
Mike Frysinger 221a31cd0a style: use import git_trace2_event_log everywhere
Align with Google style guides and `import git_trace2_event_log` as a
module rather than import symbols out of it.

Change-Id: I4fdb0692ccbcf38ecdd756a4417c68f0cfaebc0c
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/654815
Reviewed-by: Brian Gan <brgan@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
2026-11-09 19:52:17 -08:00
Mike Frysinger ccddf51633 style: use import git_superproject everywhere
Align with Google style guides and `import git_superproject` as a module
rather than import symbols out of it.

Change-Id: I939f1123d5c6f79b56c244a5ffdf5bcfa136b2db
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/654814
Commit-Queue: Mike Frysinger <vapier@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2026-11-09 19:43:03 -08:00
Mike Frysinger 72e3c8c277 style: use import event_log everywhere
Align with Google style guides and `import event_log` as a module
rather than import symbols out of it.

Change-Id: I2c558f1161490b354f0b956ac0e86e658942c3a2
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/654813
Reviewed-by: Brian Gan <brgan@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2026-11-09 19:06:10 -08:00
Mike Frysinger 4cef373d98 style: use import manifest_xml everywhere
Align with Google style guides and `import manifest_xml` as a module
rather than import symbols out of it.

Change-Id: Ib600a5ccaf53b178e27e6e9d56847751d266bfe4
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/654812
Tested-by: Mike Frysinger <vapier@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
2026-11-09 17:34:52 -08:00
Gavin Mak 95d7c8c0df sync: don't read target tree after reprojectcmd
After repo.reprojectcmd exits 0, _Reproject ran `git diff-index --cached
--name-only <revid>^{tree}` to verify that the index matches the target
commit's tree.

Peeling <revid>^{tree} and comparing every entry against the index
forces Git to read the target commit and walk every tree object in the
target revision from .git/objects.

reprojectcmd exists for virtualized filesystems such as ABFS whose
checkout command materializes the worktree and writes .git/index from
its own tree metadata without reading .git/objects/pack/*-trees-*.pack.
Running diff-index against <revid>^{tree} afterward forces Git to fault
in the tree packfiles over the network (260 FetchTrees pack downloads /
1.64 GiB across a 3,296-project Android checkout).

Trust reprojectcmd's exit status for index materialization instead of
re-walking the target tree in Git, while keeping the HEAD postcondition
check that verifies the command did not modify refs.

Bug: 543101585
Change-Id: Ie5feea41a4191245232c6763a489d01596370c55

Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/643004
Commit-Queue: Gavin Mak <gavinmak@google.com>
Tested-by: Gavin Mak <gavinmak@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
2026-11-09 15:15:49 -08:00
Gavin Mak 616396317c sync: verify fetchcmd postconditions without reading objects
After repo.fetchcmd exits, _CustomFetch verified the tracking ref and
FETCH_HEAD with ResolveCommit, i.e. `git rev-parse --verify
<ref>^{commit}`. Peeling to a commit makes Git look the object up: it
opens every pack index in objects/pack/ until it finds the commit, then
reads the commit from its packfile.

fetchcmd exists for object stores that are populated lazily, such as
ABFS, whose `abfs git fetch` registers packfiles as virtual files and
returns at once. There the peel is the first read of the packs the
command registered, and it blocks until they are downloaded. A project
whose revision did not change needs no objects to sync, yet paid that
download whenever fetchcmd registered new packs for it.

Compare the object IDs that the refs record instead (ResolveRef, which
runs the same rev-parse without the peel). Only when they differ peel
both sides to commits, so an annotated tag still matches the commit it
points to. A commit missing from the object store now fails the checkout
that reads it instead of the network half.

On a first sync the checkout reads the commit anyway, so there the
download only moves to the next command that needs the object.

Bug: 543101585
Change-Id: I51248ff1e9674b16e3ff8cee69572dbc8c7a8e99
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/643003
Commit-Queue: Gavin Mak <gavinmak@google.com>
Tested-by: Gavin Mak <gavinmak@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
2026-11-09 15:15:43 -08:00
Gavin Mak 4978203b07 sync: skip shallow bloat check when using fetchcmd
Skip projects fetched via repo.fetchcmd in _CheckForBloatedProjects,
and expose Project.UseFetchCmd alongside Project.UseReprojectCmd.

The bloat check exists because Project._RemoteFetch passes --no-auto-gc
for clone-depth="1" repositories. Projects using repo.fetchcmd bypass
_RemoteFetch and manage object storage externally, so scanning their
worktrees for bloat is unnecessary and recommending git repack can
materialize virtualized objects locally.

Bug: 543101585
Change-Id: I16510ad3b5b39c3a5e2a1a75df706439252a088e
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/655083
Tested-by: Gavin Mak <gavinmak@google.com>
Commit-Queue: Gavin Mak <gavinmak@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
2026-11-09 15:03:09 -08:00
Mike Frysinger cc3f52cd6c style: use import git_config everywhere
Align with Google style guides and `import git_config` as a module
rather than import symbols out of it.

Change-Id: I467f1f8c0868c53b71917ca0a9610606e1ce4d83
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/654811
Reviewed-by: Brian Gan <brgan@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2026-11-09 13:35:49 -08:00
John Cai e045aa19d8 Adding sparse checkout functionality
Sparse checkout allows Git to check out only a portion of the
repository. This is particularly helpful for monorepository workflows
where CI jobs only need a portion of the repository to run tests.

This speeds up the CI jobs, and puts less load on the Git server as it
relieves it from having to pack up all the objects.

In the Git project, though it is still labeled experimental, the feature
has been stable for a number of years and is unlikely to change at this
point.

This change allows configuring Git to use sparse checkout and provide a
list of directories for the sync command to retrieve.

Projects with sparse paths default to a blob:none partial clone so the
excluded paths are never fetched, unless a filter is already configured
or the project is excluded from partial clones.  Both the plain and the
git-worktree checkout flows configure sparse-checkout before populating
the working tree.

Change-Id: I772c7db5209b345306be378771c8f2040832bca1
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/535061
Reviewed-by: Gavin Mak <gavinmak@google.com>
Tested-by: John Cai <johncai86@gmail.com>
Commit-Queue: John Cai <johncai86@gmail.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
2026-11-09 11:14:00 -08:00
Mike Frysinger c382d3807a style: use import color everywhere
Align with Google style guides and `import color` as a module
rather than import symbols out of it.

Change-Id: Id3f1f8ea324097d6e1ea5ed33c67b4b024abce7f
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/654810
Commit-Queue: Mike Frysinger <vapier@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2026-11-09 09:07:27 -08:00
Mike Frysinger 9d01d216e0 style: use import test_manifest_xml everywhere
Align with Google style guides and `import test_manifest_xml` as a module
rather than import symbols out of it.

Change-Id: Ib85716bea2eb09028e05b86d445336405e1df870
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/654809
Reviewed-by: Brian Gan <brgan@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
2026-11-09 08:52:28 -08:00
Mike Frysinger 52f01a18da style: use import pager everywhere
Align with Google style guides and `import pager` as a module
rather than import symbols out of it.

Change-Id: I20ec5024ece35ae27bf46364e97c59400aae0cf0
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/654808
Commit-Queue: Mike Frysinger <vapier@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2026-11-09 07:55:40 -08:00
Mike Frysinger 3a3d1fc7cd style: use import editor everywhere
Align with Google style guides and `import editor` as a module
rather than import symbols out of it.

Change-Id: Ie941ff12f63c2b168bcec6510751e155156f26e7
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/654807
Reviewed-by: Brian Gan <brgan@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
2026-11-09 07:09:25 -08:00
Mike Frysinger 2029997aef style: use import io everywhere
Align with Google style guides and `import io` as a module
rather than import symbols out of it.

Change-Id: Ic3e78aa81ffc24687f61c7ce744e596fbdb13415
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/654806
Commit-Queue: Mike Frysinger <vapier@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2026-11-06 11:58:10 -08:00
Mike Frysinger caa4cd6564 style: use import collections everywhere
Align with Google style guides and `import collections` as a module
rather than import symbols out of it.

Change-Id: I165028d5b70a78492e361e6b6f9e3eea19d014b6
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/654805
Reviewed-by: Brian Gan <brgan@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2026-11-06 11:57:56 -08:00
Mike Frysinger e15b3e0298 style: use import urllib.xxx everywhere
Align with Google style guides and `import urllib.xxx` as a module
rather than import symbols out of it.

Change-Id: Ia177f4fd5ee2a3f38f8a8860e9a2ba8beac8078f
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/654804
Reviewed-by: Brian Gan <brgan@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
2026-11-06 11:56:05 -08:00
Mike Frysinger a4b44c5026 style: use import types everywhere
Align with Google style guides and `import types` as a module
rather than import symbols out of it.

Change-Id: I20f8058eb1b5dafc1d2964c276e28b95b188bfff
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/654803
Commit-Queue: Mike Frysinger <vapier@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2026-11-06 10:29:39 -08:00
Mike Frysinger 8f2c0f1483 flake8: enable flake8-import-restrictions
Disable the warning across existing modules for now.  We'll need to
clean those up, but we can at least stop new bad modules from being
added to the tree.

Change-Id: I39be6450ecde86ce30553b6e277f870e0d3865c1
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/654623
Reviewed-by: Brian Gan <brgan@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
2026-11-05 11:03:12 -08:00
Mike Frysinger 7ed9700a95 flake8: fix nested import checks
Import modules at the top of the module in most cases.  Many of these
weren't actually saving any time:
* editor: shlex is already imported by the main module
* platform_utils: On Windows, the win32 module is almost always needed
* tests: There's no point in optimizing these.

The trace import in the main module is about the only one worth allowing
since that module itself is rarely used, and only when in a specific
debug mode.

Change-Id: I5d3fcecbe51e0ce78d4e856d7033565150ef4526
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/654103
Commit-Queue: Mike Frysinger <vapier@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2026-11-05 10:50:14 -08:00
hungweichen d621aa8ee4 event_log: only record events when --event-log is specified
Add an enabled flag to EventLog (defaulting to False on
Command.event_log and enabled by _Repo._RunLong when --event-log is
passed) and return None early from EventLog.Add when disabled.

Because EventLog.AddSync only resolves project.GetCommitRevisionId()
when EventLog.Add returns an event, disabling Command.event_log by
default eliminates 3,300+ synchronous git subprocess calls in
MainProcess result callbacks during normal repo sync runs without
touching subcmds/sync.py.

Bug: 564817989
Change-Id: I79dd66d1c392ba5ee562f104759e36d1dd6eefea
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/649606
Tested-by: Gavin Mak <gavinmak@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
Commit-Queue: Gavin Mak <gavinmak@google.com>
2026-11-05 08:19:19 -08:00
hungweichen b16e5f49d6 git_refs, project: skip redundant git calls on unborn HEAD and warm refs
Read plain files-backend unborn HEAD symrefs directly before spawning
git symbolic-ref, update already-loaded bare_ref snapshots in
_InitAnyMRef when no external ref changes occurred, and reuse warm
bare_ref snapshots in GetRevisionId for non-tag refs.

Also skip redundant rev-parse and empty-index ls-files subprocesses in
_Reproject when HEAD is guaranteed to be an unborn local ref.

Bug: 564817989
Change-Id: I0da10cefb14753ce6e1e22e192d652790d59a5b0
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/649605
Tested-by: Gavin Mak <gavinmak@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
Commit-Queue: Gavin Mak <gavinmak@google.com>
2026-11-05 07:52:57 -08:00