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