From 1ea8bbd7e5756f67180c47aee46b38ad85cd1085 Mon Sep 17 00:00:00 2001 From: Tyrie Vella Date: Tue, 2 Jun 2026 14:02:46 -0700 Subject: [PATCH] fix worktree mounts using primary enlistment's .gvfs paths Worktree mounts shared the primary enlistment's .gvfs metadata (placeholder database, RepoMetadata, diagnostics, corrupt objects) instead of using their own per-worktree .gvfs directory. This caused stale file content after git reset --hard in worktrees, because placeholder tracking was shared with the primary mount. Root cause: code throughout the codebase derived .gvfs paths from EnlistmentRoot, which always resolves to the primary enlistment root even for worktree mounts. The correct property is DotGVFSRoot, which resolves to the per-worktree .gvfs for worktree mounts and the primary .gvfs for primary mounts. Product fixes: - GVFSDatabase: accept dotGVFSRoot directly instead of deriving from EnlistmentRoot; update InProcessMount, SparseVerb, DiskLayoutUpgrade, EnlistmentPathData, ProfilingEnvironment call sites - GitRepo: resolve DotGVFSRoot at construction for corrupt object paths - GVFSVerb.InitializeLocalCacheAndObjectsPaths: use DotGVFSRoot for RepoMetadata (affects dehydrate, prefetch) - DiagnoseVerb: use DotGVFSRoot for .gvfs file collection and RepoMetadata initialization - CacheVerb: use DotGVFSRoot for RepoMetadata - RequiredGitConfig: narrow parameter to GVFSEnlistment, use DotGVFSRoot - GVFSLogsRoot: derive from DotGVFSRoot instead of re-deriving - GitMaintenanceStep: check WorkingDirectoryRoot for existence - HooksInstaller: use WorkingDirectoryRoot in error messages Rename to prevent recurrence: - Rename Enlistment.EnlistmentRoot to PrimaryEnlistmentRoot, forcing every caller to explicitly choose the right path property. Audit of all ~280 references across ~75 files confirmed each usage is correct. Test: - Add WorktreeUsesPerWorktreePlaceholderDatabase functional test Assisted-by: Claude Opus 4.6 Signed-off-by: Tyrie Vella --- GVFS/FastFetch/CheckoutPrefetcher.cs | 6 +- GVFS/FastFetch/FastFetchVerb.cs | 2 +- GVFS/FastFetch/GitEnlistment.cs | 2 +- GVFS/GVFS.Common/Database/GVFSDatabase.cs | 4 +- .../DiskLayoutUpgrade_SqlitePlaceholders.cs | 2 +- GVFS/GVFS.Common/Enlistment.cs | 4 +- GVFS/GVFS.Common/FileSystem/HooksInstaller.cs | 4 +- GVFS/GVFS.Common/GVFSEnlistment.cs | 6 +- GVFS/GVFS.Common/Git/GitRepo.cs | 8 +- GVFS/GVFS.Common/Git/RequiredGitConfig.cs | 5 +- .../HealthCalculator/EnlistmentPathData.cs | 2 +- GVFS/GVFS.Common/LocalCacheResolver.cs | 2 +- .../Maintenance/GitMaintenanceStep.cs | 2 +- .../EnlistmentPerFixture/WorktreeTests.cs | 95 +++++++++++++++++++ GVFS/GVFS.Mount/InProcessMount.cs | 12 +-- GVFS/GVFS.Mount/InProcessMountVerb.cs | 2 +- .../ProfilingEnvironment.cs | 2 +- .../Common/Database/GVFSDatabaseTests.cs | 2 +- .../Common/WorktreeEnlistmentTests.cs | 2 +- .../Maintenance/GitMaintenanceQueueTests.cs | 8 +- .../Maintenance/GitMaintenanceStepTests.cs | 2 +- .../Maintenance/LooseObjectStepTests.cs | 2 +- .../PackfileMaintenanceStepTests.cs | 2 +- .../Maintenance/PostFetchStepTests.cs | 2 +- GVFS/GVFS/CommandLine/CacheVerb.cs | 2 +- GVFS/GVFS/CommandLine/CloneVerb.cs | 14 +-- GVFS/GVFS/CommandLine/DehydrateVerb.cs | 10 +- GVFS/GVFS/CommandLine/DiagnoseVerb.cs | 8 +- GVFS/GVFS/CommandLine/GVFSVerb.cs | 10 +- GVFS/GVFS/CommandLine/MountVerb.cs | 12 +-- GVFS/GVFS/CommandLine/PrefetchVerb.cs | 10 +- GVFS/GVFS/CommandLine/RepairVerb.cs | 6 +- GVFS/GVFS/CommandLine/SparseVerb.cs | 8 +- GVFS/GVFS/RepairJobs/GitConfigRepairJob.cs | 2 +- 34 files changed, 181 insertions(+), 81 deletions(-) diff --git a/GVFS/FastFetch/CheckoutPrefetcher.cs b/GVFS/FastFetch/CheckoutPrefetcher.cs index e8a48a941..4064aa7bc 100644 --- a/GVFS/FastFetch/CheckoutPrefetcher.cs +++ b/GVFS/FastFetch/CheckoutPrefetcher.cs @@ -72,7 +72,7 @@ public override void Prefetch(string branchOrCommit, bool isBranch) commitToFetch = branchOrCommit; } - using (new IndexLock(this.Enlistment.EnlistmentRoot, this.Tracer)) + using (new IndexLock(this.Enlistment.PrimaryEnlistmentRoot, this.Tracer)) { this.DownloadMissingCommit(commitToFetch, this.GitObjects); @@ -124,7 +124,7 @@ public override void Prefetch(string branchOrCommit, bool isBranch) if (!indexGen.HasFailures) { Index newIndex = new Index( - this.Enlistment.EnlistmentRoot, + this.Enlistment.PrimaryEnlistmentRoot, this.Tracer, indexGen.TemporaryIndexFilePath, readOnly: false); @@ -200,7 +200,7 @@ private Index GetSourceIndex() if (File.Exists(indexPath)) { - Index output = new Index(this.Enlistment.EnlistmentRoot, this.Tracer, indexPath, readOnly: true); + Index output = new Index(this.Enlistment.PrimaryEnlistmentRoot, this.Tracer, indexPath, readOnly: true); output.Parse(); return output; } diff --git a/GVFS/FastFetch/FastFetchVerb.cs b/GVFS/FastFetch/FastFetchVerb.cs index 27c5b1c4f..737b31ffe 100644 --- a/GVFS/FastFetch/FastFetchVerb.cs +++ b/GVFS/FastFetch/FastFetchVerb.cs @@ -240,7 +240,7 @@ private int ExecuteWithExitCode() CacheServerInfo cacheServer = new CacheServerInfo(this.GetRemoteUrl(enlistment), null); tracer.WriteStartEvent( - enlistment.EnlistmentRoot, + enlistment.PrimaryEnlistmentRoot, enlistment.RepoUrl, cacheServer.Url, new EventMetadata diff --git a/GVFS/FastFetch/GitEnlistment.cs b/GVFS/FastFetch/GitEnlistment.cs index fd08cdda0..2fec7cbbc 100644 --- a/GVFS/FastFetch/GitEnlistment.cs +++ b/GVFS/FastFetch/GitEnlistment.cs @@ -29,7 +29,7 @@ private GitEnlistment(string repoRoot, string gitBinPath) public string FastFetchLogRoot { - get { return Path.Combine(this.EnlistmentRoot, GVFSConstants.DotGit.Root, ".fastfetch"); } + get { return Path.Combine(this.PrimaryEnlistmentRoot, GVFSConstants.DotGit.Root, ".fastfetch"); } } public static GitEnlistment CreateFromCurrentDirectory(string gitBinPath) diff --git a/GVFS/GVFS.Common/Database/GVFSDatabase.cs b/GVFS/GVFS.Common/Database/GVFSDatabase.cs index 4e191a7ff..5104c504a 100644 --- a/GVFS/GVFS.Common/Database/GVFSDatabase.cs +++ b/GVFS/GVFS.Common/Database/GVFSDatabase.cs @@ -21,10 +21,10 @@ public class GVFSDatabase : IGVFSConnectionPool, IDisposable private IDbConnectionFactory connectionFactory; private BlockingCollection connectionPool; - public GVFSDatabase(PhysicalFileSystem fileSystem, string enlistmentRoot, IDbConnectionFactory connectionFactory, int initialPooledConnections = InitialPooledConnections) + public GVFSDatabase(PhysicalFileSystem fileSystem, string dotGVFSRoot, IDbConnectionFactory connectionFactory, int initialPooledConnections = InitialPooledConnections) { this.connectionPool = new BlockingCollection(); - this.databasePath = Path.Combine(enlistmentRoot, GVFSPlatform.Instance.Constants.DotGVFSRoot, GVFSConstants.DotGVFS.Databases.VFSForGit); + this.databasePath = Path.Combine(dotGVFSRoot, GVFSConstants.DotGVFS.Databases.VFSForGit); this.connectionFactory = connectionFactory; string folderPath = Path.GetDirectoryName(this.databasePath); diff --git a/GVFS/GVFS.Common/DiskLayoutUpgrades/DiskLayoutUpgrade_SqlitePlaceholders.cs b/GVFS/GVFS.Common/DiskLayoutUpgrades/DiskLayoutUpgrade_SqlitePlaceholders.cs index eeffd14e0..e5a295480 100644 --- a/GVFS/GVFS.Common/DiskLayoutUpgrades/DiskLayoutUpgrade_SqlitePlaceholders.cs +++ b/GVFS/GVFS.Common/DiskLayoutUpgrades/DiskLayoutUpgrade_SqlitePlaceholders.cs @@ -30,7 +30,7 @@ public override bool TryUpgrade(ITracer tracer, string enlistmentRoot) } using (placeholderList) - using (GVFSDatabase database = new GVFSDatabase(fileSystem, enlistmentRoot, new SqliteDatabase())) + using (GVFSDatabase database = new GVFSDatabase(fileSystem, Path.Combine(enlistmentRoot, GVFSPlatform.Instance.Constants.DotGVFSRoot), new SqliteDatabase())) { PlaceholderTable placeholders = new PlaceholderTable(database); List oldPlaceholderEntries = placeholderList.GetAllEntries(); diff --git a/GVFS/GVFS.Common/Enlistment.cs b/GVFS/GVFS.Common/Enlistment.cs index 5dcfd9e54..a9208b0ed 100644 --- a/GVFS/GVFS.Common/Enlistment.cs +++ b/GVFS/GVFS.Common/Enlistment.cs @@ -21,7 +21,7 @@ protected Enlistment( throw new ArgumentException("Path to git.exe must be set"); } - this.EnlistmentRoot = enlistmentRoot; + this.PrimaryEnlistmentRoot = enlistmentRoot; this.WorkingDirectoryRoot = workingDirectoryRoot; this.WorkingDirectoryBackingRoot = workingDirectoryBackingRoot; this.DotGitRoot = Path.Combine(this.WorkingDirectoryBackingRoot, GVFSConstants.DotGit.Root); @@ -52,7 +52,7 @@ protected Enlistment( this.Authentication = authentication ?? new GitAuthentication(gitProcess, this.RepoUrl); } - public string EnlistmentRoot { get; } + public string PrimaryEnlistmentRoot { get; } // Path to the root of the working (i.e. "src") directory. // On platforms where the contents of the working directory are stored diff --git a/GVFS/GVFS.Common/FileSystem/HooksInstaller.cs b/GVFS/GVFS.Common/FileSystem/HooksInstaller.cs index f7dfae0fc..bdf6a03cb 100644 --- a/GVFS/GVFS.Common/FileSystem/HooksInstaller.cs +++ b/GVFS/GVFS.Common/FileSystem/HooksInstaller.cs @@ -229,7 +229,7 @@ private static bool TryUpdateHook( metadata.Add(nameof(installedHookPath), installedHookPath); metadata.Add("Exception", e.ToString()); context.Tracer.RelatedError(metadata, "Failed to compare " + hookName + " version"); - errorMessage = "Error comparing " + hookName + " versions. " + ConsoleHelper.GetGVFSLogMessage(context.Enlistment.EnlistmentRoot); + errorMessage = "Error comparing " + hookName + " versions. " + ConsoleHelper.GetGVFSLogMessage(context.Enlistment.WorkingDirectoryRoot); return false; } } @@ -248,7 +248,7 @@ private static bool TryUpdateHook( metadata.Add(nameof(installedHookPath), installedHookPath); metadata.Add("Exception", e.ToString()); context.Tracer.RelatedError(metadata, "Failed to copy " + hookName + " to enlistment"); - errorMessage = "Error copying " + hookName + " to enlistment. " + ConsoleHelper.GetGVFSLogMessage(context.Enlistment.EnlistmentRoot); + errorMessage = "Error copying " + hookName + " to enlistment. " + ConsoleHelper.GetGVFSLogMessage(context.Enlistment.WorkingDirectoryRoot); return false; } } diff --git a/GVFS/GVFS.Common/GVFSEnlistment.cs b/GVFS/GVFS.Common/GVFSEnlistment.cs index e0b18b28b..286b32037 100644 --- a/GVFS/GVFS.Common/GVFSEnlistment.cs +++ b/GVFS/GVFS.Common/GVFSEnlistment.cs @@ -30,11 +30,11 @@ public GVFSEnlistment(string enlistmentRoot, string repoUrl, string gitBinPath, flushFileBuffersForPacks: true, authentication: authentication) { - this.NamedPipeName = GVFSPlatform.Instance.GetNamedPipeName(this.EnlistmentRoot); - this.DotGVFSRoot = Path.Combine(this.EnlistmentRoot, GVFSPlatform.Instance.Constants.DotGVFSRoot); + this.NamedPipeName = GVFSPlatform.Instance.GetNamedPipeName(this.PrimaryEnlistmentRoot); + this.DotGVFSRoot = Path.Combine(this.PrimaryEnlistmentRoot, GVFSPlatform.Instance.Constants.DotGVFSRoot); this.GitStatusCacheFolder = Path.Combine(this.DotGVFSRoot, GVFSConstants.DotGVFS.GitStatusCache.Name); this.GitStatusCachePath = Path.Combine(this.DotGVFSRoot, GVFSConstants.DotGVFS.GitStatusCache.CachePath); - this.GVFSLogsRoot = Path.Combine(this.EnlistmentRoot, GVFSPlatform.Instance.Constants.DotGVFSRoot, GVFSConstants.DotGVFS.LogName); + this.GVFSLogsRoot = Path.Combine(this.DotGVFSRoot, GVFSConstants.DotGVFS.LogName); this.LocalObjectsRoot = Path.Combine(this.WorkingDirectoryBackingRoot, GVFSConstants.DotGit.Objects.Root); } diff --git a/GVFS/GVFS.Common/Git/GitRepo.cs b/GVFS/GVFS.Common/Git/GitRepo.cs index e5aefa579..d88ebbd89 100644 --- a/GVFS/GVFS.Common/Git/GitRepo.cs +++ b/GVFS/GVFS.Common/Git/GitRepo.cs @@ -16,6 +16,7 @@ public class GitRepo : IDisposable private PhysicalFileSystem fileSystem; private LibGit2RepoInvoker libgit2RepoInvoker; private Enlistment enlistment; + private string dotGVFSRoot; public GitRepo(ITracer tracer, Enlistment enlistment, PhysicalFileSystem fileSystem, Func repoFactory = null) { @@ -23,6 +24,11 @@ public GitRepo(ITracer tracer, Enlistment enlistment, PhysicalFileSystem fileSys this.enlistment = enlistment; this.fileSystem = fileSystem; + // Resolve the per-worktree .gvfs root if available; otherwise + // derive from EnlistmentRoot (primary enlistments). + this.dotGVFSRoot = (enlistment as GVFSEnlistment)?.DotGVFSRoot + ?? Path.Combine(enlistment.PrimaryEnlistmentRoot, GVFSPlatform.Instance.Constants.DotGVFSRoot); + this.GVFSLock = new GVFSLock(tracer); this.libgit2RepoInvoker = new LibGit2RepoInvoker( @@ -240,7 +246,7 @@ private LooseBlobState GetLooseBlobStateAtPath(string blobPath, Action - public static Dictionary GetRequiredSettings(Enlistment enlistment) + public static Dictionary GetRequiredSettings(GVFSEnlistment enlistment) { string expectedHooksPath = Path.Combine(enlistment.DotGitRoot, GVFSConstants.DotGit.Hooks.RootName); expectedHooksPath = Paths.ConvertPathToGitFormat(expectedHooksPath); @@ -31,8 +31,7 @@ public static Dictionary GetRequiredSettings(Enlistment enlistme if (!GVFSEnlistment.IsUnattended(tracer: null) && GVFSPlatform.Instance.IsGitStatusCacheSupported()) { gitStatusCachePath = Path.Combine( - enlistment.EnlistmentRoot, - GVFSPlatform.Instance.Constants.DotGVFSRoot, + enlistment.DotGVFSRoot, GVFSConstants.DotGVFS.GitStatusCache.CachePath); gitStatusCachePath = Paths.ConvertPathToGitFormat(gitStatusCachePath); diff --git a/GVFS/GVFS.Common/HealthCalculator/EnlistmentPathData.cs b/GVFS/GVFS.Common/HealthCalculator/EnlistmentPathData.cs index 8a6df6818..d56cfc8bd 100644 --- a/GVFS/GVFS.Common/HealthCalculator/EnlistmentPathData.cs +++ b/GVFS/GVFS.Common/HealthCalculator/EnlistmentPathData.cs @@ -54,7 +54,7 @@ public void LoadPlaceholdersFromDatabase(GVFSEnlistment enlistment) List filePlaceholders = new List(); List folderPlaceholders = new List(); - using (GVFSDatabase database = new GVFSDatabase(new PhysicalFileSystem(), enlistment.EnlistmentRoot, new SqliteDatabase())) + using (GVFSDatabase database = new GVFSDatabase(new PhysicalFileSystem(), enlistment.DotGVFSRoot, new SqliteDatabase())) { PlaceholderTable placeholderTable = new PlaceholderTable(database); placeholderTable.GetAllEntries(out filePlaceholders, out folderPlaceholders); diff --git a/GVFS/GVFS.Common/LocalCacheResolver.cs b/GVFS/GVFS.Common/LocalCacheResolver.cs index b0c31dc86..dbdb261e0 100644 --- a/GVFS/GVFS.Common/LocalCacheResolver.cs +++ b/GVFS/GVFS.Common/LocalCacheResolver.cs @@ -33,7 +33,7 @@ public static bool TryGetDefaultLocalCacheRoot(GVFSEnlistment enlistment, out st return true; } - return GVFSPlatform.Instance.TryGetDefaultLocalCacheRoot(enlistment.EnlistmentRoot, out localCacheRoot, out localCacheRootError); + return GVFSPlatform.Instance.TryGetDefaultLocalCacheRoot(enlistment.PrimaryEnlistmentRoot, out localCacheRoot, out localCacheRootError); } public bool TryGetLocalCacheKeyFromLocalConfigOrRemoteCacheServers( diff --git a/GVFS/GVFS.Common/Maintenance/GitMaintenanceStep.cs b/GVFS/GVFS.Common/Maintenance/GitMaintenanceStep.cs index ae14ab4ce..1df648fc4 100644 --- a/GVFS/GVFS.Common/Maintenance/GitMaintenanceStep.cs +++ b/GVFS/GVFS.Common/Maintenance/GitMaintenanceStep.cs @@ -36,7 +36,7 @@ public static bool EnlistmentRootReady(GVFSContext context) // a "Device is not ready" error. try { - return context.FileSystem.DirectoryExists(context.Enlistment.EnlistmentRoot) + return context.FileSystem.DirectoryExists(context.Enlistment.WorkingDirectoryRoot) && context.FileSystem.DirectoryExists(context.Enlistment.GitObjectsRoot); } catch (IOException) diff --git a/GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerFixture/WorktreeTests.cs b/GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerFixture/WorktreeTests.cs index 1f8501043..7de8bb680 100644 --- a/GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerFixture/WorktreeTests.cs +++ b/GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerFixture/WorktreeTests.cs @@ -268,6 +268,101 @@ public void WorktreeOutsideEnlistmentTree() } } + [TestCase] + public void WorktreeUsesPerWorktreePlaceholderDatabase() + { + // Two commits where test4.txt has different content + const string CommitA = "5d7a7d4db1734fb468a4094469ec58d26301b59d"; + const string CommitB = "fec239ea12de1eda6ae5329d4f345784d5b61ff9"; + string testFileRelativePath = Path.Combine( + "Test_EPF_UpdatePlaceholderTests", + "LockToPreventUpdateAndDelete", + "test4.txt"); + const string ContentAtCommitA = "TestFileLockToPreventUpdateAndDelete4 \r\n"; + const string ContentAtCommitB = "Commit2LockToPreventUpdateAndDelete4 \r\n"; + + string suffix = Guid.NewGuid().ToString("N").Substring(0, 8); + string tempDir = Path.Combine(Path.GetTempPath(), $"gvfs-db-test-{suffix}"); + string worktreePath = Path.Combine(tempDir, "wt"); + string branchName = $"db-test-branch-{suffix}"; + + try + { + Directory.CreateDirectory(tempDir); + + // 1. Checkout commitB in the primary and read the file to + // create a placeholder with version B content. + GitHelpers.InvokeGitAgainstGVFSRepo( + this.Enlistment.RepoRoot, $"checkout {CommitB}") + .ExitCode.ShouldEqual(0, "checkout commitB in primary failed"); + + string primaryFilePath = Path.Combine(this.Enlistment.RepoRoot, testFileRelativePath); + File.ReadAllText(primaryFilePath).ShouldEqual(ContentAtCommitB, + "Primary should have version B content"); + + // 2. Create a worktree at commitA and read the same file. + // Without the fix, the worktree mount writes the placeholder + // entry (SHA_A) to the primary's DB, overwriting SHA_B. + ProcessResult addResult = GitHelpers.InvokeGitAgainstGVFSRepo( + this.Enlistment.RepoRoot, + $"worktree add -b {branchName} \"{worktreePath}\" {CommitA}"); + addResult.ExitCode.ShouldEqual(0, + $"worktree add failed: {addResult.Errors}"); + + this.AssertWorktreeMounted(worktreePath, "db-test worktree"); + + string worktreeFilePath = Path.Combine(worktreePath, testFileRelativePath); + File.ReadAllText(worktreeFilePath).ShouldEqual(ContentAtCommitA, + "Worktree should have version A content"); + + // 3. Checkout commitA in the primary. UpdatePlaceholders reads + // the placeholder DB to find files that need updating. + // With a contaminated DB (SHA_A from worktree), the primary's + // placeholder (on-disk SHA_B) looks up-to-date (DB says SHA_A, + // index wants SHA_A — match) and the update is skipped. + // The file retains stale commitB content. + GitHelpers.InvokeGitAgainstGVFSRepo( + this.Enlistment.RepoRoot, $"checkout {CommitA}") + .ExitCode.ShouldEqual(0, "checkout commitA in primary failed"); + + string contentAfterCheckout = File.ReadAllText(primaryFilePath); + contentAfterCheckout.ShouldEqual(ContentAtCommitA, + $"After checkout to commitA, primary should have version A content.\n" + + $"Got version B content instead — the worktree mount contaminated\n" + + $"the primary's placeholder DB, causing UpdatePlaceholders to skip\n" + + $"the update because the DB SHA matched the index SHA."); + + // 4. Verify the per-worktree placeholder DB exists (isolation check) + GVFSEnlistment.WorktreeInfo wtInfo = GVFSEnlistment.TryGetWorktreeInfo(worktreePath); + Assert.IsNotNull(wtInfo, "Should be able to resolve worktree info"); + string worktreeDbPath = Path.Combine( + wtInfo.WorktreeGitDir, ".gvfs", "databases", "VFSForGit.sqlite"); + + bool dbExists = false; + for (int i = 0; i < 20; i++) + { + if (File.Exists(worktreeDbPath)) + { + dbExists = true; + break; + } + + System.Threading.Thread.Sleep(500); + } + + Assert.IsTrue(dbExists, + $"Per-worktree VFSForGit.sqlite should exist at {worktreeDbPath}"); + } + finally + { + this.ForceCleanupWorktree(worktreePath, branchName); + if (Directory.Exists(tempDir)) + { + try { Directory.Delete(tempDir, recursive: true); } catch { } + } + } + } + private void InitWorktreeArrays(int count, out string[] paths, out string[] branches) { paths = new string[count]; diff --git a/GVFS/GVFS.Mount/InProcessMount.cs b/GVFS/GVFS.Mount/InProcessMount.cs index 824940a0f..1272eb876 100644 --- a/GVFS/GVFS.Mount/InProcessMount.cs +++ b/GVFS/GVFS.Mount/InProcessMount.cs @@ -211,7 +211,7 @@ private void MountWithLockAcquired(EventLevel verbosity, Keywords keywords) this.FailMountAndExit("The .git folder is missing or has invalid contents"); } - if (!GVFSPlatform.Instance.FileSystem.IsFileSystemSupported(this.enlistment.EnlistmentRoot, out string fsError)) + if (!GVFSPlatform.Instance.FileSystem.IsFileSystemSupported(this.enlistment.WorkingDirectoryRoot, out string fsError)) { this.FailMountAndExit("FileSystem unsupported: " + fsError); } @@ -277,7 +277,7 @@ private void MountWithLockAcquired(EventLevel verbosity, Keywords keywords) try { - Console.Title = "GVFS " + ProcessHelper.GetCurrentProcessVersion() + " - " + this.enlistment.EnlistmentRoot; + Console.Title = "GVFS " + ProcessHelper.GetCurrentProcessVersion() + " - " + this.enlistment.WorkingDirectoryRoot; } catch (IOException) { @@ -365,7 +365,7 @@ private void InitializeWorktreeMetadata() // Use try/finally to guarantee Shutdown() even if an unexpected // exception occurs — the singleton must not be left pointing at // the primary's metadata directory. - string primaryDotGVFS = Path.Combine(this.enlistment.EnlistmentRoot, GVFSPlatform.Instance.Constants.DotGVFSRoot); + string primaryDotGVFS = Path.Combine(this.enlistment.PrimaryEnlistmentRoot, GVFSPlatform.Instance.Constants.DotGVFSRoot); string error; string gitObjectsRoot; string localCacheRoot; @@ -996,7 +996,7 @@ private void HandlePostFetchJobRequest(NamedPipeMessages.Message message, NamedP private void HandleGetStatusRequest(NamedPipeServer.Connection connection) { NamedPipeMessages.GetStatus.Response response = new NamedPipeMessages.GetStatus.Response(); - response.EnlistmentRoot = this.enlistment.EnlistmentRoot; + response.EnlistmentRoot = this.enlistment.WorkingDirectoryRoot; response.LocalCacheRoot = !string.IsNullOrWhiteSpace(this.enlistment.LocalCacheRoot) ? this.enlistment.LocalCacheRoot : this.enlistment.GitObjectsRoot; response.RepoUrl = this.enlistment.RepoUrl; response.CacheServer = this.cacheServer.ToString(); @@ -1082,7 +1082,7 @@ private void MountAndStartWorkingDirectoryCallbacks(CacheServerInfo cache, bool this.tracer.RelatedInfo("Git status cache is not enabled"); } - this.gvfsDatabase = this.CreateOrReportAndExit(() => new GVFSDatabase(this.context.FileSystem, this.context.Enlistment.EnlistmentRoot, new SqliteDatabase()), "Failed to create database connection"); + this.gvfsDatabase = this.CreateOrReportAndExit(() => new GVFSDatabase(this.context.FileSystem, this.context.Enlistment.DotGVFSRoot, new SqliteDatabase()), "Failed to create database connection"); this.fileSystemCallbacks = this.CreateOrReportAndExit( () => { @@ -1193,7 +1193,7 @@ private void ValidateFileSystemSupportsRequiredFeatures() { string warning; string error; - if (!GVFSPlatform.Instance.KernelDriver.IsSupported(this.enlistment.EnlistmentRoot, out warning, out error)) + if (!GVFSPlatform.Instance.KernelDriver.IsSupported(this.enlistment.WorkingDirectoryRoot, out warning, out error)) { this.FailMountAndExit("Error: {0}", error); } diff --git a/GVFS/GVFS.Mount/InProcessMountVerb.cs b/GVFS/GVFS.Mount/InProcessMountVerb.cs index 309d56fbd..16328f60d 100644 --- a/GVFS/GVFS.Mount/InProcessMountVerb.cs +++ b/GVFS/GVFS.Mount/InProcessMountVerb.cs @@ -115,7 +115,7 @@ public void Execute() CacheServerInfo cacheServer = CacheServerResolver.GetCacheServerFromConfig(enlistment); tracer.WriteStartEvent( - enlistment.EnlistmentRoot, + enlistment.WorkingDirectoryRoot, enlistment.RepoUrl, cacheServer.Url, new EventMetadata diff --git a/GVFS/GVFS.PerfProfiling/ProfilingEnvironment.cs b/GVFS/GVFS.PerfProfiling/ProfilingEnvironment.cs index 4798c85c3..65145acba 100644 --- a/GVFS/GVFS.PerfProfiling/ProfilingEnvironment.cs +++ b/GVFS/GVFS.PerfProfiling/ProfilingEnvironment.cs @@ -76,7 +76,7 @@ private FileSystemCallbacks CreateFileSystemCallbacks() cacheServer, new RetryConfig()); - this.gvfsDatabase = new GVFSDatabase(this.Context.FileSystem, this.Context.Enlistment.EnlistmentRoot, new SqliteDatabase()); + this.gvfsDatabase = new GVFSDatabase(this.Context.FileSystem, this.Context.Enlistment.DotGVFSRoot, new SqliteDatabase()); GVFSGitObjects gitObjects = new GVFSGitObjects(this.Context, objectRequestor); return new FileSystemCallbacks( this.Context, diff --git a/GVFS/GVFS.UnitTests/Common/Database/GVFSDatabaseTests.cs b/GVFS/GVFS.UnitTests/Common/Database/GVFSDatabaseTests.cs index 4ec88b34c..6617b2329 100644 --- a/GVFS/GVFS.UnitTests/Common/Database/GVFSDatabaseTests.cs +++ b/GVFS/GVFS.UnitTests/Common/Database/GVFSDatabaseTests.cs @@ -113,7 +113,7 @@ private void TestGVFSDatabase(Action testCode, bool throwException Mock mockConnectionFactory = new Mock(MockBehavior.Strict); bool firstConnection = true; - string databasePath = Path.Combine("mock:root", ".mockvfsforgit", "databases", "VFSForGit.sqlite"); + string databasePath = Path.Combine("mock:root", "databases", "VFSForGit.sqlite"); mockConnectionFactory.Setup(x => x.OpenNewConnection(databasePath)).Returns(() => { if (firstConnection) diff --git a/GVFS/GVFS.UnitTests/Common/WorktreeEnlistmentTests.cs b/GVFS/GVFS.UnitTests/Common/WorktreeEnlistmentTests.cs index 2541e56ac..dd072b1e5 100644 --- a/GVFS/GVFS.UnitTests/Common/WorktreeEnlistmentTests.cs +++ b/GVFS/GVFS.UnitTests/Common/WorktreeEnlistmentTests.cs @@ -145,7 +145,7 @@ public void DotGVFSRootIsInWorktreeGitDir() public void EnlistmentRootIsPrimaryRoot() { GVFSEnlistment enlistment = this.CreateWorktreeEnlistment(); - enlistment.EnlistmentRoot.ShouldEqual(this.primaryRoot); + enlistment.PrimaryEnlistmentRoot.ShouldEqual(this.primaryRoot); } [TestCase] diff --git a/GVFS/GVFS.UnitTests/Maintenance/GitMaintenanceQueueTests.cs b/GVFS/GVFS.UnitTests/Maintenance/GitMaintenanceQueueTests.cs index c284e3cfc..4897e9976 100644 --- a/GVFS/GVFS.UnitTests/Maintenance/GitMaintenanceQueueTests.cs +++ b/GVFS/GVFS.UnitTests/Maintenance/GitMaintenanceQueueTests.cs @@ -28,13 +28,13 @@ public void GitMaintenanceQueueEnlistmentRootReady() GitMaintenanceQueue queue = new GitMaintenanceQueue(this.context); queue.EnlistmentRootReady().ShouldBeTrue(); - this.fileSystem.Paths.Remove(this.enlistment.EnlistmentRoot); + this.fileSystem.Paths.Remove(this.enlistment.WorkingDirectoryRoot); queue.EnlistmentRootReady().ShouldBeFalse(); this.fileSystem.Paths.Remove(this.enlistment.GitObjectsRoot); queue.EnlistmentRootReady().ShouldBeFalse(); - this.fileSystem.Paths.Add(this.enlistment.EnlistmentRoot); + this.fileSystem.Paths.Add(this.enlistment.WorkingDirectoryRoot); queue.EnlistmentRootReady().ShouldBeFalse(); this.fileSystem.Paths.Add(this.enlistment.GitObjectsRoot); @@ -108,10 +108,10 @@ private void TestSetup() ITracer tracer = new MockTracer(); this.enlistment = new MockGVFSEnlistment(); - // We need to have the EnlistmentRoot and GitObjectsRoot available for jobs to run + // We need to have the WorkingDirectoryRoot and GitObjectsRoot available for jobs to run this.fileSystem = new ReadyFileSystem(new string[] { - this.enlistment.EnlistmentRoot, + this.enlistment.WorkingDirectoryRoot, this.enlistment.GitObjectsRoot }); diff --git a/GVFS/GVFS.UnitTests/Maintenance/GitMaintenanceStepTests.cs b/GVFS/GVFS.UnitTests/Maintenance/GitMaintenanceStepTests.cs index e1f6b134a..d37236fbc 100644 --- a/GVFS/GVFS.UnitTests/Maintenance/GitMaintenanceStepTests.cs +++ b/GVFS/GVFS.UnitTests/Maintenance/GitMaintenanceStepTests.cs @@ -80,7 +80,7 @@ private void TestSetup() { ITracer tracer = new MockTracer(); GVFSEnlistment enlistment = new MockGVFSEnlistment(); - PhysicalFileSystem fileSystem = new MockFileSystem(new MockDirectory(enlistment.EnlistmentRoot, null, null)); + PhysicalFileSystem fileSystem = new MockFileSystem(new MockDirectory(enlistment.PrimaryEnlistmentRoot, null, null)); this.context = new GVFSContext(tracer, fileSystem, null, enlistment); } diff --git a/GVFS/GVFS.UnitTests/Maintenance/LooseObjectStepTests.cs b/GVFS/GVFS.UnitTests/Maintenance/LooseObjectStepTests.cs index d1d8d4b94..47f699889 100644 --- a/GVFS/GVFS.UnitTests/Maintenance/LooseObjectStepTests.cs +++ b/GVFS/GVFS.UnitTests/Maintenance/LooseObjectStepTests.cs @@ -248,7 +248,7 @@ private void TestSetup(DateTime lastRun) // Add object directory to file System List directories = new List() { gitObjectsRoot }; - PhysicalFileSystem fileSystem = new MockFileSystem(new MockDirectory(enlistment.EnlistmentRoot, directories, null)); + PhysicalFileSystem fileSystem = new MockFileSystem(new MockDirectory(enlistment.PrimaryEnlistmentRoot, directories, null)); // Create and return Context this.tracer = new MockTracer(); diff --git a/GVFS/GVFS.UnitTests/Maintenance/PackfileMaintenanceStepTests.cs b/GVFS/GVFS.UnitTests/Maintenance/PackfileMaintenanceStepTests.cs index c9e0f8939..811b55e15 100644 --- a/GVFS/GVFS.UnitTests/Maintenance/PackfileMaintenanceStepTests.cs +++ b/GVFS/GVFS.UnitTests/Maintenance/PackfileMaintenanceStepTests.cs @@ -219,7 +219,7 @@ private void TestSetup(DateTime lastRun, bool failOnVerify = false) // Add object directory to file System List directories = new List() { gitObjectsRoot }; - PhysicalFileSystem fileSystem = new MockFileSystem(new MockDirectory(enlistment.EnlistmentRoot, directories, null)); + PhysicalFileSystem fileSystem = new MockFileSystem(new MockDirectory(enlistment.PrimaryEnlistmentRoot, directories, null)); MockGitRepo repository = new MockGitRepo(this.tracer, enlistment, fileSystem); diff --git a/GVFS/GVFS.UnitTests/Maintenance/PostFetchStepTests.cs b/GVFS/GVFS.UnitTests/Maintenance/PostFetchStepTests.cs index 8f1b35f6b..a35f11a59 100644 --- a/GVFS/GVFS.UnitTests/Maintenance/PostFetchStepTests.cs +++ b/GVFS/GVFS.UnitTests/Maintenance/PostFetchStepTests.cs @@ -91,7 +91,7 @@ private void TestSetup() // Create enlistment using git process GVFSEnlistment enlistment = new MockGVFSEnlistment(this.gitProcess); - PhysicalFileSystem fileSystem = new MockFileSystem(new MockDirectory(enlistment.EnlistmentRoot, null, null)); + PhysicalFileSystem fileSystem = new MockFileSystem(new MockDirectory(enlistment.PrimaryEnlistmentRoot, null, null)); // Create and return Context this.tracer = new MockTracer(); diff --git a/GVFS/GVFS/CommandLine/CacheVerb.cs b/GVFS/GVFS/CommandLine/CacheVerb.cs index b576d4275..8b6538348 100644 --- a/GVFS/GVFS/CommandLine/CacheVerb.cs +++ b/GVFS/GVFS/CommandLine/CacheVerb.cs @@ -216,7 +216,7 @@ private void GetLocalCachePaths(ITracer tracer, GVFSEnlistment enlistment, out s try { string error; - if (RepoMetadata.TryInitialize(tracer, Path.Combine(enlistment.EnlistmentRoot, GVFSPlatform.Instance.Constants.DotGVFSRoot), out error)) + if (RepoMetadata.TryInitialize(tracer, enlistment.DotGVFSRoot, out error)) { if (!RepoMetadata.Instance.TryGetLocalCacheRoot(out localCacheRoot, out error)) { diff --git a/GVFS/GVFS/CommandLine/CloneVerb.cs b/GVFS/GVFS/CommandLine/CloneVerb.cs index e64749d8c..977c5b082 100644 --- a/GVFS/GVFS/CommandLine/CloneVerb.cs +++ b/GVFS/GVFS/CommandLine/CloneVerb.cs @@ -162,9 +162,9 @@ public override void Execute() // Create the enlistment root explicitly with CreateDirectoryAccessibleByAuthUsers before calling // AddLogFileEventListener to ensure that elevated and non-elevated users have access to the root. string createDirectoryError; - if (!GVFSPlatform.Instance.FileSystem.TryCreateDirectoryAccessibleByAuthUsers(enlistment.EnlistmentRoot, out createDirectoryError)) + if (!GVFSPlatform.Instance.FileSystem.TryCreateDirectoryAccessibleByAuthUsers(enlistment.PrimaryEnlistmentRoot, out createDirectoryError)) { - this.ReportErrorAndExit($"Failed to create '{enlistment.EnlistmentRoot}': {createDirectoryError}"); + this.ReportErrorAndExit($"Failed to create '{enlistment.PrimaryEnlistmentRoot}': {createDirectoryError}"); } tracer.AddLogFileEventListener( @@ -172,7 +172,7 @@ public override void Execute() EventLevel.Informational, Keywords.Any); tracer.WriteStartEvent( - enlistment.EnlistmentRoot, + enlistment.PrimaryEnlistmentRoot, enlistment.RepoUrl, this.CacheServerUrl, new EventMetadata @@ -214,7 +214,7 @@ public override void Execute() this.Output.WriteLine(" Branch: " + (string.IsNullOrWhiteSpace(this.Branch) ? "Default" : this.Branch)); this.Output.WriteLine(" Cache Server: " + cacheServer); this.Output.WriteLine(" Local Cache: " + resolvedLocalCacheRoot); - this.Output.WriteLine(" Destination: " + enlistment.EnlistmentRoot); + this.Output.WriteLine(" Destination: " + enlistment.PrimaryEnlistmentRoot); RetryConfig retryConfig = this.GetRetryConfig(tracer, enlistment, TimeSpan.FromMinutes(RetryConfig.FetchAndCloneTimeoutMinutes)); @@ -291,7 +291,7 @@ public override void Execute() { UseShellExecute = true, WindowStyle = ProcessWindowStyle.Minimized, - WorkingDirectory = enlistment.EnlistmentRoot + WorkingDirectory = enlistment.PrimaryEnlistmentRoot }); this.Output.WriteLine("\r\nPrefetch of commit graph has been started as a background process. Git operations involving history may be slower until prefetch has completed.\r\n"); } @@ -457,7 +457,7 @@ private Result TryClone( return new Result(error); } - if (!GVFSPlatform.Instance.FileSystem.IsFileSystemSupported(enlistment.EnlistmentRoot, out string fsError)) + if (!GVFSPlatform.Instance.FileSystem.IsFileSystemSupported(enlistment.PrimaryEnlistmentRoot, out string fsError)) { string error = $"FileSystem unsupported: {fsError}"; tracer.RelatedError(error); @@ -754,7 +754,7 @@ private Result CreateClone( // TODO(#1364): Don't call this method on POSIX platforms (or have it no-op on them) private void CreateGitScript(GVFSEnlistment enlistment) { - FileInfo gitCmd = new FileInfo(Path.Combine(enlistment.EnlistmentRoot, "git.cmd")); + FileInfo gitCmd = new FileInfo(Path.Combine(enlistment.PrimaryEnlistmentRoot, "git.cmd")); using (FileStream fs = gitCmd.Create()) using (StreamWriter writer = new StreamWriter(fs)) { diff --git a/GVFS/GVFS/CommandLine/DehydrateVerb.cs b/GVFS/GVFS/CommandLine/DehydrateVerb.cs index 2d7b7f958..28ce30357 100644 --- a/GVFS/GVFS/CommandLine/DehydrateVerb.cs +++ b/GVFS/GVFS/CommandLine/DehydrateVerb.cs @@ -91,7 +91,7 @@ protected override void Execute(GVFSEnlistment enlistment) EventLevel.Informational, Keywords.Any); tracer.WriteStartEvent( - enlistment.EnlistmentRoot, + enlistment.PrimaryEnlistmentRoot, enlistment.RepoUrl, CacheServerResolver.GetUrlFromConfig(enlistment), new EventMetadata @@ -160,7 +160,7 @@ any of your uncommitted changes. in the backup folder, but it will be harder to find them because 'git status' will not work in the backup. -To actually execute the dehydrate, run 'gvfs dehydrate --confirm --full' from {enlistment.EnlistmentRoot}. +To actually execute the dehydrate, run 'gvfs dehydrate --confirm --full' from {enlistment.PrimaryEnlistmentRoot}. "); return; @@ -196,13 +196,13 @@ from a parent of the folders list. if (fullDehydrate && Environment.CurrentDirectory.StartsWith(enlistment.WorkingDirectoryBackingRoot)) { /* If running from /src, the dehydrate would fail because of the handle we are holding on it. */ - this.Output.WriteLine($"Dehydrate --full must be run from {enlistment.EnlistmentRoot}"); + this.Output.WriteLine($"Dehydrate --full must be run from {enlistment.PrimaryEnlistmentRoot}"); return; } bool cleanStatus = this.StatusChecked || this.CheckGitStatus(tracer, enlistment, fullDehydrate); - string backupRoot = Path.GetFullPath(Path.Combine(enlistment.EnlistmentRoot, "dehydrate_backup", DateTime.Now.ToString("yyyyMMdd_HHmmss"))); + string backupRoot = Path.GetFullPath(Path.Combine(enlistment.PrimaryEnlistmentRoot, "dehydrate_backup", DateTime.Now.ToString("yyyyMMdd_HHmmss"))); this.Output.WriteLine(); if (fullDehydrate) @@ -223,7 +223,7 @@ from a parent of the folders list. this.Unmount(tracer); string error; - if (!DiskLayoutUpgrade.TryCheckDiskLayoutVersion(tracer, enlistment.EnlistmentRoot, out error)) + if (!DiskLayoutUpgrade.TryCheckDiskLayoutVersion(tracer, enlistment.PrimaryEnlistmentRoot, out error)) { this.ReportErrorAndExit(tracer, error); } diff --git a/GVFS/GVFS/CommandLine/DiagnoseVerb.cs b/GVFS/GVFS/CommandLine/DiagnoseVerb.cs index d1a624db1..928b104df 100644 --- a/GVFS/GVFS/CommandLine/DiagnoseVerb.cs +++ b/GVFS/GVFS/CommandLine/DiagnoseVerb.cs @@ -77,7 +77,7 @@ protected override void Execute(GVFSEnlistment enlistment) this.WriteMessage(enlistment.GitBinPath); this.WriteMessage(string.Empty); - this.WriteMessage("Enlistment root: " + enlistment.EnlistmentRoot); + this.WriteMessage("Enlistment root: " + enlistment.PrimaryEnlistmentRoot); this.WriteMessage("Cache Server: " + CacheServerResolver.GetCacheServerFromConfig(enlistment)); string localCacheRoot; @@ -101,8 +101,8 @@ protected override void Execute(GVFSEnlistment enlistment) this.ShowStatusWhileRunning( () => { - // .gvfs - this.CopyAllFiles(enlistment.EnlistmentRoot, archiveFolderPath, GVFSPlatform.Instance.Constants.DotGVFSRoot, copySubFolders: false); + // .gvfs (top-level files like mount.lock) + this.CopyAllFiles(Path.GetDirectoryName(enlistment.DotGVFSRoot), archiveFolderPath, Path.GetFileName(enlistment.DotGVFSRoot), copySubFolders: false); // driver if (this.FlushKernelDriverLogs()) @@ -274,7 +274,7 @@ private void GetLocalCachePaths(GVFSEnlistment enlistment, out string localCache using (ITracer tracer = new JsonTracer(GVFSConstants.GVFSEtwProviderName, "DiagnoseVerb")) { string error; - if (RepoMetadata.TryInitialize(tracer, Path.Combine(enlistment.EnlistmentRoot, GVFSPlatform.Instance.Constants.DotGVFSRoot), out error)) + if (RepoMetadata.TryInitialize(tracer, enlistment.DotGVFSRoot, out error)) { RepoMetadata.Instance.TryGetLocalCacheRoot(out localCacheRoot, out error); RepoMetadata.Instance.TryGetGitObjectsRoot(out gitObjectsRoot, out error); diff --git a/GVFS/GVFS/CommandLine/GVFSVerb.cs b/GVFS/GVFS/CommandLine/GVFSVerb.cs index c44608daf..069ac1661 100644 --- a/GVFS/GVFS/CommandLine/GVFSVerb.cs +++ b/GVFS/GVFS/CommandLine/GVFSVerb.cs @@ -96,7 +96,7 @@ public string ServicePipeName protected abstract string VerbName { get; } - public static bool TrySetRequiredGitConfigSettings(Enlistment enlistment) + public static bool TrySetRequiredGitConfigSettings(GVFSEnlistment enlistment) { Dictionary requiredSettings = RequiredGitConfig.GetRequiredSettings(enlistment); @@ -164,7 +164,7 @@ protected ReturnCode Execute( where TVerb : GVFSVerb.ForExistingEnlistment, new() { TVerb verb = new TVerb(); - verb.EnlistmentRootPathParameter = enlistment.EnlistmentRoot; + verb.EnlistmentRootPathParameter = enlistment.WorkingDirectoryRoot; verb.ServiceName = this.ServiceName; verb.Unattended = this.Unattended; @@ -246,7 +246,7 @@ protected bool TryAuthenticateAndQueryGVFSConfig( out error, out _), "Authenticating", - enlistment.EnlistmentRoot); + enlistment.WorkingDirectoryRoot); if (!result && fallbackCacheServer != null && !string.IsNullOrWhiteSpace(fallbackCacheServer.Url)) { @@ -677,7 +677,7 @@ private void CheckFileSystemSupportsRequiredFeatures(ITracer tracer, Enlistment { string warning; string error; - if (!GVFSPlatform.Instance.KernelDriver.IsSupported(enlistment.EnlistmentRoot, out warning, out error)) + if (!GVFSPlatform.Instance.KernelDriver.IsSupported(enlistment.WorkingDirectoryRoot, out warning, out error)) { this.ReportErrorAndExit(tracer, $"Error: {error}"); } @@ -935,7 +935,7 @@ protected void InitializeLocalCacheAndObjectsPaths( CacheServerInfo cacheServer) { string error; - if (!RepoMetadata.TryInitialize(tracer, Path.Combine(enlistment.EnlistmentRoot, GVFSPlatform.Instance.Constants.DotGVFSRoot), out error)) + if (!RepoMetadata.TryInitialize(tracer, enlistment.DotGVFSRoot, out error)) { this.ReportErrorAndExit(tracer, "Failed to initialize repo metadata: " + error); } diff --git a/GVFS/GVFS/CommandLine/MountVerb.cs b/GVFS/GVFS/CommandLine/MountVerb.cs index edaf0b85c..37e5f1041 100644 --- a/GVFS/GVFS/CommandLine/MountVerb.cs +++ b/GVFS/GVFS/CommandLine/MountVerb.cs @@ -158,7 +158,7 @@ protected override void Execute(GVFSEnlistment enlistment) EventLevel.Verbose, Keywords.Any); tracer.WriteStartEvent( - enlistment.EnlistmentRoot, + enlistment.PrimaryEnlistmentRoot, enlistment.RepoUrl, cacheServerFromConfig.Url, new EventMetadata @@ -169,7 +169,7 @@ protected override void Execute(GVFSEnlistment enlistment) { nameof(this.EnlistmentRootPathParameter), this.EnlistmentRootPathParameter }, }); - if (!GVFSPlatform.Instance.KernelDriver.IsReady(tracer, enlistment.EnlistmentRoot, this.Output, out errorMessage)) + if (!GVFSPlatform.Instance.KernelDriver.IsReady(tracer, enlistment.WorkingDirectoryRoot, this.Output, out errorMessage)) { tracer.RelatedEvent( EventLevel.Informational, @@ -181,7 +181,7 @@ protected override void Execute(GVFSEnlistment enlistment) }); if (!this.ShowStatusWhileRunning( - () => { return this.TryEnableAndAttachPrjFltThroughService(enlistment.EnlistmentRoot, out errorMessage); }, + () => { return this.TryEnableAndAttachPrjFltThroughService(enlistment.WorkingDirectoryRoot, out errorMessage); }, $"Attaching ProjFS to volume")) { this.ReportErrorAndExit(tracer, ReturnCode.FilterError, errorMessage); @@ -255,7 +255,7 @@ private bool TryMount(ITracer tracer, GVFSEnlistment enlistment, string mountExe // For worktrees, pass the worktree path so GVFS.Mount.exe creates the right enlistment string mountPath = enlistment.IsWorktree ? enlistment.WorkingDirectoryRoot - : enlistment.EnlistmentRoot; + : enlistment.PrimaryEnlistmentRoot; tracer.RelatedInfo($"{nameof(this.TryMount)}: Launching background process('{mountExecutableLocation}') for {mountPath}"); @@ -277,7 +277,7 @@ private bool TryMount(ITracer tracer, GVFSEnlistment enlistment, string mountExe tracer.RelatedInfo($"{nameof(this.TryMount)}: Waiting for repo to be mounted"); - return GVFSEnlistment.WaitUntilMounted(tracer, enlistment.NamedPipeName, enlistment.EnlistmentRoot, this.Unattended, out errorMessage); + return GVFSEnlistment.WaitUntilMounted(tracer, enlistment.NamedPipeName, enlistment.WorkingDirectoryRoot, this.Unattended, out errorMessage); } private bool RegisterMount(GVFSEnlistment enlistment, out string errorMessage) @@ -290,7 +290,7 @@ private bool RegisterMount(GVFSEnlistment enlistment, out string errorMessage) // listed and unregistered independently of the primary enlistment. request.EnlistmentRoot = enlistment.IsWorktree ? enlistment.WorkingDirectoryRoot - : enlistment.EnlistmentRoot; + : enlistment.PrimaryEnlistmentRoot; request.OwnerSID = GVFSPlatform.Instance.GetCurrentUser(); diff --git a/GVFS/GVFS/CommandLine/PrefetchVerb.cs b/GVFS/GVFS/CommandLine/PrefetchVerb.cs index 1d3d555b4..17483c34c 100644 --- a/GVFS/GVFS/CommandLine/PrefetchVerb.cs +++ b/GVFS/GVFS/CommandLine/PrefetchVerb.cs @@ -138,7 +138,7 @@ protected override void Execute(GVFSEnlistment enlistment) EventLevel.Informational, Keywords.Any); tracer.WriteStartEvent( - enlistment.EnlistmentRoot, + enlistment.PrimaryEnlistmentRoot, enlistment.RepoUrl, cacheServerFromConfig.Url); @@ -216,8 +216,8 @@ protected override void Execute(GVFSEnlistment enlistment) catch (AggregateException aggregateException) { this.Output.WriteLine( - "Cannot prefetch {0}. " + ConsoleHelper.GetGVFSLogMessage(enlistment.EnlistmentRoot), - enlistment.EnlistmentRoot); + "Cannot prefetch {0}. " + ConsoleHelper.GetGVFSLogMessage(enlistment.WorkingDirectoryRoot), + enlistment.WorkingDirectoryRoot); foreach (Exception innerException in aggregateException.Flatten().InnerExceptions) { tracer.RelatedError( @@ -234,8 +234,8 @@ protected override void Execute(GVFSEnlistment enlistment) catch (Exception e) { this.Output.WriteLine( - "Cannot prefetch {0}. " + ConsoleHelper.GetGVFSLogMessage(enlistment.EnlistmentRoot), - enlistment.EnlistmentRoot); + "Cannot prefetch {0}. " + ConsoleHelper.GetGVFSLogMessage(enlistment.WorkingDirectoryRoot), + enlistment.WorkingDirectoryRoot); tracer.RelatedError( new EventMetadata { diff --git a/GVFS/GVFS/CommandLine/RepairVerb.cs b/GVFS/GVFS/CommandLine/RepairVerb.cs index 731af334f..dc0034adc 100644 --- a/GVFS/GVFS/CommandLine/RepairVerb.cs +++ b/GVFS/GVFS/CommandLine/RepairVerb.cs @@ -92,7 +92,7 @@ To actually execute any necessary repair(s), run 'gvfs repair --confirm' } string error; - if (!DiskLayoutUpgrade.TryCheckDiskLayoutVersion(tracer: null, enlistmentRoot: enlistment.EnlistmentRoot, error: out error)) + if (!DiskLayoutUpgrade.TryCheckDiskLayoutVersion(tracer: null, enlistmentRoot: enlistment.PrimaryEnlistmentRoot, error: out error)) { this.ReportErrorAndExit(error); } @@ -129,7 +129,7 @@ To actually execute any necessary repair(s), run 'gvfs repair --confirm' EventLevel.Verbose, Keywords.Any); tracer.WriteStartEvent( - enlistment.EnlistmentRoot, + enlistment.PrimaryEnlistmentRoot, enlistment.RepoUrl, "N/A", new EventMetadata @@ -214,7 +214,7 @@ To actually execute any necessary repair(s), run 'gvfs repair --confirm' this.WriteMessage(tracer, "Repair succeeded, but requires some manual steps before remounting."); break; case RepairJob.FixResult.Failure: - this.WriteMessage(tracer, "Repair failed. " + ConsoleHelper.GetGVFSLogMessage(enlistment.EnlistmentRoot)); + this.WriteMessage(tracer, "Repair failed. " + ConsoleHelper.GetGVFSLogMessage(enlistment.PrimaryEnlistmentRoot)); break; } diff --git a/GVFS/GVFS/CommandLine/SparseVerb.cs b/GVFS/GVFS/CommandLine/SparseVerb.cs index bf5150c27..1ea6e5aed 100644 --- a/GVFS/GVFS/CommandLine/SparseVerb.cs +++ b/GVFS/GVFS/CommandLine/SparseVerb.cs @@ -159,7 +159,7 @@ protected override void Execute(GVFSEnlistment enlistment) string.IsNullOrEmpty(this.Set) && string.IsNullOrEmpty(this.File))) { - this.ListSparseFolders(enlistment.EnlistmentRoot); + this.ListSparseFolders(enlistment.DotGVFSRoot); return; } @@ -183,7 +183,7 @@ protected override void Execute(GVFSEnlistment enlistment) HashSet directories; bool needToChangeProjection = false; - using (GVFSDatabase database = new GVFSDatabase(new PhysicalFileSystem(), enlistment.EnlistmentRoot, new SqliteDatabase())) + using (GVFSDatabase database = new GVFSDatabase(new PhysicalFileSystem(), enlistment.DotGVFSRoot, new SqliteDatabase())) { SparseTable sparseTable = new SparseTable(database); directories = sparseTable.GetAll(); @@ -555,9 +555,9 @@ private void CheckOptions() } } - private void ListSparseFolders(string enlistmentRoot) + private void ListSparseFolders(string dotGVFSRoot) { - using (GVFSDatabase database = new GVFSDatabase(new PhysicalFileSystem(), enlistmentRoot, new SqliteDatabase())) + using (GVFSDatabase database = new GVFSDatabase(new PhysicalFileSystem(), dotGVFSRoot, new SqliteDatabase())) { SparseTable sparseTable = new SparseTable(database); HashSet directories = sparseTable.GetAll(); diff --git a/GVFS/GVFS/RepairJobs/GitConfigRepairJob.cs b/GVFS/GVFS/RepairJobs/GitConfigRepairJob.cs index c1f8c5ab9..2903bcf72 100644 --- a/GVFS/GVFS/RepairJobs/GitConfigRepairJob.cs +++ b/GVFS/GVFS/RepairJobs/GitConfigRepairJob.cs @@ -50,7 +50,7 @@ public override IssueType HasIssue(List messages) try { GVFSEnlistment enlistment = GVFSEnlistment.CreateFromDirectory( - this.Enlistment.EnlistmentRoot, + this.Enlistment.PrimaryEnlistmentRoot, this.Enlistment.GitBinPath, authentication: null);