From 2fe4e0d05cda9ab46e0afee9699265ae99d64b35 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 14:13:33 +0000 Subject: [PATCH 1/4] build(deps): bump actions/upload-artifact from 4 to 6 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 6. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v4...v6) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 1b466edda..07ad4f014 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -177,21 +177,21 @@ jobs: - name: Upload functional tests drop if: steps.skip.outputs.result != 'true' - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: FunctionalTests_${{ matrix.configuration }} path: artifacts\GVFS.FunctionalTests - name: Upload FastFetch drop if: steps.skip.outputs.result != 'true' - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: FastFetch_${{ matrix.configuration }} path: artifacts\FastFetch - name: Upload installers if: steps.skip.outputs.result != 'true' - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: Installers_${{ matrix.configuration }} path: artifacts\GVFS.Installers @@ -249,7 +249,7 @@ jobs: - name: Upload installation logs if: always() && steps.skip.outputs.result != 'true' - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: InstallationLogs_${{ matrix.configuration }}_${{ matrix.architecture }}-${{ matrix.nr }} path: install\logs @@ -264,14 +264,14 @@ jobs: - name: Upload functional test results if: always() && steps.skip.outputs.result != 'true' - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: FunctionalTests_Results_${{ matrix.configuration }}_${{ matrix.architecture }}-${{ matrix.nr }} path: TestResult.xml - name: Upload Git trace2 output if: always() && steps.skip.outputs.result != 'true' - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: GitTrace2_${{ matrix.configuration }}_${{ matrix.architecture }}-${{ matrix.nr }} path: C:\temp\git-trace2.log From 283c25295346f4a6f7e21dd8a34d1b3b8004440b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 14:13:36 +0000 Subject: [PATCH 2/4] build(deps): bump actions/download-artifact from 5 to 7 Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 5 to 7. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v5...v7) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 1b466edda..f79675e99 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -220,14 +220,14 @@ jobs: - name: Download installers if: steps.skip.outputs.result != 'true' - uses: actions/download-artifact@v5 + uses: actions/download-artifact@v7 with: name: Installers_${{ matrix.configuration }} path: install - name: Download functional tests drop if: steps.skip.outputs.result != 'true' - uses: actions/download-artifact@v5 + uses: actions/download-artifact@v7 with: name: FunctionalTests_${{ matrix.configuration }} path: ft From da88dca72ffd3aeb83c68db2f03439ff04393ec0 Mon Sep 17 00:00:00 2001 From: Tyrie Vella Date: Mon, 12 Jan 2026 07:58:32 -0800 Subject: [PATCH 3/4] Config flag for showing hydration status Some users are reporting issues (both performance and reliability) with the new hydration status feature. * Add a config flag to enable or disable hydration status calculation and reporting as part of git status. The flag is disabled by default. * Add "--porcelain" as an arg that disables hydration status reporting for scripting scenarios. * Update the "run gvfs health for details" message to clarify that it should be run at the repo root to correspond to the summary. --- GVFS/GVFS.Common/Enlistment.cs | 13 +++++++++ GVFS/GVFS.Common/GVFSConstants.cs | 3 ++ GVFS/GVFS.Common/GitStatusCache.cs | 5 ++-- .../EnlistmentHydrationSummary.cs | 4 +-- GVFS/GVFS.Hooks/Program.cs | 29 +++++++++++++++++-- .../Common/GitStatusCacheTests.cs | 4 +-- 6 files changed, 50 insertions(+), 8 deletions(-) diff --git a/GVFS/GVFS.Common/Enlistment.cs b/GVFS/GVFS.Common/Enlistment.cs index 090a81c9e..9e40b309c 100644 --- a/GVFS/GVFS.Common/Enlistment.cs +++ b/GVFS/GVFS.Common/Enlistment.cs @@ -122,5 +122,18 @@ public bool GetTrustPackIndexesConfig() return trustPackIndexes; } + + public bool GetStatusHydrationConfig() + { + var gitProcess = this.CreateGitProcess(); + + if (gitProcess.TryGetFromConfig(GVFSConstants.GitConfig.ShowHydrationStatus, forceOutsideEnlistment: false, out var valueString) + && bool.TryParse(valueString, out var statusHydrationConfig)) + { + return statusHydrationConfig; + } + + return GVFSConstants.GitConfig.ShowHydrationStatusDefault; + } } } diff --git a/GVFS/GVFS.Common/GVFSConstants.cs b/GVFS/GVFS.Common/GVFSConstants.cs index f2f05fc02..3f3abecc4 100644 --- a/GVFS/GVFS.Common/GVFSConstants.cs +++ b/GVFS/GVFS.Common/GVFSConstants.cs @@ -42,6 +42,9 @@ public static class GitConfig /* Intended to be a temporary config to allow testing of distrusting pack indexes from cache server * before it is enabled by default. */ public const string TrustPackIndexes = GVFSPrefix + "trust-pack-indexes"; + + public const string ShowHydrationStatus = GVFSPrefix + "show-hydration-status"; + public const bool ShowHydrationStatusDefault = false; } public static class LocalGVFSConfig diff --git a/GVFS/GVFS.Common/GitStatusCache.cs b/GVFS/GVFS.Common/GitStatusCache.cs index 717e7aebc..8ef6b3743 100644 --- a/GVFS/GVFS.Common/GitStatusCache.cs +++ b/GVFS/GVFS.Common/GitStatusCache.cs @@ -52,7 +52,7 @@ public class GitStatusCache : IDisposable private object cacheFileLock = new object(); - internal static bool TEST_EnableHydrationSummary = true; + internal static bool? TEST_EnableHydrationSummaryOverride = null; public GitStatusCache(GVFSContext context, GitStatusCacheConfig config) : this(context, config.BackoffTime) @@ -341,7 +341,8 @@ private void RebuildStatusCacheIfNeeded(bool ignoreBackoff) private void UpdateHydrationSummary() { - if (!TEST_EnableHydrationSummary) + bool enabled = TEST_EnableHydrationSummaryOverride ?? this.context.Enlistment.GetStatusHydrationConfig(); + if (!enabled) { return; } diff --git a/GVFS/GVFS.Common/HealthCalculator/EnlistmentHydrationSummary.cs b/GVFS/GVFS.Common/HealthCalculator/EnlistmentHydrationSummary.cs index 02a32c2f5..03ff6147b 100644 --- a/GVFS/GVFS.Common/HealthCalculator/EnlistmentHydrationSummary.cs +++ b/GVFS/GVFS.Common/HealthCalculator/EnlistmentHydrationSummary.cs @@ -28,12 +28,12 @@ public string ToMessage() { if (!IsValid) { - return "Error calculating hydration. Run 'gvfs health' for details."; + return "Error calculating hydration summary. Run 'gvfs health' at the repository root for hydration status details."; } int fileHydrationPercent = TotalFileCount == 0 ? 0 : (100 * HydratedFileCount) / TotalFileCount; int folderHydrationPercent = TotalFolderCount == 0 ? 0 : ((100 * HydratedFolderCount) / TotalFolderCount); - return $"{fileHydrationPercent}% of files and {folderHydrationPercent}% of folders hydrated. Run 'gvfs health' for details."; + return $"{fileHydrationPercent}% of files and {folderHydrationPercent}% of folders hydrated. Run 'gvfs health' at the repository root for details."; } public static EnlistmentHydrationSummary CreateSummary( diff --git a/GVFS/GVFS.Hooks/Program.cs b/GVFS/GVFS.Hooks/Program.cs index 0bfe0da54..d48230a2a 100644 --- a/GVFS/GVFS.Hooks/Program.cs +++ b/GVFS/GVFS.Hooks/Program.cs @@ -88,8 +88,9 @@ private static void RunPreCommands(string[] args) ProcessHelper.Run("gvfs", "prefetch --commits", redirectOutput: false); break; case "status": - /* If status is being run to serialize for caching, skip the health display */ - if (!args.Any(arg => arg.StartsWith("--serialize", StringComparison.OrdinalIgnoreCase))) + /* If status is being run to serialize for caching, or if --porcelain is specified, skip the health display */ + if (!ArgsBlockHydrationStatus(args) + && ConfigurationAllowsHydrationStatus()) { /* Display a message about the hydration status of the repo */ ProcessHelper.Run("gvfs", "health --status", redirectOutput: false); @@ -98,6 +99,30 @@ private static void RunPreCommands(string[] args) } } + private static bool ArgsBlockHydrationStatus(string[] args) + { + return args.Any(arg => + arg.StartsWith("--serialize", StringComparison.OrdinalIgnoreCase) + || arg.StartsWith("--porcelain", StringComparison.OrdinalIgnoreCase)); + } + + private static bool ConfigurationAllowsHydrationStatus() + { + try + { + ProcessResult result = ProcessHelper.Run("git", $"config --get {GVFSConstants.GitConfig.ShowHydrationStatus}"); + bool hydrationStatusEnabled; + if (bool.TryParse(result.Output.Trim(), out hydrationStatusEnabled)) + { + return hydrationStatusEnabled; + } + } + catch (Exception) + { + } + return GVFSConstants.GitConfig.ShowHydrationStatusDefault; + } + private static void ExitWithError(params string[] messages) { foreach (string message in messages) diff --git a/GVFS/GVFS.UnitTests/Common/GitStatusCacheTests.cs b/GVFS/GVFS.UnitTests/Common/GitStatusCacheTests.cs index 20ea38171..59737a83f 100644 --- a/GVFS/GVFS.UnitTests/Common/GitStatusCacheTests.cs +++ b/GVFS/GVFS.UnitTests/Common/GitStatusCacheTests.cs @@ -73,7 +73,7 @@ public void SetUp() this.fileSystem, new MockGitRepo(tracer, enlistment, this.fileSystem), enlistment); - GitStatusCache.TEST_EnableHydrationSummary = false; + GitStatusCache.TEST_EnableHydrationSummaryOverride = false; } [TearDown] @@ -85,7 +85,7 @@ public void TearDown() this.gitParentPath = null; this.gvfsMetadataPath = null; this.enlistmentDirectory = null; - GitStatusCache.TEST_EnableHydrationSummary = true; + GitStatusCache.TEST_EnableHydrationSummaryOverride = null; } [TestCase] From c90942741d3ee9a26f65f71abd19413c3ed960e5 Mon Sep 17 00:00:00 2001 From: Tyrie Vella Date: Mon, 12 Jan 2026 15:35:03 -0800 Subject: [PATCH 4/4] Log hydration calculation errors to telemetry --- GVFS/GVFS.Common/GitStatusCache.cs | 3 ++- .../HealthCalculator/EnlistmentHydrationSummary.cs | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/GVFS/GVFS.Common/GitStatusCache.cs b/GVFS/GVFS.Common/GitStatusCache.cs index 717e7aebc..bce8f444f 100644 --- a/GVFS/GVFS.Common/GitStatusCache.cs +++ b/GVFS/GVFS.Common/GitStatusCache.cs @@ -372,9 +372,10 @@ private void UpdateHydrationSummary() } else { + metadata["Exception"] = hydrationSummary.Error?.ToString(); this.context.Tracer.RelatedWarning( metadata, - $"{nameof(GitStatusCache)}{nameof(RebuildStatusCacheIfNeeded)}: hydration summary could not be calculdated.", + $"{nameof(GitStatusCache)}{nameof(RebuildStatusCacheIfNeeded)}: hydration summary could not be calculated.", Keywords.Telemetry); } } diff --git a/GVFS/GVFS.Common/HealthCalculator/EnlistmentHydrationSummary.cs b/GVFS/GVFS.Common/HealthCalculator/EnlistmentHydrationSummary.cs index 02a32c2f5..6762e2665 100644 --- a/GVFS/GVFS.Common/HealthCalculator/EnlistmentHydrationSummary.cs +++ b/GVFS/GVFS.Common/HealthCalculator/EnlistmentHydrationSummary.cs @@ -12,6 +12,8 @@ public class EnlistmentHydrationSummary public int TotalFileCount { get; private set; } public int HydratedFolderCount { get; private set; } public int TotalFolderCount { get; private set; } + public Exception Error { get; private set; } = null; + public bool IsValid { @@ -67,7 +69,7 @@ public static EnlistmentHydrationSummary CreateSummary( TotalFolderCount = totalFolderCount, }; } - catch + catch (Exception e) { return new EnlistmentHydrationSummary() { @@ -75,6 +77,7 @@ public static EnlistmentHydrationSummary CreateSummary( HydratedFolderCount = -1, TotalFileCount = -1, TotalFolderCount = -1, + Error = e, }; } }