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 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.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..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(); @@ -261,7 +262,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/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"); diff --git a/Scalar.FunctionalTests/Tools/GitHelpers.cs b/Scalar.FunctionalTests/Tools/GitHelpers.cs index eed0084108..326c74ecaa 100644 --- a/Scalar.FunctionalTests/Tools/GitHelpers.cs +++ b/Scalar.FunctionalTests/Tools/GitHelpers.cs @@ -83,13 +83,13 @@ 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); - 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 +97,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]}'"); } } } 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