Skip to content

[pull] master from microsoft:master#65

Merged
pull[bot] merged 10 commits intocgallred:masterfrom
microsoft:master
Mar 23, 2026
Merged

[pull] master from microsoft:master#65
pull[bot] merged 10 commits intocgallred:masterfrom
microsoft:master

Conversation

@pull
Copy link
Copy Markdown

@pull pull bot commented Mar 23, 2026

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

tyrielv and others added 10 commits March 18, 2026 11:51
Acquire a FileBasedLock on .gvfs/mount.lock at the start of
InProcessMount.Mount() before any resource initialization or pipe
creation. If a second GVFS.Mount.exe process starts for the same
repo, it fails to acquire the lock and exits cleanly, allowing the
first process to complete without conflict.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the slow git ls-tree -r -d HEAD approach (~25s on a large repo
with 2.8 million files) with in-memory projection tree walk (~78ms) via
FolderData.GetRecursiveFolderCount.

- Add GitIndexProjection.GetProjectedFolderCount for mounted repos
- Add GitIndexProjection.CountIndexFolders (git index parser) as fallback
  for unmounted repos (gvfs health --status)
- Add GitStatusCache.SetProjectedFolderCountProvider, called by
  FileSystemCallbacks after GitIndexProjection is created
- Make projectedFolderCountProvider a required parameter of CreateSummary
- Remove GetHeadTreeCount, GetHeadTreeId, and TreeCountCache.dat
- Add GVFSEnlistment.GitIndexPath convenience property
- Fix activeHydrationTask race (Interlocked.Exchange) and add bounded
  Dispose wait
- Rewrite EnlistmentHydrationSummaryTests for CountIndexFolders

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When git commands like cherry-pick -n or merge stage changes directly
(as opposed to user edits followed by git add), those staged files have
skip-worktree set and are not in the GVFS ModifiedPaths database. A
subsequent 'restore --staged' then fails to properly unstage them:
- Modified/deleted files become invisible to git status
- Added files (ProjFS placeholders) vanish on projection changes

Fix by sending a PreUnstage pipe message from the pre-command hook
before 'restore --staged' or 'checkout HEAD --' runs:
1. Query staged files via 'git diff --cached --name-status -z' matching
   the command's pathspec, and add them to ModifiedPaths so git clears
   skip-worktree and detects their working tree state
2. For staged-added files, write their content to disk via batched
   'git checkout-index --force' (with hooks bypassed to avoid deadlock)
   so they persist as full files across projection changes

Pathspecs are forwarded from the hook args to scope the operation,
avoiding unnecessary ModifiedPaths additions during large merge
conflict resolutions. On failure, the hook blocks with an actionable
error message rather than allowing silent corruption.

Components:
- GVFS.Hooks/Program.Unstage.cs: detect unstage operations, extract
  pathspecs, send PreUnstage message, block on failure
- GVFS.Mount/InProcessMount.cs: handle PreUnstage message
- GVFS.Virtualization/FileSystemCallbacks.cs: AddStagedFilesToModifiedPaths
  queries staged files, adds to ModifiedPaths, hydrates added files
- GVFS.Common/Git/GitProcess.cs: DiffCachedNameStatus, batched
  CheckoutIndexForFiles, QuoteGitPath for safe path escaping
- GVFS.Common/NamedPipes/UnstageNamedPipeMessages.cs: message type
- CorruptionReproTests.cs: functional test
- GitProcessTests.cs: QuoteGitPath unit + integration tests

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ount lock

- Add TryAcquireLock(out Exception) to FileBasedLock so callers can
  pattern-match on exception type to distinguish lock contention
  (IOException/sharing violation) from permission or I/O errors.
- Replace bare return with FailMountAndExit() when lock acquisition
  fails, so the process exits with a non-zero exit code.
- Add ReturnCode.MountAlreadyRunning (8) for the lock contention case,
  keeping GenericError (3) for unexpected lock failures.
- Add FailMountAndExit(ReturnCode, ...) overload to support per-call
  exit codes while preserving existing callers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…path

CountIndexFolders now applies the same entry filter as
AddIndexEntryToProjection so the unmounted fallback folder count
matches the mounted projection tree walk.

Added three test cases for the filtering behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add mount lock to prevent concurrent mount race condition
…ection

Replace git ls-tree with projection-based folder count
…thspec-from-file

Fix three issues identified in code review:

1. HIGH: AddStagedFilesToModifiedPaths now returns failure when
   git diff --cached exits non-zero, instead of silently succeeding
   with addedCount=0 (which re-opened the corruption this PR fixes).

2. MEDIUM: GetRestorePathspec now strips the tree-ish argument for
   checkout commands (e.g. HEAD in 'checkout HEAD -- file'), and
   skips --source/-s values for restore commands, preventing
   accidental pathspec scope widening.

3. MEDIUM: --pathspec-from-file and --pathspec-file-nul are now
   forwarded through the IPC protocol to the mount process, which
   passes them directly to git diff --cached. The hook never reads
   the file itself -- git handles all pathspec parsing on both sides.
   Stdin (-) is unsupported in hook context and fails closed.

Refactors parsing logic into UnstageCommandParser (public static class
in a separate file) so it can be linked into GVFS.UnitTests without
pulling in the full GVFS.Hooks Exe assembly.

DiffCachedNameStatus now accepts optional pathspecFromFile and
pathspecFileNul parameters.

IPC message body format extended:
  null/empty        -> all staged files
  path1\0path2      -> inline pathspecs (unchanged)
  \nF\n<filepath>   -> --pathspec-from-file
  \nFZ\n<filepath>  -> --pathspec-from-file + --pathspec-file-nul

Adds 28 unit tests covering IsUnstageOperation and GetRestorePathspec.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fix corruption when unstaging changes made by git commands
@pull pull bot locked and limited conversation to collaborators Mar 23, 2026
@pull pull bot added the ⤵️ pull label Mar 23, 2026
@pull pull bot merged commit 1cf5fea into cgallred:master Mar 23, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant