Rebase to Git for Windows 2.56.0-rc1 - #990
Merged
Johannes Schindelin (dscho) merged 365 commits intoSep 23, 2026
Merged
Conversation
The fsmonitor script that can be used for running all the git tests using watchman was causing some of the tests to fail because it wrote to stderr and created some files for debugging purposes. Add a new debug script to use with debugging and modify the other script to remove the code that would cause tests to fail. Signed-off-by: Kevin Willford <Kevin.Willford@microsoft.com>
Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
The following commands and options are not currently supported when working in a GVFS repo. Add code to detect and block these commands from executing. 1) fsck 2) gc 4) prune 5) repack 6) submodule 8) update-index --split-index 9) update-index --index-version (other than 4) 10) update-index --[no-]skip-worktree 11) worktree Signed-off-by: Ben Peart <benpeart@microsoft.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Loosen the blocking of the `prune` command from all "GVFS repos" (those that have `core.gvfs` set) to only those that actually use the virtual file system (VFS for Git only). This allows for `prune` to be used in Scalar clones. Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com>
When our patches to support that hook were upstreamed, the hook's name was eliciting some reviewer suggestions, and it was renamed to `post-index-change`. These patches (with the new name) made it into v2.22.0. However, VFSforGit users may very well have checkouts with that hook installed under the original name. To support this, let's just introduce a hack where we look a bit more closely when we just failed to find the `post-index-change` hook, and allow any `post-indexchanged` hook to run instead (if it exists).
Disable deserialization when verbose output requested. Verbose mode causes Git to print diffs for modified files. This requires the index to be loaded to have the currently staged OID values. Without loading the index, verbose output make it look like everything was deleted. Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
In earlier versions of `microsoft/git`, we found a user who had set `core.gvfs = false` in their global config. This should not have been necessary, but it also should not have caused a problem. However, it did. The reason was that `gvfs_load_config_value()` was called from `config.c` when reading config key/value pairs from all the config files. The local config should override the global config, and this is done by `config.c` reading the global config first then reading the local config. However, our logic only allowed writing the `core_gvfs` variable once. In v2.51.0, we had to adapt to upstream changes that changed way the `core.gvfs` config value is read, and the special handling is no longer necessary, yet we still want the test case that ensures that this bug does not experience a regression. Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Replace the special casing of the `worktree` command being blocked on VFS-enabled repos with the new `BLOCK_ON_VFS_ENABLED` flag. Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com>
When using a virtual file system layer, the FSMonitor does not make sense. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Verify that `git status --deserialize=x -v` does not crash and generates the same output as a normal (scanning) status command. These issues are described in the previous 2 commits. Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Emit a warning message when the `gvfs.sharedCache` option is set that the `repack` command will not perform repacking on the shared cache. In the future we can teach `repack` to operate on the shared cache, at which point we can drop this commit. Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com>
When sparse-checkout is enabled, add the sparse-checkout percentage to the Trace2 data stream. This number was already computed and printed on the console in the "You are in a sparse checkout..." message. It would be helpful to log it too for performance monitoring. Signed-off-by: Jeff Hostetler <jeffhostetler@github.com>
Teach Git to not throw a fatal error when an explicitly-specified status-cache file (`git status --deserialize=<foo>`) could not be found or opened for reading and silently fallback to a traditional scan. This matches the behavior when the status-cache file is implicitly given via a config setting. Note: the current version causes a test to start failing. Mark this as an expected result for now. Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com> Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Teach subprocess_start() to use a copy of the passed `cmd` string rather than borrowing the buffer from the caller. Some callers of subprocess_start() pass the value returned from find_hook() which points to a static buffer and therefore is only good until the next call to find_hook(). This could cause problems for the long-running background processes managed by sub-process.c where later calls to subprocess_find_entry() to get an existing process will fail. This could cause more than 1 long-running process to be created. TODO Need to confirm, but if only read_object_hook() uses TODO subprocess_start() in this manner, we could drop this TODO commit when we drop support for read_object_hook(). Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Add function to start a subprocess with an argv. Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Create a function to add a new object to the loose object cache after the existing odb/xx/ directory was scanned. This will be used in a later commit to keep the loose object cache fresh after dynamically fetching an individual object and without requiring the odb/xx/ directory to be rescanned. Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
…and report_tracking() Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Prevent packfile parsing from accidentally dynamically fetching each individual object found in the packfile. When index-pack parses the input packfile, it does a lookup in the ODB to test for conflicts/collisions. This can accidentally cause the object to be individually fetched when gvfs-helper (or read-object-hook or partial-clone) is enabled. The call site was migrated to odb_has_object() as part of the upstream refactoring, but odb_has_object(odb, oid, HAS_OBJECT_FETCH_PROMISOR) sets only OBJECT_INFO_QUICK without OBJECT_INFO_SKIP_FETCH_OBJECT, which means it WILL trigger remote fetches via gvfs-helper. But we want to prevent index-pack from individually fetching every object it encounters during the collision check. Passing 0 instead gives us both OBJECT_INFO_QUICK and OBJECT_INFO_SKIP_FETCH_OBJECT, which is the correct equivalent of the original OBJECT_INFO_FOR_PREFETCH behavior. Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Create gvfs-helper. This is a helper tool to use the GVFS Protocol REST API to fetch objects and configuration data from a GVFS cache-server or Git server. This tool uses libcurl to send object requests to either server. This tool creates loose objects and/or packfiles. Create gvfs-helper-client. This code resides within git proper and uses the sub-process API to manage gvfs-helper as a long-running background process. Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com> Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
Add data for the number of files created/overwritten and deleted during the checkout. Give proper category name to all events in unpack-trees.c and eliminate "exp". This is modified slightly from the original version due to interactions with 26f924d (unpack-trees: exit check_updates() early if updates are not wanted, 2020-01-07). Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com> Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
The config variable `gvfs.sharedCache` contains the pathname to an alternate <odb> that will be used by `gvfs-helper` to store dynamically-fetched missing objects. If this directory does not exist on disk, `prepare_alt_odb()` omits this directory from the in-memory list of alternates. This causes `git` commands (and `gvfs-helper` in particular) to fall-back to `.git/objects` for storage of these objects. This disables the shared-cache and leads to poorer performance. Teach `alt_obj_usable()` and `prepare_alt_odb()`, match up the directory named in `gvfs.sharedCache` with an entry in `.git/objects/info/alternates` and force-create the `<odb>` root directory (and the associated `<odb>/pack` directory) if necessary. If the value of `gvfs.sharedCache` refers to a directory that is NOT listed as an alternate, create an in-memory alternate entry in the odb-list. (This is similar to how GIT_ALTERNATE_OBJECT_DIRECTORIES works.) This work happens the first time that `prepare_alt_odb()` is called. Furthermore, teach the `--shared-cache=<odb>` command line option in `gvfs-helper` (which is runs after the first call to `prepare_alt_odb()`) to override the inherited shared-cache (and again, create the ODB directory if necessary). Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Update tracing around report_tracking() to use 'tracking' category rather than 'exp' category. Add ahead/behind results from stat_tracking_info(). Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Upstream Git is _very_ keen on not allowing in-memory addition of alternates, see f0eb23a (odb: remove the ability to link sources ad-hoc, 2026-09-11). However, we really need this functionality here. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Add trace2 message for CURL and HTTP errors. Fix typo reporting network error code back to gvfs-helper-client. Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Fix parsing of the "loose <odb>" response from `gvfs-helper` and use the actually parsed OID when updating the loose oid cache. Previously, an uninitialized "struct oid" was used to update the cache. This did not cause any corruption, but could cause extra fetches for objects visited multiple times. Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Promoting a microsoft/git release into the microsoft/homebrew-git tap used to be handled by `release-homebrew.yml`, which authenticated to Azure via OIDC, pulled a GitHub PAT from an Azure Key Vault, and pushed to the tap. That plumbing existed because the prior internal guidance mandated GitHub-Actions-native federated identity to Azure and deprecated the Azure Pipelines automation this workflow had originally replaced. That guidance has now reversed: federated identity from GitHub Actions to Azure has been turned off. Rather than migrate the automation a third time (and rebuild the full plumbing needed to fetch a PAT via Azure Pipelines with workload identity into Key Vault under the new rules), replace the workflow with a script the operator runs by hand while promoting a pre-release to a full release. The operator's own `gh auth login` session already has push access to microsoft/homebrew-git, so the entire OIDC-to-Key-Vault chain disappears. The script reproduces the behaviour of the previously-used `mjcheetham/update-homebrew@v1.5.1` action invoked with `type: cask, alwaysUsePullRequest: false`: it locates the single `git-*.pkg` asset for the tag, rewrites `version` and `sha256` in the cask, commits, and pushes to the tap's default branch. The `sha256` is taken from the asset's API-reported `digest` field rather than recomputed locally, because microsoft/homebrew-git#102 documented cases where GitHub occasionally served the "unicorn" 500 page with a 200 status for an asset download, which then poisons any locally computed hash. This is the first of three such scripts (homebrew, vfsforgit, winget) that will supersede the corresponding workflows; a follow-up commit will delete those workflows and the local `.github/actions/akv-secret/` composite action once all three replacements are in place. Assisted-by: Opus 4.7 Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
The Windows runners used by `vfs-functional-tests.yml` ship `rustup` plus a `*-pc-windows-msvc` default toolchain (see https://github.com/actions/runner-images/blob/main/images/windows/Windows2022-Readme.md and https://github.com/actions/partner-runner-images/blob/main/images/arm-windows-11-image.md), but no precompiled `std` for `*-pc-windows-gnu` or `*-pc-windows-gnullvm`. With the Makefile now picking a GCC-compatible target triple based on `$(MSYSTEM)`, the build step needs that precompiled `std` to be installed before invoking `make`, otherwise `cargo build --target <triple>` fails to find a usable `std` for the chosen target. Add a step between the SDK setup and the `make` invocation that selects the matching triple from `$MSYSTEM` (which `git-for-windows/setup-git-for-windows-sdk` exports for every subsequent step) and runs `rustup target add` for it. The mapping mirrors what `config.mak.uname` derives from `$(MSYSTEM)` and `$(HOST_CPU)`, just enumerated explicitly here since CI has direct knowledge of which MSYS2 subsystems the matrix actually exercises (`CLANGARM64` for the ARM64 runner, `MINGW64` for the x86_64 runner). For a `staticlib` crate-type `cargo build` does not invoke an external linker, so no further toolchain components (e.g. the `gnullvm` LLVM linker) need to be installed; `rustup target add` alone is sufficient. Assisted-by: Claude Opus 4.7 Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
For the same rationale as the preceding release-homebrew commit, port the body of `.github/workflows/release-vfsforgit.yml` into a POSIX-sh script that the operator invokes by hand while promoting a pre-release to a full release. Given a release tag on microsoft/git, the script opens a pull request against microsoft/VFSForGit that bumps the `GIT_VERSION` default in `.github/workflows/build.yaml` so that VFSForGit builds pick up the newly promoted release by default. The operator's own `gh auth login` session already has push access to microsoft/VFSForGit, so no PAT and no Key Vault-backed secret are needed. The commit and the pull request are attributed to that user rather than to `github-actions[bot]`, which also makes the change to the downstream repository traceable to an identifiable human who can be pinged for follow-up. One portability wart worth calling out: the version bump uses the `<in >out && mv -f out in` idiom rather than `sed -i`, because the `-i` flag has incompatible spellings between GNU sed on Linux (which accepts `-i` with no argument) and BSD sed on macOS (which requires an explicit empty suffix, `-i ''`). The script is expected to run from either platform, so it sticks to the portable form and stays plain POSIX sh throughout. Assisted-by: Opus 4.7 Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Same rationale as the two prior scripts (release-homebrew.sh, release-vfsforgit.sh): replace a CI-driven fan-out step with a hand-run script that reads its GitHub token from `gh auth token`, sidestepping the PAT/Azure Key Vault dance. This one _must_ be run on Windows (or in WSL) because `wingetcreate.exe`, the tool that authors the manifest and opens the PR against microsoft/winget-pkgs, is Windows-only; the superseded workflow already ran on `windows-latest` for that reason, and neither the operator nor the automation ever invoked this step from macOS or Linux. microsoft/git tags look like `vX.Y.Z.vfs.N.M`, but winget wants a purely dotted numeric version, so the script strips the leading `v` and the `vfs.` segment to produce `X.Y.Z.N.M` (for example, `v2.54.0.vfs.0.4` becomes `2.54.0.0.4`), matching what the previous workflow emitted. The tag is parsed with `-not ($tag -match ...)` rather than the seemingly equivalent `-notmatch`, because PowerShell's `-notmatch` operator does not populate the `$Matches` automatic variable, yet the two capture groups are read as `$Matches[1]` and `$Matches[2]` immediately afterwards. See https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_comparison_operators for the documented behaviour. `wingetcreate submit` pushes to the operator's personal fork of microsoft/winget-pkgs and opens a PR from there; if that fork is stale, submit fails with "The forked repository could not be synced". The script therefore issues a `POST /repos/<user>/winget-pkgs/merge-upstream` first, and treats a 404 as fine, since wingetcreate creates the fork on demand at submit time when none exists. Assisted-by: Opus 4.7 Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Some users reported issues of repeated messages: fatal: recursion detected in die handler This wasn't happening every time, but we eventually captured a GIT_TRACE2_PERF log file with this issue and revealed an interesting internal detail, failing with this message: unable to format message: %4d-%02d-%02dT%02d:%02d:%02d.%06ldZ This specific format string tracks to tr2_tbuf_utc_datetime_extended() in trace2/tr2_tbuf.c. This logic began as tr2_tbuf_utc_time() in ee4512e (trace2: create new combined trace facility, 2019-02-22) but was later split in bad229a (trace2: clarify UTC datetime formatting, 2019-04-15). This use of xsnprintf() is writing a very specific datetime format into a 32-character buffer. The format requires that the input data will not overflow the format digits or the buffer will not hold the result. Since we are using xsnprintf() here, those failures turn into die() events. This method and its siblings, tr2_tbuf_local_time() and tr2_tbuf_utc_datetime(), are used in the tracing library. The extended form is used only for the 'event' format, which these users were using via a config setting for use in client-side telemetry. The non-extended form is used to help generate the 'SID' that defines the process in the traces. Not only are these inappropriate times for a failure, but the extended method is called specifially during the 'atexit' event, which was triggering this problem in a loop as the 'atexit' event would be retriggered by the die(). I could not determine the exact cause of why these errors started occuring in a bunch. My best guess is that these users are dogfooding an early operating system version that is more likely to fail in the gettimeofday() function and thus leaves the structures uninitialized and potentially violating the expected values. However, for full defense-in-depth I made several modifications: 1. Both 'tv' and 'tm' structs are initialized with zero values, allowing an erroring gettimeofday() or gmtime_r() method to leave them zero-valued. A zero-valued date is better than a die() here. 2. Replace the use of xsnprintf() with snprintf() to avoid the possibility of calling die() here. Instead, check the response to see if there was a failure. On failure, put a blank value into the buffer instead of possibly allowing a value that would not format correctly for a trace2 consumer. This value should be seen as obviously wrong and therefore signals a problem. As the core issue in this code seems to require a system method returning an error, no test accompanies this change. This change removes all uses of xsnprintf() from the trace2/ directory. There are two uses of xstrdup() that could be considered for removal, but they only die() on out-of-memory errors instead of formatting issues. I chose to leave those in place for now. Signed-off-by: Derrick Stolee <stolee@gmail.com>
This PR simply ports #952 to the `vfs-2.55.0` branch. It intentionally collapses the commits to make future rebases quicker.
In virtual filesystem (VFS/GVFS) mode, reset --mixed failed to report
hydrated files as modified. A hydrated file is one that has been read
(e.g. via blame or cat-file) and materialized on disk by ProjFS, but
not modified — so it is not in GVFS's ModifiedPaths database and
retains the skip-worktree bit in the index.
The existing VFS-specific code in update_index_from_diff() used
file_exists() to decide whether to clear skip-worktree:
- Files NOT on disk (virtual/placeholder): file_exists() returns
false, skip-worktree is cleared, and the pre-reset content is
written to disk via checkout_entry(). These files correctly
appear as modified. This path remains unchanged.
- Files already on disk (hydrated): file_exists() returns true,
so the code left skip-worktree set. refresh_index() then skipped
the file entirely, hiding the working-tree vs index mismatch.
The file was invisible to both the reset output and subsequent
git status.
Fix this by always clearing skip-worktree (respect_skip_worktree = 0)
for all entries processed by update_index_from_diff() when VFS mode is
active. The file_exists() check now only controls whether pre-reset
content needs to be written to disk — it no longer affects the
skip-worktree decision.
After the reset, GVFS's GitIndexParser detects the cleared
skip-worktree bits via the post-index-change hook and adds the
affected paths to ModifiedPaths, so subsequent git commands also
see them correctly.
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Users were noticing some cases of infinite loops with the error message: ``` fatal: recursion detected in die handler ``` It's only happening for repos with a post-command hook, but it's not deterministic. I'm not sure what is triggering the problem, but the post-command hook is definitely able to recurse with its existing logic around the `run_post_hook` variable. Move this earlier to avoid a potential double-call. It's a fixup to the introduction of the method, which may cause conflicts with later adjustments to this method still in the branch thicket (but maybe those should be squashed, too). See #955 for the version on 2.54.0.
When pushing from a repository that uses the GVFS Protocol, `git push` spawns `git pack-objects --all-progress-implied --revs --stdout --thin -q` and feeds it revision parameters on stdin: the advertised refs and negotiated objects as negative (exclusion) tips, plus each ref's old and new tips. Normally feed_object() omits a negative object that is not present locally, but the core.gvfs GVFS_MISSING_OK bit disables that check so that missing negatives are still fed. That bypass is actively harmful under the GVFS Protocol. pack-objects adds `--objects-edge` for `--thin` and, while marking edges uninteresting and hunting for preferred delta bases, reads the tree of every fed exclusion. For an exclusion the client does not have locally, that read lazily downloads the object, issuing one gh_client__get_ immediate request per advertised ref. A scalar clone against a server that advertises many refs therefore triggers a storm of immediate object fetches during an ordinary push. Partial clone deliberately assumes the objects behind our refs are already present and never fetches them for a push. Restore that behavior for the GVFS Protocol behind a new opt-in config, gvfs.negativeRefCheck. When set, `git push` performs a non-fetching existence check -- odb_has_object() with flags 0 implies OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT, so the probe never fetches -- and omits any advertised object it does not have, exactly as Git does without the GVFS_MISSING_OK bit. The decision is computed once in pack_objects() because advertised ref lists can be large. The config defaults to false, so the legacy GVFS_MISSING_OK behavior is unchanged unless an operator opts in, keeping the fallout controllable. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
#963) This is a companion of #935, porting the changes from vfs-2.54.0 to vfs-2.55.0. ## Problem In virtual filesystem (VFS/GVFS) mode, `reset --mixed` fails to report hydrated files as modified. A **hydrated file** is one that has been read (e.g., via `blame` or `cat-file`) and materialized on disk by ProjFS, but not modified — so it is not in GVFS's ModifiedPaths database and retains the `skip-worktree` bit in the index. ### Reproduction 1. `gvfs clone` a repo 2. `git blame Readme.md` — hydrates the file (ProjFS materializes content on disk) 3. `git reset --mixed HEAD~1` (where `Readme.md` differs between HEAD and HEAD~1) 4. **Expected:** `Readme.md` appears in reset output and `git status` shows it as modified 5. **Actual:** `Readme.md` is missing from output; `git status` reports clean ### Root cause The VFS-specific code in `update_index_from_diff()` uses `file_exists()` to decide whether to clear `skip-worktree`: - **Files NOT on disk** (virtual/placeholder): `file_exists()` returns false → `skip-worktree` cleared, pre-reset content written to disk via `checkout_entry()` → correctly reported as modified ✓ - **Files on disk** (hydrated): `file_exists()` returns true → `skip-worktree` left set → `refresh_index()` skips the entry → invisible to status ✗ The original code assumed that if a file exists on disk, it must already be tracked properly. But hydrated-but-not-modified files exist on disk with stale content and are NOT in ModifiedPaths. ## Fix Always clear `skip-worktree` (`respect_skip_worktree = 0`) for all entries processed by `update_index_from_diff()` when VFS mode is active. The `file_exists()` check now only controls whether pre-reset content needs to be written to disk — it no longer gates the skip-worktree decision. After the reset, GVFS's `GitIndexParser` detects the cleared skip-worktree bits via the `post-index-change` hook and adds affected paths to ModifiedPaths, so subsequent git commands also see them correctly. ### Before (buggy) ```c if (core_virtualfilesystem && !file_exists(two->path)) { respect_skip_worktree = 0; // only for missing files // ... write content to disk ... } ``` ### After (fixed) ```c if (core_virtualfilesystem) { respect_skip_worktree = 0; // for ALL changed entries if (!file_exists(two->path)) // only write content for missing files { // ... write content to disk ... } } ``` ## Testing - 3 new tests in `t1093-virtualfilesystem.sh`: - **Hydrated file**: file exists on disk, should appear in reset output - **Non-hydrated file**: file missing from disk, should be written and appear in output - **Partial reset**: unchanged files retain skip-worktree - Verified manually against a real GVFS enlistment: GVFS and control repo now produce identical output (224 modified files including `Readme.md`) - All 25 existing `t1093` tests pass
When using the GVFS protocol with 'scalar clone', the first 'git fetch' uses the prefetch endpoint to download commits and trees so history operations are usable immediately after cloning. Some users want to optimize for the initial usability of the repository, and they don't need the full history available right away. They are prepared to wait for future fetches (perhaps in the background) doing that work for them. Add a new --no-prefetch option that skips the initial prefetch. This is implemented by using '-c core.gvfs=X' arguments in the underlying fetch operation to temporarily avoid the prefetch operation for that subcommand only. It's important that this does not actually stop prefetches forever, though that can be adjusted by flipping the appropriate bit in the core.gvfs config option. Signed-off-by: Derrick Stolee <stolee@gmail.com>
The object database refactor that introduced per-source object stores (cb506a8 "odb: introduce \"files\" source" and the surrounding series, first released in v2.54.0) changed how do_oid_object_info_extended() searches for an object. It now iterates the sources and, within each source, consults that source's packfiles and then its loose object store before moving on to the next source. Before that series the search consulted every packfile -- across the primary object directory and all alternates -- before it looked at any loose object. The refactor reversed that for the multi-source case: for an object that lives in an alternate's packfile, the primary source's loose object store is now consulted first. That loose lookup is a filesystem stat(), and because callers such as cache_tree_fully_valid() pass ODB_HAS_OBJECT_RECHECK_PACKED (which clears OBJECT_INFO_QUICK) the cached-loose-index fast path is skipped and a real stat() runs for every such object. In a repository that keeps its objects in an alternate -- the common arrangement for VFS for Git and Scalar enlistments, where a shared object cache is mounted as an alternate -- this is a steep penalty. cache_tree_fully_valid() walks the whole cache tree and calls odb_has_object() for every node; on an enlistment with a ~2.4M-entry index that is ~380k objects, each incurring a wasted stat() on the primary loose store. A same-commit branch switch spent ~32s in cache_tree_fully_valid() (two calls of ~16s), observed in the field as a ~2x rise in median checkout duration after the client carrying the refactor rolled out. Restore the previous ordering without undoing the per-source encapsulation: when there is more than one source, scan the packfiles of every source first (OBJECT_INFO_SKIP_LOOSE) and only then consult each source's loose store (OBJECT_INFO_SKIP_PACKED). The single-source case is unchanged, so repositories without alternates keep the existing path. With the fix the same branch switch spends ~2s in cache_tree_fully_valid(), the ~380k wasted stat()s are gone, and performance matches versions predating the refactor. Assisted-by: Claude Opus 4.8 Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
When pushing from a repository that uses the GVFS Protocol, `git push`
spawns `git pack-objects --all-progress-implied --revs --stdout --thin
-q` and feeds it revision parameters on stdin: the advertised refs and
negotiated objects as negative (exclusion) tips, plus each ref's old and
new tips. Normally feed_object() omits a negative object that is not
present locally, but the core.gvfs GVFS_MISSING_OK bit disables that
check so that missing negatives are still fed.
That bypass is actively harmful under the GVFS Protocol. pack-objects
adds `--objects-edge` for `--thin` and, while marking edges
uninteresting and hunting for preferred delta bases, reads the tree of
every fed exclusion. For an exclusion the client does not have locally,
that read lazily downloads the object, issuing one gh_client__get_
immediate request per advertised ref. A scalar clone against a server
that advertises many refs therefore triggers a storm of immediate object
fetches during an ordinary push.
Partial clone deliberately assumes the objects behind our refs are
already present and never fetches them for a push. Restore that behavior
for the GVFS Protocol behind a new opt-in config, gvfs.negativeRefCheck.
When set, `git push` performs a non-fetching existence check --
odb_has_object() with flags 0 implies OBJECT_INFO_QUICK |
OBJECT_INFO_SKIP_FETCH_OBJECT, so the probe never fetches -- and omits
any advertised object it does not have, exactly as Git does without the
GVFS_MISSING_OK bit. The decision is computed once in pack_objects()
because advertised ref lists can be large.
The config defaults to false, so the legacy GVFS_MISSING_OK behavior is
unchanged unless an operator opts in, keeping the fallout controllable.
* [X] This change only applies to interactions with Azure DevOps and the
GVFS Protocol.
When a user uses the --no-prefetch option, they do not get batched commit and tree packfiles before attempting a checkout. Thankfully, the GVFS Protocol has a mechanism to help here: the /gvfs/objects POST endpoint can ask for a commit and that will trigger a download of all trees needed for a checkout of that commit. When using --no-prefetch and the GVFS protocol, run this extra POST request before running a checkout. Signed-off-by: Derrick Stolee <stolee@gmail.com>
Switching branches in a VFS for Git or Scalar enlistment became drastically slower in Git v2.55. The cause is the interaction of two independent changes, not a single one. Commit 062b914 (treewide: convert users of repo_has_object_file() to has_object()), first released in v2.50, accidentally inverted the object existence check in cache_tree_fully_valid(), so that function bailed out at the root instead of validating the cache tree recursively. Commit 5217312 (cache-tree: fix inverted object existence check in cache_tree_fully_valid), first released in v2.55, correctly restored the recursion. In between, v2.54's per-source object database refactor changed the cross-source lookup order: instead of scanning all packfiles before any loose object store, it scans packed then loose per source. That change caused no observable checkout regression in v2.54 precisely because the inverted check prevented recursion and thereby masked the per-object cost. Conversely, v2.49 did recurse, yet stayed fast because its global pack-first lookup found the objects in an alternate's packs before attempting any loose lookup. v2.55 is therefore the first version combining recursive cache-tree validation with per-source packed-then-loose lookup, at a cost of roughly one wasted primary loose-object lstat() per cache-tree node. In enlistments that use an alternate object cache, that cost is severe. cache_tree_fully_valid() calls odb_has_object() hundreds of thousands of times, and ODB_HAS_OBJECT_RECHECK_PACKED clears OBJECT_INFO_QUICK, so each call performs a real lstat() in the primary loose object store before the object is found in the alternate's packfile. On a measured index with about 2.4M entries: 381,006 cache-tree nodes, 380,944 wasted lstat() calls, not a single miss; cache-tree validation took about 32 seconds and switching to a branch pointing at the same commit about 36 seconds. This merge restores the all-sources-packed-before-all-sources-loose order whenever more than one source is present. The wasted stats are gone, validation drops to about 2 seconds and branch switching to about 6-7 seconds. Presence semantics are unchanged. The trade-off needs to be stated plainly: the mitigation lives in the shared object-info lookup, which is a slightly incorrect representation layer for a problem specific to presence-only queries via odb_has_object(). When an object is loose in the primary and packed in an alternate, metadata callers now observe the alternate's packed representation. Observable differences include reported on-disk size, mtime, delta base, corruption handling, and promisor-pack classification. Object content, type and logical size, as well as presence, remain correct because objects are content-addressed, which bounds the fallout to the representation level. We accept those behavior changes deliberately in exchange for fixing an intolerable regression in this fork now. The architecturally correct fix is upstream's plan to move alternate handling into the files backend. That backend would own both the primary and the alternates and could therefore scan all relevant packs before any loose-object lookup without violating the abstraction. The upstream contributor estimates that work at "three to four patch years", i.e. likely months in Git project time, and probably not before Git 2.56. microsoft/git cannot wait that long. This merge is consequently an explicitly temporary mitigation specific to Microsoft Git. Once upstream's fix lands, this implementation should be replaced and the regression test reassessed. That test currently asserts packed-versus-loose selection through %(deltabase), which necessarily pins representation ordering and may not survive the upstream architecture. A future replacement could instead verify the absence of the unwanted lstat() calls directly, possibly as a Linux-only strace test, since the behavior itself is platform-independent.
When using the GVFS protocol with `scalar clone`, the first `git fetch` issues a `/gvfs/prefetch` request to download the commits and trees that back the checked-out branch, so history operations are usable immediately after cloning. For large repositories this prefetch can dominate the clone time. Some users would rather optimize for the initial usability of the working tree and do not need full history right away; they are content to let a later fetch (including background maintenance) download the prefetch data for them. This PR adds a `--[no-]prefetch` option to `scalar clone`. With `--no-prefetch`, the initial `/gvfs/prefetch` request is skipped so the worktree becomes ready as quickly as possible. ### Implementation The prefetch-during-fetch behavior is gated by the `GVFS_PREFETCH_DURING_FETCH` bit (`1 << 7`) in `core.gvfs`, which `scalar clone` sets as part of the value `150`. Rather than persisting a different `core.gvfs` value (which would disable prefetching *forever*), `--no-prefetch` only clears that bit for the single `git fetch` invocation performed during the clone, by passing `-c core.gvfs=<value without the prefetch bit>`. The persisted `core.gvfs` is left untouched, so: - the initial clone skips the prefetch and finishes sooner, and - the **next** `git fetch` -- including the background maintenance `prefetch` task -- still performs the prefetch, hydrating the object cache shortly afterward. The option has no effect when the GVFS Protocol is not in use. ### Documentation `Documentation/scalar.adoc` documents `--[no-]prefetch`, making clear that it only affects the clone's initial fetch and that the prefetch data is still downloaded by the next fetch. ### Tests `t/t9210-scalar.sh` gains a test against the GVFS-enabled test server which asserts that: - a normal clone emits a `prefetch/since` trace event, - a `--no-prefetch` clone does not, - the persisted `core.gvfs` remains `150`, and - a subsequent `git fetch` performs the deferred prefetch.
Since f978f56 (odb: eagerly initialize alternates, 2026-08-17), config-only commands emit error-labelled diagnostics for unusable alternates even though those entries are ignored. An unset config key still returns the ordinary status 1, but VFS mistakes the accompanying diagnostics for a configuration failure and cannot recreate a deleted shared cache. Warnings keep these diagnostics visible without implying that ignoring an alternate is a command failure, and VFS already tolerates them. The message text and source rejection behavior remain unchanged. Assisted-by: GPT-6 Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
A VS x64 build linked scalar successfully, then its post-build vcpkg.exe z-applocal invocation failed with "The process cannot access the file because it is being used by another process." MSBuild reported exit 32. https://github.com/microsoft/git/actions/runs/35200873703 In vcpkg 2026-07-27, the telemetry self-copy can open the tool's executable without sharing (src/vcpkg/base/files.cpp:3757-3832), outside the DLL deployment mutex. That can prevent concurrent launches with the same diagnostic and exit status, although the CI lock owner was not recorded. Avoid this source of contention by disabling unnecessary telemetry for MSBuild, retaining native app-local DLL deployment and four workers. Assisted-by: GPT-6 Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Prepare the configuration surface for parallel POST workers before the worker implementation is introduced. Add gvfs.postThreads with a default of one so this commit does not change request execution on its own. Document the intended concurrent behavior and clamp values below one. Later commits in the series consume the value while introducing the parallel success path and then its complete failure handling. Helped-by: GPT-5.6 Sol Co-authored-by: Neil Kainga <t-neilkainga@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Neil Kainga <t-neilkainga@microsoft.com> Signed-off-by: Derrick Stolee <stolee@gmail.com>
Cargo's MSVC builds need Microsoft's `link.exe` to take precedence. 41d1d14 (rust: fix linking binaries with cargo) assumes `/mingw64/bin`, so `/ucrt64/bin` can remain ahead of MSVC in `PATH`. Honor the active MinGW environment, including SDK setups that provide `MSYSTEM` rather than `MINGW_PREFIX`. Use the modern UCRT64 default when neither is set, while explicit `MSYSTEM=MINGW64` or `MINGW_PREFIX=/mingw64` settings continue to select the legacy toolchain. Assisted-by: GPT-6 Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
The parallel POST implementation needs standalone curl handles with the same runtime settings as handles allocated through get_active_slot(). Creating raw handles would otherwise omit cookies, configured host resolutions, redirect policy, IP selection, and current authentication defaults. Extract the per-request handle preparation into a shared helper and use it from get_active_slot(). Expose a function that duplicates the initialized default handle and applies the same preparation for callers that manage a handle outside the active-slot machinery. Also expose whether cookies are configured. Libcurl cannot safely share cookie state across concurrently performing handles, so callers can retain an established sequential path in that case. Helped-by: GPT-5.6 Sol Co-authored-by: Neil Kainga <t-neilkainga@microsoft.com> Signed-off-by: Neil Kainga <t-neilkainga@microsoft.com> Signed-off-by: Derrick Stolee <stolee@gmail.com>
CMake's x64 build definitions already select UCRT64, but the runtime fallback still assumes `/mingw64`. Match the existing defaults when `system_prefix()` cannot infer the prefix from the executable location. Normal discovery and explicit architecture definitions remain unchanged. Assisted-by: GPT-6 Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Fetching a large set of missing objects through gvfs-helper performs each HTTP POST and index-pack operation sequentially. This leaves the client waiting on individual network transfers even when the server and local machine can support concurrent work. Introduce the parallel success-path mechanism. Use a mutex-protected queue to distribute full object batches across worker threads. Each worker owns a curl handle and streams each response into a fresh index-pack process. Serialize child startup while marking pipe descriptors close-on-exec so concurrent index-pack children cannot keep sibling pipes open. Keep OID formatting and result collection thread-local, and partition work into batches containing at least two objects because a single non-commit object can be returned loose instead of as a pack. This commit deliberately establishes the core worker and transfer mechanics first. The next commit completes authentication, throttling, fallback, retry, and concurrent pack installation behavior before tests exercise the new path. Helped-by: GPT-5.6 Sol Co-authored-by: Neil Kainga <t-neilkainga@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Neil Kainga <t-neilkainga@microsoft.com> Signed-off-by: Derrick Stolee <stolee@gmail.com>
The initial parallel POST path handles successful requests but does not yet match the sequential path when authentication, throttling, corrupt responses, or concurrent pack installation interfere with a request. Those differences can turn recoverable network failures into hard errors or allow sibling processes to manipulate the same pack paths. Classify HTTP and curl failures with the existing retry rules, refresh credentials outside worker threads, and preserve the cache, backup cache, and origin fallback order. Share response-header parsing with the sequential path so workers retain rate-limit telemetry while keeping soft-throttle state local to each worker. Coordinate Retry-After delays across workers without overflowing sleep intervals, and wait before starting index-pack. Serialize child setup and completion because finish_command() invalidates process-global path state. Limit the worker count to the number of queued object batches. Give each index-pack attempt unique pack and index paths, validate its reported pack hash, and retry corrupt or truncated responses. A complete final pack and index pair remains sufficient when another process wins the installation race. Group the per-attempt buffers behind one cleanup helper so success, retry, fallback, and failure paths release the same state. Helped-by: GPT-5.6 Sol Co-authored-by: Neil Kainga <t-neilkainga@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Neil Kainga <t-neilkainga@microsoft.com> Signed-off-by: Derrick Stolee <stolee@gmail.com>
Exercise gvfs-helper POST requests with both one and four configured workers so the sequential and parallel paths must fetch identical object sets. Cover multiple batches, a final single-OID remainder, and duplicate requests while checking both installed objects and packfile counts. Require pthread support for parallel cases and use Trace2 assertions to prove that each test reaches its intended execution mode. Helped-by: GPT-5.6 Sol Co-authored-by: Neil Kainga <t-neilkainga@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Neil Kainga <t-neilkainga@microsoft.com> Signed-off-by: Derrick Stolee <stolee@gmail.com>
Parallel requests need to preserve the sequential path's behavior for configuration boundaries, authentication, throttling, cache fallback, corrupt responses, and request headers. Extend the protocol test server with targeted failure modes. Verify that parallel POST refreshes authentication, honors Retry-After, falls back from cache 404 responses only when permitted, retries a one-time corrupt pack, and reports permanent corruption as an index-pack failure. Also cover absent and invalid thread configuration, cookie-enabled sequential fallback, configured headers, multiple participating workers, and a timeout-protected child-pipe stress case. Helped-by: GPT-5.6 Sol Co-authored-by: Neil Kainga <t-neilkainga@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Neil Kainga <t-neilkainga@microsoft.com> Signed-off-by: Derrick Stolee <stolee@gmail.com>
Improve full-clone performance by allowing `gvfs-helper post` to download object batches concurrently. The new `gvfs.postThreads` configuration defaults to 1, preserving the existing sequential behavior unless explicitly enabled. The series is organized into six reviewable commits: 1. Add the configuration surface. 2. Factor reusable curl-handle preparation. 3. Introduce the parallel POST success path. 4. Complete retry, authentication, fallback, throttling, and pack installation behavior. 5. Test sequential and parallel success paths. 6. Test failure handling and request-header parity. Each worker owns an independently prepared curl handle and streams responses into a dedicated `index-pack --stdin` child. Work is distributed through a mutex-protected queue, with the worker count capped by the number of object batches. Requests with configured cookies retain the established sequential path because libcurl cookie state cannot safely be shared by concurrently performing handles. The parallel path preserves the sequential HTTP policy for authentication refresh, transient errors, Retry-After, cache and backup-cache fallback, `--no-fallback`, configured headers, `X-Session-Id`, and `X-VSS-E2EID`. Sequential and parallel requests share response-header parsing, while soft-throttle state remains local to each worker. Child pipes are created and marked close-on-exec before spawning, and child setup and completion are serialized around process-global run-command state. Each `index-pack` attempt uses unique pack and index paths, validates its reported pack hash, retries corrupt or truncated responses, and tolerates another process winning installation of the same final pack. The focused `t5798-gvfs-helper-post-threads.sh` suite contains 22 tests covering configuration boundaries, sequential and parallel requests, multi-worker participation, singleton remainders, duplicate downloads, deadlock prevention, authentication, throttling, cache fallback, `--no-fallback`, corrupt packs, cookies, and configured headers. Parallel tests use pthread prerequisites and Trace2 assertions to prove the intended execution path. Neil Kainga diagnosed and tested the pipe-inheritance fix on a 1JS full clone with `gvfs.postThreads=8` and is credited throughout the series.
Matthew John Cheetham (mjcheetham)
approved these changes
Sep 23, 2026
Johannes Schindelin (dscho)
merged commit Sep 23, 2026
3906f0e
into
vfs-2.56.0-rc1
167 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Range-diff relative to clean/vfs-2.56.0-rc0
2: 7500633 = 1: e8b6f68 t: remove advice from some tests
6: 3bb63cd = 2: a837ddc survey: calculate more stats on refs
34: a3c0958 = 3: d2d8b2b survey: show some commits/trees/blobs histograms
35: 129f423 = 4: 4a763a5 survey: add vector of largest objects for various scaling dimensions
36: 5f54bff = 5: 48f7678 survey: add pathname of blob or tree to large_item_vec
37: e951402 = 6: 84ee7a3 survey: add commit-oid to large_item detail
43: 32e1bae = 7: bac7b8a fixup! ci(dockerized): do show the result of failing tests again
38: 2c92909 = 8: 679d30d survey: add commit name-rev lookup to each large_item
44: ecbca63 = 9: 7ce6a12 fixup! Add a GitHub workflow to verify that Git/Scalar work in Nano Server
39: 964775a = 10: a10d5f5 survey: add --no-name-rev option
45: 9c5e670 = 11: 91ae0a0 fixup! mingw: allow
git.exeto be used instead of the "Git wrapper"3: 48e4d91 = 12: 2a72bc2 sparse-index.c: fix use of index hashes in expand_index
40: 5766cd4 = 13: 8545e8f survey: started TODO list at bottom of source file
46: f511831 = 14: c558d23 fixup! Add an AGENTS.md file to help with AI-assisted debugging/development
1: 46eb66c = 15: 62dfe30 t5300: confirm failure of git index-pack when non-idx suffix requested
33: 1c354c3 = 16: 4b6a062 t1092: add test for untracked files and directories
41: 50dad10 = 17: 5d6b31e survey: expanded TODO list at the bottom of the source file
47: 00e67bb = 18: 3e3cda8 fixup! survey: turn into a thin shim over
git repo structure4: 43c6a23 = 19: 21a20d7 index-pack: disable rev-index if index file has non .idx suffix
42: c1cb5e4 = 20: 6e71e20 survey: expanded TODO with more notes
5: 931ef57 = 21: b6e9a10 trace2: prefetch value of GIT_TRACE2_DST_DEBUG at startup
48: b10016d = 22: 4b3f05f reset --stdin: trim carriage return from the paths
49: 9d4a892 ! 23: 2315267 Identify microsoft/git via a distinct version suffix
50: fc61c15 = 24: 387d42e gvfs: ensure that the version is based on a GVFS tag
51: f121869 = 25: 8fe0318 gvfs: add a GVFS-specific header file
52: ebc67af = 26: 6bb6cea gvfs: add the core.gvfs config setting
53: 1947436 = 27: 3104500 gvfs: add the feature to skip writing the index' SHA-1
119: b485a8f = 28: dad67c0 scalar: set the config write-lock timeout to 150ms
120: cb011a7 = 29: 0e97b91 scalar: set the config write-lock timeout to 150ms
121: 82c3d02 = 30: 6e5b9ce scalar: upgrade the config lock timeout setting automagically
122: 11d1ee2 = 31: e3d9c2c config: (handle and) warn about deprecated lock timeout setting
123: 8e34ab4 = 32: c6dcc7d scalar: add docs from microsoft/scalar
124: dc68633 = 33: 48f662a scalar (Windows): use forward slashes as directory separators
125: e08ee1e = 34: c836201 scalar: add retry logic to run_git()
126: 1d0d6e5 = 35: 8eeb0de scalar: support the
configcommand for backwards compatibility127: faac545 = 36: a9ee7c4 TO-UPSTREAM: sequencer: avoid progress when stderr is redirected
7: e3e3851 = 37: 8413b20 cat_one_file(): make it easy to see that the
sizevariable is initialized8: d63a724 = 38: 2a33af0 fsck: avoid using an uninitialized variable
9: a361fa5 = 39: 043d525 load_revindex_from_disk(): avoid accessing uninitialized data
21: 4a57bae = 40: 975532c load_pack_mtimes_file(): avoid accessing uninitialized data
10: 6588c6c = 41: 0dcf0ca revision: defensive programming
11: ea5e631 = 42: 0d6ccdd get_parent(): defensive programming
12: bd8de2b = 43: 80ee9af fetch-pack: defensive programming
24: ddf80bb = 44: 3991a05 codeql: run static analysis as part of CI builds
13: 6f8a428 = 45: 2625274 unparse_commit(): defensive programming
25: 0b9521f = 46: bebfeea codeql: publish the sarif file as build artifact
14: 7e7cb7c = 47: 8c0cfd6 verify_commit_graph(): defensive programming
26: 3925ef3 = 48: 68098e0 codeql: disable a couple of non-critical queries for now
15: 85c2ba1 = 49: 1002a1e stash: defensive programming
27: 6287b25 = 50: a728598 date: help CodeQL understand that there are no leap-year issues here
16: 18015c7 = 51: 8d99b7e stash: defensive programming
28: b5bc320 = 52: 2c56230 help: help CodeQL understand that consuming envvars is okay here
17: f1c57ea = 53: a591bf1 push: defensive programming
29: de364d2 = 54: f539aa9 ctype: help CodeQL understand that
sane_istest()does not access array past end18: 7de2e14 = 55: 63c78c3 test-tool repository: check return value of
lookup_commit()19: ed03b01 = 56: d4d2bbb fetch: defensive programming
30: 2929e38 = 57: 4647696 ctype: accommodate for CodeQL misinterpreting the
zinmallocz()20: 476eec5 = 58: 8119da8 shallow: handle missing shallow commits gracefully
22: e8e1878 = 59: b8d6506 inherit_tracking(): defensive programming
31: 86dfdfd = 60: c5c7510 strbuf_read: help with CodeQL misunderstanding that
strbuf_read()does NUL-terminate correctly23: e5f4a77 = 61: 7f82c2a commit-graph: suppress warning about using a stale stack addresses
32: 3d565bc = 62: 264244e codeql: also check JavaScript code
54: 070e4e2 ! 63: bc828ac gvfs: add the feature that blobs may be missing
55: 27a2466 = 64: efe7aac gvfs: prevent files to be deleted outside the sparse checkout
56: ac9efbf = 65: 7cd8abe gvfs: optionally skip reachability checks/upload pack during fetch
57: 552522f = 66: 9e059c1 gvfs: ensure all filters and EOL conversions are blocked
58: 0effa7c ! 67: 936c3cb gvfs: allow "virtualizing" objects
59: 697bc19 ! 68: 7078bf0 Hydrate missing loose objects in check_and_freshen()
60: d9f2b60 = 69: 52d65c3 sha1_file: when writing objects, skip the read_object_hook
61: d513d64 = 70: 0db9709 gvfs: add global command pre and post hook procs
62: 0af1253 = 71: cca50d8 t0400: verify that the hook is called correctly from a subdirectory
63: fa4dece = 72: dab4515 t0400: verify core.hooksPath is respected by pre-command
64: c9cd2e0 = 73: 379801e Pass PID of git process to hooks.
65: 6363a34 = 74: f27b308 sparse-checkout: make sure to update files with a modify/delete conflict
66: 4d3b3a5 = 75: 5f08216 worktree: allow in Scalar repositories
67: b7c15f8 = 76: e638b16 sparse-checkout: avoid writing entries with the skip-worktree bit
68: 53d1c52 = 77: 919aede Do not remove files outside the sparse-checkout
69: 8479886 = 78: d4d2f19 send-pack: do not check for sha1 file when GVFS_MISSING_OK set
70: d0e5d6b = 79: 14afb0c gvfs: allow corrupt objects to be re-downloaded
71: 0c4f86d ! 80: df9d855 cache-tree: remove use of strbuf_addf in update_one
@@ Commit message Signed-off-by: Kevin Willford <kewillf@microsoft.com> ## cache-tree.c ## -@@ cache-tree.c: static int update_one(struct cache_tree *it, +@@ cache-tree.c: static int update_one(struct repository *repo, continue; strbuf_grow(&buffer, entlen + 100); @@ cache-tree.c: static int update_one(struct cache_tree *it, + } + strbuf_add(&buffer, path + baselen, entlen); + strbuf_addch(&buffer, '\0'); - strbuf_add(&buffer, oid->hash, the_hash_algo->rawsz); + strbuf_add(&buffer, oid->hash, repo->hash_algo->rawsz); #if DEBUG_CACHE_TREE72: 71bdc1e = 81: d744a50 gvfs: block unsupported commands when running in a GVFS repo
73: 03fd1e5 = 82: 5293057 gvfs: allow overriding core.gvfs
74: b5641ef = 83: fe70f93 BRANCHES.md: Add explanation of branches and using forks
75: 8c07328 = 84: e3dce25 Add virtual file system settings and hook proc
76: 90e751b = 85: 155b7d1 virtualfilesystem: don't run the virtual file system hook if the index has been redirected
77: 694a4b5 = 86: 71d3838 virtualfilesystem: check if directory is included
78: 846ebaf = 87: 3b7e478 backwards-compatibility: support the post-indexchanged hook
79: 41f89fd = 88: 6aa05b5 gvfs: verify that the built-in FSMonitor is disabled
80: bdb2d72 = 89: 32f6ed5 wt-status: add trace2 data for sparse-checkout percentage
81: 05a3899 = 90: 9bfac18 status: add status serialization mechanism
82: 0004187 = 91: 193e7a2 Teach ahead-behind and serialized status to play nicely together
83: eb99c1d = 92: 3ab1d75 status: serialize to path
84: d1826ec = 93: 9be55c9 status: reject deserialize in V2 and conflicts
85: a7059a1 = 94: 0b0ec59 serialize-status: serialize global and repo-local exclude file metadata
86: 35c8e9d = 95: af8635a status: deserialization wait
87: 71177dd = 96: 787969c status: deserialize with -uno does not print correct hint
88: ffcf83b = 97: f29d65e fsmonitor: check CE_FSMONITOR_VALID in ce_uptodate
89: 18e72af = 98: a916773 fsmonitor: add script for debugging and update script for tests
90: de2e7db = 99: b9e929c status: disable deserialize when verbose output requested.
91: 569e9a2 = 100: 7503d99 t7524: add test for verbose status deserialzation
92: cb3b7bc = 101: 5aa1c05 deserialize-status: silently fallback if we cannot read cache file
94: bb605dd = 102: 115a64e gvfs:trace2:data: add trace2 tracing around read_object_process
96: 603a821 = 103: ec1b027 gvfs:trace2:data: status deserialization information
98: 8f7c018 = 104: 6c3dfbd gvfs:trace2:data: status serialization
100: c57a0fa = 105: b5d3600 gvfs:trace2:data: add vfs stats
102: 0328598 = 106: 9ae932b trace2: refactor setting process starting time
104: d877e37 = 107: 3f1d7c1 trace2:gvfs:experiment: report_tracking
93: 8819c18 = 108: 8718e26 git.c: add VFS enabled cmd blocking
105: 07bd962 = 109: f0e4207 trace2:gvfs:experiment: read_cache: annotate thread usage in read-cache
95: 465d16d = 110: be11956 git.c: permit repack cmd in Scalar repos
106: b80dc76 ! 111: dc929de trace2:gvfs:experiment: read-cache: time read/write of cache-tree extension
@@ read-cache.c: static int read_index_extension(struct index_state *istate, switch (CACHE_EXT(ext)) { case CACHE_EXT_TREE: + trace2_region_enter("index", "read/extension/cache_tree", NULL); - istate->cache_tree = cache_tree_read(data, sz); + istate->cache_tree = cache_tree_read(istate->repo, data, sz); + trace2_data_intmax("index", NULL, "read/extension/cache_tree/bytes", (intmax_t)sz); + trace2_region_leave("index", "read/extension/cache_tree", NULL); break; @@ read-cache.c: static int do_write_index(struct index_state *istate, struct tempf strbuf_reset(&sb); + trace2_region_enter("index", "write/extension/cache_tree", NULL); - cache_tree_write(&sb, istate->cache_tree); + cache_tree_write(istate->repo, &sb, istate->cache_tree); err = write_index_ext_header(f, eoie_c, CACHE_EXT_TREE, sb.len) < 0; hashwrite(f, sb.buf, sb.len); + trace2_data_intmax("index", NULL, "write/extension/cache_tree/bytes", (intmax_t)sb.len);97: 2960ca8 = 112: 491ddfa git.c: permit fsck cmd in Scalar repos
107: d01c480 = 113: b407c07 trace2:gvfs:experiment: add region to apply_virtualfilesystem()
99: 54c0591 = 114: 76b2053 git.c: permit prune cmd in Scalar repos
108: 4637647 = 115: 6dfe362 trace2:gvfs:experiment: add region around unpack_trees()
101: 1805df9 = 116: af6ff28 worktree: remove special case GVFS cmd blocking
109: ad44619 ! 117: 7554357 trace2:gvfs:experiment: add region to cache_tree_fully_valid()
103: 9c8e4f5 = 118: b51cffb builtin/repack.c: emit warning when shared cache is present
110: afce0be = 119: 26176b8 trace2:gvfs:experiment: add unpack_entry() counter to unpack_trees() and report_tracking()
111: 4bd0068 = 120: f09b67d trace2:gvfs:experiment: increase default event depth for unpack-tree data
112: bc48a14 = 121: 65f6c35 trace2:gvfs:experiment: add data for check_updates() in unpack_trees()
113: e062a65 = 122: 11ffcc8 Trace2:gvfs:experiment: capture more 'tracking' details
114: 776be05 = 123: 3fa557b credential: set trace2_child_class for credential manager children
115: e9d624a = 124: bc332b6 sub-process: do not borrow cmd pointer from caller
116: 75e2cab = 125: 09086b7 sub-process: add subprocess_start_argv()
117: 352e3e6 = 126: fa9f21e sha1-file: add function to update existing loose object cache
118: 1c21c53 = 127: 502918c index-pack: avoid immediate object fetch while parsing packfile
128: 827daec = 128: fcb6c54 gvfs-helper: create tool to fetch objects using the GVFS Protocol
129: de7a132 = 129: 2db620a sha1-file: create shared-cache directory if it doesn't exist
-: ----------- > 130: c5d6bc6 fixup! sha1-file: create shared-cache directory if it doesn't exist
130: 4aeefd4 = 131: 51f1386 gvfs-helper: better handling of network errors
131: 16bf382 = 132: 7f4a505 gvfs-helper-client: properly update loose cache with fetched OID
132: fb6b166 = 133: aea7e33 gvfs-helper: V2 robust retry and throttling
133: bfb2b53 = 134: 6780db4 gvfs-helper: expose gvfs/objects GET and POST semantics
134: 57a5026 = 135: ca5a532 gvfs-helper: dramatically reduce progress noise
135: 8feadb0 = 136: 669cda6 gvfs-helper: handle pack-file after single POST request
136: b82e5fd ! 137: 57d89ba test-gvfs-prococol, t5799: tests for gvfs-helper
137: 7393b9b = 138: d0bbcdd gvfs-helper: move result-list construction into install functions
138: fa05036 = 139: b6b3d0f t5799: add support for POST to return either a loose object or packfile
139: f299bd2 = 140: 085879c t5799: cleanup wc-l and grep-c lines
140: bdf8316 = 141: 1761118 gvfs-helper: verify loose objects after write
141: a0935f0 = 142: 9e4d6d2 t7599: create corrupt blob test
142: 55e7432 ! 143: a366684 gvfs-helper: add prefetch support
143: 39ffced = 144: 9081419 gvfs-helper: add prefetch .keep file for last packfile
144: e09132d = 145: 3525dc8 gvfs-helper: do one read in my_copy_fd_len_tail()
145: ea44858 = 146: c49e061 gvfs-helper: move content-type warning for prefetch packs
146: 799b046 = 147: da218cf fetch: use gvfs-helper prefetch under config
147: 8bbc3ae = 148: 5a0c9ce gvfs-helper: better support for concurrent packfile fetches
148: cd13c40 = 149: d35d1ad remote-curl: do not call fetch-pack when using gvfs-helper
149: cbac56f = 150: 8a3a478 fetch: reprepare packs before checking connectivity
150: f66ba48 = 151: e6abb7b gvfs-helper: retry when creating temp files
151: a81292e = 152: 9074f57 sparse: avoid warnings about known cURL issues in gvfs-helper.c
163: c6476e4 = 153: ae1b721 gvfs-helper: add --max-retries to prefetch verb
166: 146e046 = 154: 550d785 t5799: add tests to detect corrupt pack/idx files in prefetch
169: 5b86976 = 155: 824accb gvfs-helper: ignore .idx files in prefetch multi-part responses
172: 8199341 = 156: 1c06ba8 t5799: explicitly test gvfs-helper --fallback and --no-fallback
175: 0ac5663 = 157: 8f1f114 gvfs-helper: don't fallback with new config
177: 28136c3 = 158: cf79810 test-gvfs-protocol: add cache_http_503 to mayhem
152: 0e9b50b = 159: 15955cf maintenance: care about gvfs.sharedCache config
179: 5443476 = 160: b5cab59 t5799: add unit tests for new
gvfs.fallbackconfig setting153: bdd9ee9 = 161: cb7ad0b unpack-trees:virtualfilesystem: Improve efficiency of clear_ce_flags
160: 0aa9ecc = 162: db7bf8e update-microsoft-git: create barebones builtin
162: e9f57fb = 163: 3d22821 update-microsoft-git: Windows implementation
165: da68df6 = 164: 236dd62 update-microsoft-git: use brew on macOS
168: 6064249 = 165: 87eff26 .github: reinstate ISSUE_TEMPLATE.md for microsoft/git
171: 365ecfd = 166: 0ca8687 .github: update PULL_REQUEST_TEMPLATE.md
154: 7cc0768 = 167: e083895 Disable the
monitor-componentsworkflow in msft-git174: 1fa3d0b = 168: 3d8b726 Adjust README.md for microsoft/git
155: 79a7d58 = 169: 0c2b041 .github: enable windows builds on microsoft fork
156: ed2a8b4 = 170: a6fc155 .github/actions/akv-secret: add action to get secrets
157: b76e04a = 171: 1cb5171 release: create initial Windows installer build workflow
181: c57d4f9 = 172: 9959362 scalar: implement a minimal JSON parser
158: 97ba474 = 173: 3b76db4 help: special-case HOST_CPU
universal182: a37814f = 174: 2afa625 scalar clone: support GVFS-enabled remote repositories
159: dfb31a0 = 175: 0f618ed release: add Mac OSX installer build
183: 0276544 = 176: bc5eb4b test-gvfs-protocol: also serve smart protocol
161: 857c903 = 177: d52f6fb release: build unsigned Ubuntu .deb package
184: 7b4bab3 = 178: 284e0a0 gvfs-helper: add the
endpointcommand164: 3506782 = 179: 3abdd32 release: add signing step for .deb package
185: e383855 = 180: 1f84a71 dir_inside_of(): handle directory separators correctly
167: 1a30429 = 181: a4ca71e release: create draft GitHub release with packages & installers
186: fd05203 = 182: e629027 scalar: disable authentication in unattended mode
170: 48fd064 = 183: dd44bd0 build-git-installers: publish gpg public key
187: 016458c = 184: 6a60f66 abspath: make strip_last_path_component() global
173: bd980c7 = 185: ad19277 release: continue pestering until user upgrades
188: 2241451 = 186: 59077f5 scalar: do initialize
gvfs.sharedCache176: e34165e = 187: 6721b29 dist: archive HEAD instead of HEAD^{tree}
189: 5b87ef2 = 188: 9531cdf scalar diagnose: include shared cache info
178: 2e92df1 = 189: b280761 release: include GIT_BUILT_FROM_COMMIT in MacOS build
190: 888593b = 190: 04149c4 scalar: only try GVFS protocol on https:// URLs
180: 85154d9 = 191: fa4f8aa release: remove the obsolete GitHub installer workflow
192: 1673edc = 192: ac5e537 add/rm: allow adding sparse entries when virtual
194: 6fb81e9 = 193: 89e87c5 sparse-checkout: add config to disable deleting dirs
196: b30ac75 = 194: ecac8e8 diff: ignore sparse paths in diffstat
191: b61c6b5 = 195: e4e0016 scalar: verify that we can use a GVFS-enabled repository
198: e6d5e92 = 196: 3488094 repo-settings: enable sparse index by default
193: ef2763e = 197: 10ebb67 scalar: add the
cache-servercommand195: c4433f9 = 198: 161442e scalar: add a test toggle to skip accessing the vsts/info endpoint
197: 04a9e88 = 199: 70e8e5d scalar: adjust documentation to the microsoft/git fork
202: 94094dd = 200: bae5811 TO-CHECK: t1092: use quiet mode for rebase tests
199: 4dbdb32 = 201: df33d6d scalar: enable untracked cache unconditionally
204: 7061a7f = 202: 75d5414 reset: fix mixed reset when using virtual filesystem
200: f75c7d8 = 203: dbef07a scalar: parse
clone --no-fetch-commits-and-treesfor backwards compatibility206: 1dfacca = 204: 4e56187 diff(sparse-index): verify with partially-sparse
201: a9dc475 = 205: e53877a scalar: make GVFS Protocol a forced choice
208: 19853e6 = 206: 32e5af4 stash: expand testing for
git stash -u203: eb6abab = 207: fab48c9 scalar: work around GVFS Protocol HTTP/2 failures
210: eccb43c = 208: f963cdc sparse-index: add ensure_full_index_with_reason()
205: 8e69605 = 209: f70640d gvfs-helper-client: clean up server process(es)
212: 0439844 = 210: cedaeec treewide: add reasons for expanding index
207: bfdf76c = 211: 42890de scalar diagnose: accommodate Scalar's Functional Tests
213: ae5c4a0 = 212: 4a598f6 treewide: custom reasons for expanding index
209: 24ea019 = 213: 555d92e ci: run Scalar's Functional Tests
214: 6157538 = 214: 7a1ee60 sparse-index: add macro for unaudited expansions
211: 600c1aa = 215: e79d611 scalar: upgrade to newest FSMonitor config setting
215: 3dd67ab = 216: f13ff22 Docs: update sparse index plan with logging
216: 05b87ce = 217: 118b6bb sparse-index: log failure to clear skip-worktree
217: c269a09 = 218: 713abdb stash: use -f in checkout-index child process
218: e92a8e5 = 219: ffa770d sparse-index: do not copy hashtables during expansion
219: aa73a14 = 220: b74aa97 TO-UPSTREAM: sub-process: avoid leaking
cmd220: 4ceed76 = 221: bf9f191 remote-curl: release filter options before re-setting them
221: 44ff449 = 222: 84b8512 transport: release object filter options
222: f9c3c53 = 223: 9acea34 push: don't reuse deltas with path walk
223: bcc1ac7 = 224: 5d6b49f maintenance: add cache-local-objects maintenance task
224: 7a0c0e5 = 225: 6dab639 scalar.c: add cache-local-objects task
225: ef56408 = 226: 0cc3de9 hooks: add custom post-command hook config
226: b8de263 = 227: 54006fe TO-UPSTREAM: Docs: fix asciidoc failures from short delimiters
227: 1df86bc = 228: 699c357 hooks: make hook logic memory-leak free
228: 5a24d2a = 229: 7eba3af t0401: test post-command for alias, version, typo
229: cb7bbfc = 230: 8558aa6 hooks: better handle config without gitdir
230: 5fc95bf = 231: c77fe05 scalar: add run_git_argv
231: 8a7979b = 232: 7d67fa7 scalar: add --ref-format option to scalar clone
232: 3ae1bee = 233: 677b777 gvfs-helper: skip collision check for loose objects
233: 9e73837 = 234: 9a5a7d8 gvfs-helper: emit advice on transient errors
234: b1f4c82 = 235: 6edf57e gvfs-helper: avoid collision check for packfiles
235: 720fdc8 = 236: 25778e2 t5799: update cache-server methods for multiple instances
236: 890f643 = 237: c8341af gvfs-helper: override cache server for prefetch
237: 5b5d6c0 = 238: d8b669f gvfs-helper: override cache server for get
238: 89ecacd = 239: 2296011 gvfs-helper: override cache server for post
239: 01a0ed3 = 240: 3a717d1 t5799: add test for all verb-specific cache-servers together
240: 100cbc2 = 241: 22f9441 lib-gvfs-helper: create helper script for protocol tests
241: 75571e4 = 242: 8e807f3 t579*: split t5799 into several parts
242: 2869828 = 243: 8f24271 scalar: add ---cache-server-url options
243: ae96f88 = 244: d8ae2cf Restore previous errno after post command hook
244: dc15249 = 245: 876afc3 t9210: differentiate origin and cache servers
245: 73a7700 = 246: e17bbfd unpack-trees: skip lstats for deleted VFS entries in checkout
246: e08e189 = 247: 8073299 worktree: conditionally allow worktree on VFS-enabled repos
248: dfc9ab9 ! 248: fce704b gvfs-helper: create shared object cache if missing
247: c9dc6e0 ! 249: 1f725d7 gvfs-helper: send X-Session-Id headers
249: cb1bad8 = 250: 204ccf2 gvfs: add gvfs.sessionKey config
250: 590d648 = 251: a044a27 gvfs: clear DIE_IF_CORRUPT in streaming incore fallback
251: 01c47a7 = 252: 334fb47 worktree remove: use GVFS_SUPPORTS_WORKTREES for skip-clean-check gate
252: 4ec183e = 253: ef7f7fd ci: add new VFS for Git functional tests workflow
253: 4fcd4e2 = 254: 08cd50f azure-pipelines: add stub release pipeline for Azure
254: f47fc02 = 255: 4793e5f diff: add renameThreshold configuration option
255: ca2cb70 = 256: 50951a5 gvfs-helper: separate packfile extraction from indexing
256: 562d21c = 257: f2e175d blame: add blame.renames, blame.renameThreshold, blame.renameLimit
257: de8f73c = 258: e20ff86 gvfs-helper: run prefetch index-pack in parallel
258: 65359b9 = 259: 244d595 gvfs-helper: add gvfs.prefetchThreads config for parallel prefetch
259: fcba8de = 260: 1631c47 azure-pipelines: add ESRP code signing
260: 4a4c90b = 261: eb515d7 azure-pipelines: allow overriding Git version
261: 8d8da1d = 262: cff8a32 azure-pipelines: build, sign and stage the Linux Debian package
262: 0cb444a = 263: bac85b6 azure-pipelines: add signed macOS ARM64 releases
263: 7188b5e = 264: de16895 azure-pipelines: build, sign and stage the Windows installer
264: dc99c1f = 265: 3051db2 azure-pipelines: enable on tag push, default ESRP and GitHub release on
265: 7243306 = 266: 36f0c21 release: binskim for Windows
266: 7215421 = 267: e26f975 release: suppress unfixable binskim findings
267: a75c9be = 268: 1ac3713 binskim: add baseline
268: 7f8af06 = 269: 7b3aa78 checkout: preserve skip-worktree for virtual filesystem paths
269: 6367af0 (upstreamed as: ce6f9ff) < -: ----------- rust: pick a GCC-compatible Cargo target under MSYS2/MinGW
270: 24cb175 = 270: 428f04e ci(vfs): install the GCC-compatible Rust target before building
271: 0dfa153 = 271: f0a9340 release-homebrew: add a hand-run script to replace the workflow
272: 6631971 = 272: 6f360f9 release-vfsforgit: add hand-run script to supersede the workflow
273: c282088 = 273: 5a089ba .github: add release-winget.sh to open winget-pkgs PR
274: 984500a = 274: 9b99ba8 trace2: tolerate failed timestamp formatting
275: 9166bf9 = 275: 846d5de reset --mixed: clear skip-worktree for all changed entries in VFS mode
276: 661a3ec = 276: 36faa37 send-pack: add gvfs.negativeRefCheck to skip missing negatives
277: 1db3949 ! 277: 74d7f80 odb: scan all sources' packfiles before loose objects
@@ Commit message Signed-off-by: Tyrie Vella <tyrielv@gmail.com> ## odb.c ## -@@ odb.c: static int register_all_submodule_sources(struct object_database *odb) - return ret; +@@ odb.c: void disable_obj_read_lock(void) + pthread_mutex_destroy(&obj_read_mutex); } +static enum odb_read_status read_object_info_from_sources(278: 077213e = 278: 6fd9369 scalar: add --[no-]prefetch option
279: a18dd2a = 279: a8aab29 scalar: request for commit via POST
280: 478fbc7 = 280: 919a530 odb: warn when ignoring unusable alternates
281: a67c7c2 = 281: 7bf7e90 ci: avoid vcpkg telemetry contention during MSBuild
282: 9e91310 = 282: a3273f7 rust: honor the active MinGW prefix when invoking Cargo
283: b91c1f8 = 283: 92bfd44 cmake: default the Windows runtime prefix to UCRT64
284: 65c9292 = 284: 5ae7fad gvfs-helper: add gvfs.postThreads config option
285: 142551d = 285: 2b87ce6 http: factor reusable curl handle preparation
286: 98a8cdf = 286: dc15f86 gvfs-helper: parallelize POST object requests
287: 79c7b55 = 287: e86ce06 gvfs-helper: preserve POST failure handling in parallel mode
288: 551e1d7 = 288: bc00162 t5798: test parallel POST object requests
289: f332ea4 = 289: eefe24c t5798: test parallel POST failure handling
(
clean/vfs-2.56.0-rc0is a heavily auto-squashed, tree-same version of #984's PR branch)