Release M279 - #2080
Merged
Merged
Conversation
….vfs.0.5 Update default Microsoft Git version to v2.54.0.vfs.0.5
Add `vnext` to build.yaml's pull_request/push branch filters so the feature-integration branch gets the same CI (build + unit + functional tests) as master. This lets PRs targeting vnext produce the required status checks. Assisted-by: Claude Opus 4.8 Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
…ause The GVFS telemetry "Blob hydration failure" and "Directory enumeration failure" buckets conflate causes outside gvfs.exe's control (network, local disk/IO, ProjFS) with actionable ones (a missing object on the server, a size mismatch, or GVFS's own stale-enumeration eviction). Stamp a cause tag on the failure telemetry so the release-readiness dashboard can bucket them apart. No behavior changes: - BlobHydrationFailureCategory (nested in GVFSGitObjects) is now returned from TryCopyBlobContentStream via an out parameter as well as stamped on the terminal telemetry, so the virtualizer's own terminal event is tagged with the same cause rather than left uncategorized. Categories: NetworkUnavailable / DownloadFailed / LocalIO / ProjFSWriteFailed (not gvfs-fixable) vs ObjectNotOnServer / LocalCopyFailed / SizeMismatch / Unexpected (actionable). The size-mismatch, IOException, and WriteFileData failure sites were previously logged with a message the dashboard did not match; they now carry the tag so they are counted. - EnumerationFailureReason (nested enum) on "Failed to find active enumeration ID": Evicted (GVFS eviction removed a live enumeration; self-inflicted) vs Unknown (ProjFS delivered an id GVFS never held or already ended). The eviction-tracking map is populated before the entry is removed from the active set (closing a mislabel race) and pruned on every sweep so it cannot outlive its window. Unit tests assert each cause value deterministically. Assisted-by: Claude Opus 4.8 Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
ci: run build.yaml on vnext
Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 5 to 6. - [Release notes](https://github.com/actions/setup-dotnet/releases) - [Commits](actions/setup-dotnet@v5...v6) --- updated-dependencies: - dependency-name: actions/setup-dotnet dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
…ions/setup-dotnet-6 Bump actions/setup-dotnet from 5 to 6
….vfs.0.3 Update default Microsoft Git version to v2.55.0.vfs.0.3
The health verb always labeled its final line 'Repository status: ...' even when the calculation was scoped to a subdirectory (via -d or when run from a subdirectory of the enlistment). That could report a highly hydrated subtree as 'Highly Hydrated' at the repository level, which is misleading. When TargetDirectory is non-empty, print 'Directory status (<path>): ...' instead and add a hint suggesting the user re-run from the repo root for the full-repo status. Update the functional test regex to accept either label.
…lemetry Split blob-hydration and directory-enumeration failure telemetry by cause
RetryableException wraps its real cause in InnerException. The blob- hydration failure categorization checked the RetryableException type itself, so every RetryableException - the largest hydration failure bucket in the field - was tagged NetworkUnavailable, even when the real cause was local disk/IO. On this branch the RetryableException reaches OnFailure from Context.Repository.TryCopyBlobContentStream - typically StreamUtil wrapping an IOException while reading a corrupt or truncated local loose object. Unwrap RetryableException.InnerException before categorizing, and map IOException / UnauthorizedAccessException / Win32Exception (the local disk/IO family) to LocalIO. A RetryableException whose inner cause is not local (e.g. HttpRequestException), or that has no inner cause, stays NetworkUnavailable. Telemetry metadata only; no behavior change. Add unit tests for each inner-cause mapping (IOException, Unauthorized- AccessException, Win32Exception -> LocalIO; HttpRequestException and no inner -> NetworkUnavailable), and reset the process-global RetryCircuitBreaker in the fixture SetUp and TearDown so these failure- driving tests cannot open the circuit for one another or for a later fixture. Stacked follow-up to PR #2071; do not publish until #2071 merges. Assisted-by: Claude Opus 4.8 Signed-off-by: Tyrie Vella <tyrielv@gmail.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Attribute wrapped blob-hydration failures to their inner cause
….vfs.0.6 Update the default Microsoft Git version used by VFS for Git to the newly promoted [`v2.55.0.vfs.0.6`](https://github.com/microsoft/git/releases/tag/v2.55.0.vfs.0.6) release.
…larification gvfs health: distinguish directory-scoped status from repository status
On the GVFS 2.0 line, mount startup failed roughly twice as often as the 1.0.26014.1 LKG. The dominant 2.0-specific cause is the hook update on mount. After a GVFS upgrade changes a native hook binary, the next mount re-copies it into the enlistment via a copy-to-temp-then-rename (HooksInstaller.TryUpdateHook). The rename can fail transiently with Win32Exception (5) ERROR_ACCESS_DENIED when the existing enlistment hook is locked (open handle, AV scan). CopyHook wraps that in a retryable RetryableException, but the mount-time call site failed immediately with no retry - unlike the clone-time InstallHooks path, which retries with backoff. So a transient lock failed the whole mount. Fix 1 - retry at mount time (primary): wrap the mount-time CopyHook in the existing TryHooksInstallationAction retry helper (3x exponential backoff), matching the clone-time path. A transient ACCESS_DENIED rename is now retried, not fatal. Fix 2 - tolerate locked-but-already-correct: after retries are exhausted, if the enlistment hook already matches the installed one, treat it as success instead of failing the mount. Fix 3 - compare path resilience: reading the hook version opens the hook files, which can be transiently locked too. A compare failure no longer hard-fails the mount; it logs a telemetry warning and falls through to the resilient copy path. Change detection compares the hook FileVersion. These native (C++) hook binaries embed their GVFS version in the PE version resource, so the version differs only when a GVFS upgrade changed the hook - which is rare (roughly monthly) compared to daily mounts - so the common mount does no copy. The comparison reads the version through a small context.FileSystem.GetFileVersion seam instead of a direct static FileVersionInfo call, so the mount-time path can be unit-tested. A null/empty version is treated as "cannot confirm identical" (not a match) so a version-less binary forces the resilient copy rather than being assumed correct. The unused FileVersionInfo-returning GetVersionInfo/FileVersionsMatch/ ProductVersionsMatch (and their mock overrides) are removed. Every mount-hook outcome (MissingFromEnlistment, CompareFailed, LockedButAlreadyCorrect, CopyFailed) now emits with Keywords.Telemetry and a stable HookUpdateResult field so all outcomes are queryable together; previously the missing-hook warning bound to the params-object overload and silently dropped its metadata. Worktree behavior is unchanged (InProcessMount already skips hook install for worktrees). PhysicalFileSystem.TryCopyToTempFileAndRename is made virtual so the copy path can be unit-tested. Adds GVFS.UnitTests HooksInstallerMountUpdateTests covering: identical hook not copied, different/missing hook copied, copy-when-version-differs-despite-same- content, no-copy-when-version-matches-despite-different-content, copy-when-both- versions-null, transient copy failure retried then succeeds, locked-but-already- correct hook does not fail the mount, persistent copy failure still fails, a compare failure refreshes the hook without failing, and a missing installed hook fails without copying. Full unit suite: 887 passed. Assisted-by: Claude Opus 4.8 Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
Mount: retry hook copy and tolerate transiently-locked hooks
tyrielv
enabled auto-merge
August 10, 2026 18:14
Keith Klein (KeithIsSleeping)
approved these changes
Aug 10, 2026
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.
Changes:
gvfs health(gvfs health: distinguish directory-scoped status from repository status #2078)