From eb321dc9ca917344e9a5caf0c425757c3c777a04 Mon Sep 17 00:00:00 2001 From: Derrick Stolee Date: Mon, 9 Mar 2020 10:57:49 -0400 Subject: [PATCH 1/5] Update Git to v2.26.0 Signed-off-by: Derrick Stolee --- Directory.Build.props | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index f60a7cdbc3..c7d7e45c9e 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -36,8 +36,16 @@ 0.2.173.2 - 2.20200227.1 + + + 2.20200323.8 v2.25.0.vfs.1.1 + https://github.com/facebook/watchman/suites/307436006/artifacts/304557 https://github.com/microsoft/Git-Credential-Manager-Core/releases/download/v2.0.79-beta/gcmcore-osx-2.0.79.64449.pkg From cbf6f828e21f82507825545c375febed9b394d98 Mon Sep 17 00:00:00 2001 From: Derrick Stolee Date: Thu, 12 Mar 2020 11:49:18 -0400 Subject: [PATCH 2/5] GitHelpers: ignore whitespace lines Signed-off-by: Derrick Stolee --- .../Tests/GitCommands/GitCommandsTests.cs | 2 +- .../Tests/GitCommands/GitRepoTests.cs | 2 +- Scalar.FunctionalTests/Tools/GitHelpers.cs | 19 +++++++++++++------ .../Should/EnumerableShouldExtensions.cs | 6 +++--- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/Scalar.FunctionalTests/Tests/GitCommands/GitCommandsTests.cs b/Scalar.FunctionalTests/Tests/GitCommands/GitCommandsTests.cs index 9eb5abcc67..8c5805a54a 100644 --- a/Scalar.FunctionalTests/Tests/GitCommands/GitCommandsTests.cs +++ b/Scalar.FunctionalTests/Tests/GitCommands/GitCommandsTests.cs @@ -980,7 +980,7 @@ public void OpenFileThenCheckout() string command = "checkout -b tests/functional/OpenFileThenCheckout_2"; ProcessResult expectedResult = GitProcess.InvokeProcess(controlRepoRoot, command); ProcessResult actualResult = GitHelpers.InvokeGitAgainstScalarRepo(scalarRepoRoot, command); - GitHelpers.ErrorsShouldMatch(command, expectedResult, actualResult); + GitHelpers.LinesShouldMatch(command, expectedResult.Errors, actualResult.Errors); actualResult.Errors.ShouldContain("Switched to a new branch"); this.ValidateGitCommand("status"); diff --git a/Scalar.FunctionalTests/Tests/GitCommands/GitRepoTests.cs b/Scalar.FunctionalTests/Tests/GitCommands/GitRepoTests.cs index aff27c486f..aa49b8f789 100644 --- a/Scalar.FunctionalTests/Tests/GitCommands/GitRepoTests.cs +++ b/Scalar.FunctionalTests/Tests/GitCommands/GitRepoTests.cs @@ -261,7 +261,7 @@ protected void RunGitCommand(string command, bool ignoreErrors = false, bool che if (!ignoreErrors) { - GitHelpers.ErrorsShouldMatch(command, expectedResult, actualResult); + GitHelpers.LinesShouldMatch(command, expectedResult.Errors, actualResult.Errors); } if (command != "status" && checkStatus) diff --git a/Scalar.FunctionalTests/Tools/GitHelpers.cs b/Scalar.FunctionalTests/Tools/GitHelpers.cs index eed0084108..90adc1aac7 100644 --- a/Scalar.FunctionalTests/Tools/GitHelpers.cs +++ b/Scalar.FunctionalTests/Tools/GitHelpers.cs @@ -87,9 +87,8 @@ public static void ValidateGitCommand( ProcessResult expectedResult = GitProcess.InvokeProcess(controlRepoRoot, command, environmentVariables); ProcessResult actualResult = GitHelpers.InvokeGitAgainstScalarRepo(scalarRepoRoot, command, environmentVariables); - ErrorsShouldMatch(command, expectedResult, actualResult); - actualResult.Output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries) - .ShouldMatchInOrder(expectedResult.Output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries), LinesAreEqual, command + " Output Lines"); + LinesShouldMatch(command + " Errors Lines", actualResult.Errors, expectedResult.Errors); + LinesShouldMatch(command + " Output Lines", actualResult.Output, expectedResult.Output); if (command != "status") { @@ -97,10 +96,18 @@ public static void ValidateGitCommand( } } - public static void ErrorsShouldMatch(string command, ProcessResult expectedResult, ProcessResult actualResult) + public static void LinesShouldMatch(string message, string expected, string actual) { - actualResult.Errors.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries) - .ShouldMatchInOrder(expectedResult.Errors.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries), LinesAreEqual, command + " Errors Lines"); + IEnumerable actualLines = NonEmptyLines(actual); + IEnumerable expectedLines = NonEmptyLines(expected); + actualLines.ShouldMatchInOrder(expectedLines, LinesAreEqual, message); + } + + private static IEnumerable NonEmptyLines(string data) + { + return data + .Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries) + .Where(s => !string.IsNullOrWhiteSpace(s)); } private static bool LinesAreEqual(string actualLine, string expectedLine) diff --git a/Scalar.TestInfrastructure/Should/EnumerableShouldExtensions.cs b/Scalar.TestInfrastructure/Should/EnumerableShouldExtensions.cs index 9e32a9c5a8..561bbb7536 100644 --- a/Scalar.TestInfrastructure/Should/EnumerableShouldExtensions.cs +++ b/Scalar.TestInfrastructure/Should/EnumerableShouldExtensions.cs @@ -136,12 +136,12 @@ private static IEnumerable ShouldMatch(this IEnumerable group, IEnumera foreach (T groupExtraItem in groupExtraItems) { - errorMessage.AppendLine(string.Format("Extra: {0}", groupExtraItem)); + errorMessage.AppendLine(string.Format("Extra: '{0}'", groupExtraItem)); } foreach (T groupMissingItem in groupMissingItems) { - errorMessage.AppendLine(string.Format("Missing: {0}", groupMissingItem)); + errorMessage.AppendLine(string.Format("Missing: '{0}'", groupMissingItem)); } if (shouldMatchInOrder) @@ -150,7 +150,7 @@ private static IEnumerable ShouldMatch(this IEnumerable group, IEnumera { if (!equals(groupList[i], expectedValuesList[i])) { - errorMessage.AppendLine($"Items ordered differently, found: {groupList[i]} expected: {expectedValuesList[i]}"); + errorMessage.AppendLine($"Items ordered differently, found: '{groupList[i]}' expected: '{expectedValuesList[i]}'"); } } } From 574c5abf999a78e02db9c910c6687a8491c700e1 Mon Sep 17 00:00:00 2001 From: Derrick Stolee Date: Sun, 15 Mar 2020 15:31:13 -0400 Subject: [PATCH 3/5] Use no-op for core.editor It appears that a behavior change in Git is causing the editor to be opened after a rebase conflict. Signed-off-by: Derrick Stolee --- Scalar.FunctionalTests/Tests/GitCommands/GitRepoTests.cs | 1 + Scalar.FunctionalTests/Tools/ControlGitRepo.cs | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Scalar.FunctionalTests/Tests/GitCommands/GitRepoTests.cs b/Scalar.FunctionalTests/Tests/GitCommands/GitRepoTests.cs index aa49b8f789..d49514edbe 100644 --- a/Scalar.FunctionalTests/Tests/GitCommands/GitRepoTests.cs +++ b/Scalar.FunctionalTests/Tests/GitCommands/GitRepoTests.cs @@ -212,6 +212,7 @@ protected void CreateEnlistment(string commitish = null) ScalarTestConfig.PathToScalar, commitish: commitish, fullClone: this.validateWorkingTree != Settings.ValidateWorkingTreeMode.SparseMode); + GitProcess.Invoke(this.Enlistment.RepoRoot, "config core.editor true"); GitProcess.Invoke(this.Enlistment.RepoRoot, "config advice.statusUoption false"); this.ControlGitRepo = ControlGitRepo.Create(commitish); this.ControlGitRepo.Initialize(); diff --git a/Scalar.FunctionalTests/Tools/ControlGitRepo.cs b/Scalar.FunctionalTests/Tools/ControlGitRepo.cs index 892a6e2c65..fce194e208 100644 --- a/Scalar.FunctionalTests/Tools/ControlGitRepo.cs +++ b/Scalar.FunctionalTests/Tools/ControlGitRepo.cs @@ -1,7 +1,5 @@ -using Scalar.FunctionalTests.FileSystemRunners; using System; using System.IO; -using System.Runtime.InteropServices; namespace Scalar.FunctionalTests.Tools { @@ -52,6 +50,7 @@ public void Initialize() Directory.CreateDirectory(this.RootPath); GitProcess.Invoke(this.RootPath, "init"); GitProcess.Invoke(this.RootPath, "config core.autocrlf false"); + GitProcess.Invoke(this.RootPath, "config core.editor true"); GitProcess.Invoke(this.RootPath, "config merge.stat false"); GitProcess.Invoke(this.RootPath, "config merge.renames false"); GitProcess.Invoke(this.RootPath, "config advice.statusUoption false"); From 47deb82c3a4f1b0c7ef6d6350e0009c1df9e837d Mon Sep 17 00:00:00 2001 From: Derrick Stolee Date: Mon, 16 Mar 2020 10:44:14 -0400 Subject: [PATCH 4/5] Fix GIT_COMMITTER_DATE to keep tests consistent Signed-off-by: Derrick Stolee --- Scalar.FunctionalTests/Tools/GitHelpers.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Scalar.FunctionalTests/Tools/GitHelpers.cs b/Scalar.FunctionalTests/Tools/GitHelpers.cs index 90adc1aac7..326c74ecaa 100644 --- a/Scalar.FunctionalTests/Tools/GitHelpers.cs +++ b/Scalar.FunctionalTests/Tools/GitHelpers.cs @@ -83,6 +83,7 @@ public static void ValidateGitCommand( Dictionary environmentVariables = new Dictionary(); environmentVariables["GIT_QUIET"] = "true"; + environmentVariables["GIT_COMMITTER_DATE"] = "Thu Feb 16 10:07:35 2017 -0700"; ProcessResult expectedResult = GitProcess.InvokeProcess(controlRepoRoot, command, environmentVariables); ProcessResult actualResult = GitHelpers.InvokeGitAgainstScalarRepo(scalarRepoRoot, command, environmentVariables); From 3ff302371a908b3ce9de226b39a0a3d10d5480b1 Mon Sep 17 00:00:00 2001 From: Derrick Stolee Date: Tue, 17 Mar 2020 08:20:38 -0400 Subject: [PATCH 5/5] ConfigStep: install fsmonitor hook from installed templates Before, we would copy samples from the .git/hooks/ directory, but that relies on the timing of when a user initialized their repository. Further, the .git directory is less safe than the place where Git is installed. This new mechanism allows us to upgrade the fsmonitor hook automatically with new Git updates. Also update core.fsmonitorHookVersion to 2 explicitly. Signed-off-by: Derrick Stolee --- Scalar.Common/Maintenance/ConfigStep.cs | 18 +++++++++++++++--- Scalar.Common/Platforms/Mac/MacPlatform.cs | 5 +++++ .../Platforms/Windows/WindowsPlatform.cs | 14 ++++++++++++++ Scalar.Common/ScalarConstants.cs | 5 +++++ Scalar.Common/ScalarPlatform.cs | 2 ++ Scalar.UnitTests/Mock/Common/MockPlatform.cs | 5 +++++ 6 files changed, 46 insertions(+), 3 deletions(-) diff --git a/Scalar.Common/Maintenance/ConfigStep.cs b/Scalar.Common/Maintenance/ConfigStep.cs index e03d6c78da..9cfdf7629b 100644 --- a/Scalar.Common/Maintenance/ConfigStep.cs +++ b/Scalar.Common/Maintenance/ConfigStep.cs @@ -235,9 +235,18 @@ private void ConfigureWatchmanIntegration() try { + string hooksDir = ScalarPlatform.Instance.GetTemplateHooksDirectory(); + + if (string.IsNullOrEmpty(hooksDir)) + { + this.Context.Tracer.RelatedError("Could not find hook templates directory. Skipping watchman integration."); + return; + } + + // Install query-watchman hook from latest Git path string fsMonitorWatchmanSampleHookPath = Path.Combine( - this.Context.Enlistment.WorkingDirectoryRoot, - ScalarConstants.DotGit.Hooks.FsMonitorWatchmanSamplePath); + hooksDir, + ScalarConstants.DotGit.Hooks.FsMonitorWatchmanSampleName); string queryWatchmanPath = Path.Combine( this.Context.Enlistment.WorkingDirectoryRoot, @@ -250,7 +259,10 @@ private void ConfigureWatchmanIntegration() string dotGitRoot = this.Context.Enlistment.DotGitRoot.Replace(Path.DirectorySeparatorChar, ScalarConstants.GitPathSeparator); this.RunGitCommand( - process => process.SetInLocalConfig("core.fsmonitor", dotGitRoot + "/hooks/query-watchman"), + process => process.SetInLocalConfig("core.fsmonitor", dotGitRoot + "/hooks/query-watchman"), + "config"); + this.RunGitCommand( + process => process.SetInLocalConfig("core.fsmonitorHookVersion", "2"), "config"); this.Context.Tracer.RelatedInfo("Watchman configured!"); diff --git a/Scalar.Common/Platforms/Mac/MacPlatform.cs b/Scalar.Common/Platforms/Mac/MacPlatform.cs index 4eeec81f4e..dbc80b30ab 100644 --- a/Scalar.Common/Platforms/Mac/MacPlatform.cs +++ b/Scalar.Common/Platforms/Mac/MacPlatform.cs @@ -146,6 +146,11 @@ public override void IsServiceInstalledAndRunning(string name, out bool installe running = installed && scalarService.IsRunning; } + public override string GetTemplateHooksDirectory() + { + return Path.Combine("usr", "local", ScalarConstants.InstalledGit.HookTemplateDir); + } + public class MacPlatformConstants : POSIXPlatformConstants { public override string InstallerExtension diff --git a/Scalar.Common/Platforms/Windows/WindowsPlatform.cs b/Scalar.Common/Platforms/Windows/WindowsPlatform.cs index 1133831614..85b6ed0e7c 100644 --- a/Scalar.Common/Platforms/Windows/WindowsPlatform.cs +++ b/Scalar.Common/Platforms/Windows/WindowsPlatform.cs @@ -337,6 +337,20 @@ public override ProductUpgraderPlatformStrategy CreateProductUpgraderPlatformInt return new WindowsProductUpgraderPlatformStrategy(fileSystem, tracer); } + public override string GetTemplateHooksDirectory() + { + string gitBinPath = GitInstallation.GetInstalledGitBinPath(); + + string tail = Path.Combine("cmd", "git.exe"); + if (gitBinPath.EndsWith(tail)) + { + string gitBasePath = gitBinPath.Substring(0, gitBinPath.Length - tail.Length); + return Path.Combine(gitBasePath, "mingw64", ScalarConstants.InstalledGit.HookTemplateDir); + } + + return null; + } + public override bool TryGetDefaultLocalCacheRoot(string enlistmentRoot, out string localCacheRoot, out string localCacheRootError) { string pathRoot; diff --git a/Scalar.Common/ScalarConstants.cs b/Scalar.Common/ScalarConstants.cs index f6b336ec64..47f53782d3 100644 --- a/Scalar.Common/ScalarConstants.cs +++ b/Scalar.Common/ScalarConstants.cs @@ -187,6 +187,11 @@ public static class Hidden } } + public static class InstalledGit + { + public static readonly string HookTemplateDir = Path.Combine("share", "git-core", "templates", "hooks"); + } + public static class VerbParameters { public const string InternalUseOnly = "internal_use_only"; diff --git a/Scalar.Common/ScalarPlatform.cs b/Scalar.Common/ScalarPlatform.cs index 92fba6431a..b7252e22af 100644 --- a/Scalar.Common/ScalarPlatform.cs +++ b/Scalar.Common/ScalarPlatform.cs @@ -114,6 +114,8 @@ public abstract ProductUpgraderPlatformStrategy CreateProductUpgraderPlatformInt PhysicalFileSystem fileSystem, ITracer tracer); + public abstract string GetTemplateHooksDirectory(); + public bool TryGetNormalizedPathRoot(string path, out string pathRoot, out string errorMessage) { pathRoot = null; diff --git a/Scalar.UnitTests/Mock/Common/MockPlatform.cs b/Scalar.UnitTests/Mock/Common/MockPlatform.cs index cd290770e1..2bb23390eb 100644 --- a/Scalar.UnitTests/Mock/Common/MockPlatform.cs +++ b/Scalar.UnitTests/Mock/Common/MockPlatform.cs @@ -173,6 +173,11 @@ public override bool TryKillProcessTree(int processId, out int exitCode, out str return true; } + public override string GetTemplateHooksDirectory() + { + throw new NotSupportedException(); + } + public class MockPlatformConstants : ScalarPlatformConstants { public override string ExecutableExtension