From 93f981180b215f38544ace147c536b0a95a422ad Mon Sep 17 00:00:00 2001 From: Chris Darroch Date: Sun, 7 Jul 2019 22:02:05 -0700 Subject: [PATCH 1/3] use WorkingDirectoryBackingRoot in RepairJobs Repair jobs run while the GVFS enlistment is not mounted, which on Linux requires us to use the backing root in order to access the .git contents. --- GVFS/GVFS/RepairJobs/GitConfigRepairJob.cs | 2 +- GVFS/GVFS/RepairJobs/GitHeadRepairJob.cs | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/GVFS/GVFS/RepairJobs/GitConfigRepairJob.cs b/GVFS/GVFS/RepairJobs/GitConfigRepairJob.cs index 6c488ca942..ca594ad8ac 100644 --- a/GVFS/GVFS/RepairJobs/GitConfigRepairJob.cs +++ b/GVFS/GVFS/RepairJobs/GitConfigRepairJob.cs @@ -74,7 +74,7 @@ public override IssueType HasIssue(List messages) public override FixResult TryFixIssues(List messages) { - string configPath = Path.Combine(this.Enlistment.WorkingDirectoryRoot, GVFSConstants.DotGit.Config); + string configPath = Path.Combine(this.Enlistment.WorkingDirectoryBackingRoot, GVFSConstants.DotGit.Config); string configBackupPath; if (!this.TryRenameToBackupFile(configPath, out configBackupPath, messages)) { diff --git a/GVFS/GVFS/RepairJobs/GitHeadRepairJob.cs b/GVFS/GVFS/RepairJobs/GitHeadRepairJob.cs index 414213dfdc..8d29cecf59 100644 --- a/GVFS/GVFS/RepairJobs/GitHeadRepairJob.cs +++ b/GVFS/GVFS/RepairJobs/GitHeadRepairJob.cs @@ -52,7 +52,7 @@ public override FixResult TryFixIssues(List messages) try { - string refPath = Path.Combine(this.Enlistment.WorkingDirectoryRoot, GVFSConstants.DotGit.Head); + string refPath = Path.Combine(this.Enlistment.WorkingDirectoryBackingRoot, GVFSConstants.DotGit.Head); File.WriteAllText(refPath, refLog.TargetSha); } catch (IOException ex) @@ -82,7 +82,7 @@ public override FixResult TryFixIssues(List messages) /// A full symbolic ref name. eg. HEAD, refs/remotes/origin/HEAD, refs/heads/master private static bool TryReadLastRefLogEntry(Enlistment enlistment, string fullSymbolicRef, out RefLogEntry refLog, out string error) { - string refLogPath = Path.Combine(enlistment.WorkingDirectoryRoot, GVFSConstants.DotGit.Logs.Root, fullSymbolicRef); + string refLogPath = Path.Combine(enlistment.WorkingDirectoryBackingRoot, GVFSConstants.DotGit.Logs.Root, fullSymbolicRef); if (!File.Exists(refLogPath)) { refLog = null; @@ -112,7 +112,7 @@ private static bool TryReadLastRefLogEntry(Enlistment enlistment, string fullSym private static bool TryParseHead(Enlistment enlistment, List messages) { - string refPath = Path.Combine(enlistment.WorkingDirectoryRoot, GVFSConstants.DotGit.Head); + string refPath = Path.Combine(enlistment.WorkingDirectoryBackingRoot, GVFSConstants.DotGit.Head); if (!File.Exists(refPath)) { messages.Add("Could not find ref file for '" + GVFSConstants.DotGit.Head + "'"); @@ -145,35 +145,35 @@ private bool CanBeRepaired(List messages) { Func createErrorMessage = operation => string.Format("Can't repair HEAD while a {0} operation is in progress", operation); - string rebasePath = Path.Combine(this.Enlistment.WorkingDirectoryRoot, GVFSConstants.DotGit.RebaseApply); + string rebasePath = Path.Combine(this.Enlistment.WorkingDirectoryBackingRoot, GVFSConstants.DotGit.RebaseApply); if (Directory.Exists(rebasePath)) { messages.Add(createErrorMessage("rebase")); return false; } - string mergeHeadPath = Path.Combine(this.Enlistment.WorkingDirectoryRoot, GVFSConstants.DotGit.MergeHead); + string mergeHeadPath = Path.Combine(this.Enlistment.WorkingDirectoryBackingRoot, GVFSConstants.DotGit.MergeHead); if (File.Exists(mergeHeadPath)) { messages.Add(createErrorMessage("merge")); return false; } - string bisectStartPath = Path.Combine(this.Enlistment.WorkingDirectoryRoot, GVFSConstants.DotGit.BisectStart); + string bisectStartPath = Path.Combine(this.Enlistment.WorkingDirectoryBackingRoot, GVFSConstants.DotGit.BisectStart); if (File.Exists(bisectStartPath)) { messages.Add(createErrorMessage("bisect")); return false; } - string cherrypickHeadPath = Path.Combine(this.Enlistment.WorkingDirectoryRoot, GVFSConstants.DotGit.CherryPickHead); + string cherrypickHeadPath = Path.Combine(this.Enlistment.WorkingDirectoryBackingRoot, GVFSConstants.DotGit.CherryPickHead); if (File.Exists(cherrypickHeadPath)) { messages.Add(createErrorMessage("cherry-pick")); return false; } - string revertHeadPath = Path.Combine(this.Enlistment.WorkingDirectoryRoot, GVFSConstants.DotGit.RevertHead); + string revertHeadPath = Path.Combine(this.Enlistment.WorkingDirectoryBackingRoot, GVFSConstants.DotGit.RevertHead); if (File.Exists(revertHeadPath)) { messages.Add(createErrorMessage("revert")); From 6cd45c3fbd3520502fc0fddb1531a0d577f4618f Mon Sep 17 00:00:00 2001 From: Chris Darroch Date: Wed, 12 Jun 2019 16:21:19 -0700 Subject: [PATCH 2/3] use RepoBackingRoot as needed in functional tests --- .../LooseObjectStepTests.cs | 2 +- .../Tests/EnlistmentPerTestCase/RepairTests.cs | 16 ++++++++-------- .../Tests/GitCommands/CheckoutTests.cs | 2 +- .../Tools/GVFSFunctionalTestEnlistment.cs | 15 +++++++++++++++ 4 files changed, 25 insertions(+), 10 deletions(-) diff --git a/GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerTestCase/LooseObjectStepTests.cs b/GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerTestCase/LooseObjectStepTests.cs index 5a14879b50..69254634f1 100644 --- a/GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerTestCase/LooseObjectStepTests.cs +++ b/GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerTestCase/LooseObjectStepTests.cs @@ -188,7 +188,7 @@ private void ExpandOneTempPack(bool copyPackBackToPackDirectory) using (FileStream packFileStream = File.OpenRead(packFile)) { string output = GitProcess.InvokeProcess( - this.Enlistment.RepoRoot, + this.Enlistment.RepoBackingRoot, "unpack-objects", new Dictionary() { { "GIT_OBJECT_DIRECTORY", this.GitObjectRoot } }, inputStream: packFileStream).Output; diff --git a/GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerTestCase/RepairTests.cs b/GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerTestCase/RepairTests.cs index e089d20e98..18caf16310 100644 --- a/GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerTestCase/RepairTests.cs +++ b/GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerTestCase/RepairTests.cs @@ -25,7 +25,7 @@ public void FixesCorruptHeadSha() { this.Enlistment.UnmountGVFS(); - string headFilePath = Path.Combine(this.Enlistment.RepoRoot, ".git", "HEAD"); + string headFilePath = Path.Combine(this.Enlistment.RepoBackingRoot, ".git", "HEAD"); File.WriteAllText(headFilePath, "0000"); this.Enlistment.TryMountGVFS().ShouldEqual(false, "GVFS shouldn't mount when HEAD is corrupt"); @@ -39,7 +39,7 @@ public void FixesCorruptHeadSymRef() { this.Enlistment.UnmountGVFS(); - string headFilePath = Path.Combine(this.Enlistment.RepoRoot, ".git", "HEAD"); + string headFilePath = Path.Combine(this.Enlistment.RepoBackingRoot, ".git", "HEAD"); File.WriteAllText(headFilePath, "ref: refs"); this.Enlistment.TryMountGVFS().ShouldEqual(false, "GVFS shouldn't mount when HEAD is corrupt"); @@ -53,7 +53,7 @@ public void FixesMissingGitIndex() { this.Enlistment.UnmountGVFS(); - string gitIndexPath = Path.Combine(this.Enlistment.RepoRoot, ".git", "index"); + string gitIndexPath = Path.Combine(this.Enlistment.RepoBackingRoot, ".git", "index"); File.Delete(gitIndexPath); this.Enlistment.TryMountGVFS().ShouldEqual(false, "GVFS shouldn't mount when git index is missing"); @@ -67,7 +67,7 @@ public void FixesGitIndexCorruptedWithBadData() { this.Enlistment.UnmountGVFS(); - string gitIndexPath = Path.Combine(this.Enlistment.RepoRoot, ".git", "index"); + string gitIndexPath = Path.Combine(this.Enlistment.RepoBackingRoot, ".git", "index"); this.CreateCorruptIndexAndRename( gitIndexPath, (current, temp) => @@ -90,7 +90,7 @@ public void FixesGitIndexContainingAllNulls() { this.Enlistment.UnmountGVFS(); - string gitIndexPath = Path.Combine(this.Enlistment.RepoRoot, ".git", "index"); + string gitIndexPath = Path.Combine(this.Enlistment.RepoBackingRoot, ".git", "index"); // Set the contents of the index file to gitIndexPath NULL this.CreateCorruptIndexAndRename( @@ -114,7 +114,7 @@ public void FixesGitIndexCorruptedByTruncation() { this.Enlistment.UnmountGVFS(); - string gitIndexPath = Path.Combine(this.Enlistment.RepoRoot, ".git", "index"); + string gitIndexPath = Path.Combine(this.Enlistment.RepoBackingRoot, ".git", "index"); // Truncate the contents of the index this.CreateCorruptIndexAndRename( @@ -141,7 +141,7 @@ public void FixesCorruptGitConfig() { this.Enlistment.UnmountGVFS(); - string gitIndexPath = Path.Combine(this.Enlistment.RepoRoot, ".git", "config"); + string gitIndexPath = Path.Combine(this.Enlistment.RepoBackingRoot, ".git", "config"); File.WriteAllText(gitIndexPath, "[cor"); this.Enlistment.TryMountGVFS().ShouldEqual(false, "GVFS shouldn't mount when git config is missing"); @@ -149,7 +149,7 @@ public void FixesCorruptGitConfig() this.RepairWithoutConfirmShouldNotFix(); this.Enlistment.Repair(confirm: true); - ProcessResult result = GitProcess.InvokeProcess(this.Enlistment.RepoRoot, "remote add origin " + this.Enlistment.RepoUrl); + ProcessResult result = GitProcess.InvokeProcess(this.Enlistment.RepoBackingRoot, "remote add origin " + this.Enlistment.RepoUrl); result.ExitCode.ShouldEqual(0, result.Errors); this.Enlistment.MountGVFS(); } diff --git a/GVFS/GVFS.FunctionalTests/Tests/GitCommands/CheckoutTests.cs b/GVFS/GVFS.FunctionalTests/Tests/GitCommands/CheckoutTests.cs index f8ae3833a5..4dcdce436c 100644 --- a/GVFS/GVFS.FunctionalTests/Tests/GitCommands/CheckoutTests.cs +++ b/GVFS/GVFS.FunctionalTests/Tests/GitCommands/CheckoutTests.cs @@ -501,7 +501,7 @@ public void CheckoutBranchWithOpenHandleBlockingProjectionDeleteAndRepoMetdataUp this.ControlGitRepo.Fetch(GitRepoTests.ConflictTargetBranch); this.Enlistment.UnmountGVFS(); - string gitIndexPath = Path.Combine(this.Enlistment.RepoRoot, ".git", "index"); + string gitIndexPath = Path.Combine(this.Enlistment.RepoBackingRoot, ".git", "index"); CopyIndexAndRename(gitIndexPath); this.Enlistment.MountGVFS(); diff --git a/GVFS/GVFS.FunctionalTests/Tools/GVFSFunctionalTestEnlistment.cs b/GVFS/GVFS.FunctionalTests/Tools/GVFSFunctionalTestEnlistment.cs index 36bf19d125..18b288f9f2 100644 --- a/GVFS/GVFS.FunctionalTests/Tools/GVFSFunctionalTestEnlistment.cs +++ b/GVFS/GVFS.FunctionalTests/Tools/GVFSFunctionalTestEnlistment.cs @@ -59,6 +59,21 @@ public string RepoUrl public string LocalCacheRoot { get; } + public string RepoBackingRoot + { + get + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + return Path.Combine(this.EnlistmentRoot, ".vfsforgit/lower"); + } + else + { + return this.RepoRoot; + } + } + } + public string RepoRoot { get { return Path.Combine(this.EnlistmentRoot, "src"); } From f1c7422e0bb69c1519cd7f634ddcd4773cc9a765 Mon Sep 17 00:00:00 2001 From: Ashe Connor Date: Wed, 26 Jun 2019 16:13:08 +1000 Subject: [PATCH 3/3] MountTests fixes --- .../Tests/EnlistmentPerFixture/MountTests.cs | 29 ++++++++++++------- .../Tools/GVFSFunctionalTestEnlistment.cs | 12 +++++++- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerFixture/MountTests.cs b/GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerFixture/MountTests.cs index 00567cf765..6237d67c63 100644 --- a/GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerFixture/MountTests.cs +++ b/GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerFixture/MountTests.cs @@ -57,7 +57,7 @@ public void MountCopiesMissingReadObjectHook() { this.Enlistment.UnmountGVFS(); - string readObjectPath = this.Enlistment.GetVirtualPathTo(".git", "hooks", "read-object" + Settings.Default.BinaryFileNameExtension); + string readObjectPath = this.Enlistment.GetDotGitPath("hooks", "read-object" + Settings.Default.BinaryFileNameExtension); readObjectPath.ShouldBeAFile(this.fileSystem); this.fileSystem.DeleteFile(readObjectPath); readObjectPath.ShouldNotExistOnDisk(this.fileSystem); @@ -76,7 +76,7 @@ public void MountSetsCoreHooksPath() .ShouldBeTrue(); this.Enlistment.MountGVFS(); - string expectedHooksPath = Path.Combine(this.Enlistment.RepoRoot, ".git", "hooks"); + string expectedHooksPath = this.Enlistment.GetDotGitPath("hooks"); expectedHooksPath = GitHelpers.ConvertPathToGitFormat(expectedHooksPath); GitProcess.Invoke( @@ -198,7 +198,7 @@ public void MountRegeneratesAlternatesFileWhenMissingGitObjectsRoot() string objectsRoot = GVFSHelpers.GetPersistedGitObjectsRoot(this.Enlistment.DotGVFSRoot).ShouldNotBeNull(); - string alternatesFilePath = Path.Combine(this.Enlistment.RepoRoot, ".git", "objects", "info", "alternates"); + string alternatesFilePath = this.Enlistment.GetDotGitPath("objects", "info", "alternates"); alternatesFilePath.ShouldBeAFile(this.fileSystem).WithContents(objectsRoot); this.fileSystem.WriteAllText(alternatesFilePath, "Z:\\invalidPath"); @@ -214,7 +214,7 @@ public void MountRegeneratesAlternatesFileWhenMissingFromDisk() string objectsRoot = GVFSHelpers.GetPersistedGitObjectsRoot(this.Enlistment.DotGVFSRoot).ShouldNotBeNull(); - string alternatesFilePath = Path.Combine(this.Enlistment.RepoRoot, ".git", "objects", "info", "alternates"); + string alternatesFilePath = this.Enlistment.GetDotGitPath("objects", "info", "alternates"); alternatesFilePath.ShouldBeAFile(this.fileSystem).WithContents(objectsRoot); this.fileSystem.DeleteFile(alternatesFilePath); @@ -345,17 +345,26 @@ private void MountShouldFail(string expectedErrorMessage, string mountWorkingDir private class MountSubfolders { public const string MountFolders = "Folders"; - private static object[] mountFolders = - { - new object[] { string.Empty }, - new object[] { "GVFS" }, - }; public static object[] Folders { get { - return mountFolders; + // On Linux, an unmounted repository is completely empty, so we must + // only try to mount from the root of the virtual path. + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + return new object[] { new object[] { string.Empty } }; + } + else + { + return new object[] + { + new object[] { string.Empty }, + new object[] { "GVFS" }, + }; + } } } diff --git a/GVFS/GVFS.FunctionalTests/Tools/GVFSFunctionalTestEnlistment.cs b/GVFS/GVFS.FunctionalTests/Tools/GVFSFunctionalTestEnlistment.cs index 18b288f9f2..ec03370ce4 100644 --- a/GVFS/GVFS.FunctionalTests/Tools/GVFSFunctionalTestEnlistment.cs +++ b/GVFS/GVFS.FunctionalTests/Tools/GVFSFunctionalTestEnlistment.cs @@ -294,10 +294,20 @@ public string GetVirtualPathTo(params string[] pathParts) return Path.Combine(this.RepoRoot, Path.Combine(pathParts)); } + public string GetBackingPathTo(params string[] pathParts) + { + return Path.Combine(this.RepoBackingRoot, Path.Combine(pathParts)); + } + + public string GetDotGitPath(params string[] pathParts) + { + return this.GetBackingPathTo(TestConstants.DotGit.Root, Path.Combine(pathParts)); + } + public string GetObjectPathTo(string objectHash) { return Path.Combine( - this.RepoRoot, + this.RepoBackingRoot, TestConstants.DotGit.Objects.Root, objectHash.Substring(0, 2), objectHash.Substring(2));