From 056470e0a8a0f99498a22b78411c68ba61594af0 Mon Sep 17 00:00:00 2001 From: Derrick Stolee Date: Wed, 3 Oct 2018 07:59:04 -0400 Subject: [PATCH] GitProcess: allow GIT_TRACE to point to full path --- GVFS/GVFS.Common/Git/GitProcess.cs | 23 +++++--- .../Tests/GitCommands/GitCommandsTests.cs | 55 +++++++++++++++++-- .../Tests/GitCommands/GitRepoTests.cs | 13 ++++- GVFS/GVFS.FunctionalTests/Tools/GitHelpers.cs | 14 ++++- 4 files changed, 88 insertions(+), 17 deletions(-) diff --git a/GVFS/GVFS.Common/Git/GitProcess.cs b/GVFS/GVFS.Common/Git/GitProcess.cs index 5c3bba3cde..ad7db839a4 100644 --- a/GVFS/GVFS.Common/Git/GitProcess.cs +++ b/GVFS/GVFS.Common/Git/GitProcess.cs @@ -1,6 +1,5 @@ using GVFS.Common.FileSystem; using GVFS.Common.Tracing; -using Microsoft.Win32; using System; using System.Collections.Generic; using System.ComponentModel; @@ -149,7 +148,7 @@ public bool IsValidRepo() Result result = this.InvokeGitAgainstDotGitFolder("rev-parse --show-toplevel"); return !result.HasErrors; } - + public Result RevParse(string gitRef) { return this.InvokeGitAgainstDotGitFolder("rev-parse " + gitRef); @@ -405,11 +404,21 @@ public Process GetGitProcess(string command, string workingDirectory, string dot // Removing trace variables that might change git output and break parsing // List of environment variables: https://git-scm.com/book/gr/v2/Git-Internals-Environment-Variables - foreach (string key in processInfo.EnvironmentVariables.Keys.Cast() - .Where(x => x.StartsWith("GIT_TRACE", StringComparison.OrdinalIgnoreCase)) - .ToList()) + foreach (string key in processInfo.EnvironmentVariables.Keys.Cast()) { - processInfo.EnvironmentVariables.Remove(key); + // If GIT_TRACE is set to a fully-rooted path, then Git sends the trace + // output to that path instead of stdout (GIT_TRACE=1) or stderr (GIT_TRACE=2). + if (key.StartsWith("GIT_TRACE", StringComparison.OrdinalIgnoreCase)) + { + string value = processInfo.EnvironmentVariables[key]; + + if (!key.Equals("GIT_TRACE") + || value.IndexOfAny(Path.GetInvalidPathChars()) >= 0 + || !Path.IsPathRooted(processInfo.EnvironmentVariables[key])) + { + processInfo.EnvironmentVariables.Remove(key); + } + } } processInfo.EnvironmentVariables["GIT_TERMINAL_PROMPT"] = "0"; @@ -601,7 +610,7 @@ private Result InvokeGitAgainstDotGitFolder( parseStdOutLine: parseStdOutLine, timeoutMs: -1); } - + public class Result { public const int SuccessCode = 0; diff --git a/GVFS/GVFS.FunctionalTests/Tests/GitCommands/GitCommandsTests.cs b/GVFS/GVFS.FunctionalTests/Tests/GitCommands/GitCommandsTests.cs index 31ac5cb08c..bd7fa77bf7 100644 --- a/GVFS/GVFS.FunctionalTests/Tests/GitCommands/GitCommandsTests.cs +++ b/GVFS/GVFS.FunctionalTests/Tests/GitCommands/GitCommandsTests.cs @@ -3,6 +3,7 @@ using GVFS.Tests.Should; using NUnit.Framework; using System; +using System.Collections.Generic; using System.IO; using System.Runtime.CompilerServices; @@ -23,7 +24,7 @@ public class GitCommandsTests : GitRepoTests private static readonly string RenameFilePathTo = Path.Combine("GVFS", "GVFS.Common", "Physical", "FileSystem", "FileProperties2.cs"); private static readonly string RenameFolderPathFrom = Path.Combine("GVFS", "GVFS.Common", "PrefetchPacks"); private static readonly string RenameFolderPathTo = Path.Combine("GVFS", "GVFS.Common", "PrefetchPacksRenamed"); - + public GitCommandsTests() : base(enlistmentPerTest: false) { } @@ -45,6 +46,48 @@ public void StatusTest() this.ValidateGitCommand("status"); } + [TestCase] + public void StatusWithGitTraceTest() + { + Dictionary environmentVariables = new Dictionary(); + + string tracePath = Path.Combine(this.Enlistment.EnlistmentRoot, "trace-log.txt"); + environmentVariables["GIT_TRACE"] = tracePath; + this.ValidateGitCommand(environmentVariables, "status"); + + this.FileSystem.FileExists(tracePath).ShouldBeTrue(); + + string lineToFind = "trace: built-in: git status"; + int count = 0; + + foreach (string line in this.FileSystem.ReadAllText(tracePath).Split('\n')) + { + if (line.IndexOf(lineToFind) >= 0) + { + count++; + } + } + + // The GIT_TRACE output is appended to the file, so we should have + // one copy for each run: normal and virtualized. + count.ShouldEqual(2); + } + + [TestCase] + public void StatusWithGitTraceInvalidCharactersTest() + { + Dictionary environmentVariables = new Dictionary(); + + if (Path.GetInvalidPathChars().Length == 0) + { + return; + } + + string tracePath = Path.Combine(this.Enlistment.EnlistmentRoot, $"trace-log{Path.GetInvalidPathChars()[0]}.txt"); + environmentVariables["GIT_TRACE"] = tracePath; + this.ValidateGitCommand(environmentVariables, "status"); + } + [TestCase] public void StatusShortTest() { @@ -263,27 +306,27 @@ public void RenameFilesWithNameAheadOfDot() { this.FolderShouldExistAndHaveFile("GitCommandsTests", "RenameFileTests", "1", "#test"); this.MoveFile( - Path.Combine("GitCommandsTests", "RenameFileTests", "1", "#test"), + Path.Combine("GitCommandsTests", "RenameFileTests", "1", "#test"), Path.Combine("GitCommandsTests", "RenameFileTests", "1", "#testRenamed")); this.FolderShouldExistAndHaveFile("GitCommandsTests", "RenameFileTests", "2", "$test"); this.MoveFile( - Path.Combine("GitCommandsTests", "RenameFileTests", "2", "$test"), + Path.Combine("GitCommandsTests", "RenameFileTests", "2", "$test"), Path.Combine("GitCommandsTests", "RenameFileTests", "2", "$testRenamed")); this.FolderShouldExistAndHaveFile("GitCommandsTests", "RenameFileTests", "3", ")"); this.MoveFile( - Path.Combine("GitCommandsTests", "RenameFileTests", "3", ")"), + Path.Combine("GitCommandsTests", "RenameFileTests", "3", ")"), Path.Combine("GitCommandsTests", "RenameFileTests", "3", ")Renamed")); this.FolderShouldExistAndHaveFile("GitCommandsTests", "RenameFileTests", "4", "+.test"); this.MoveFile( - Path.Combine("GitCommandsTests", "RenameFileTests", "4", "+.test"), + Path.Combine("GitCommandsTests", "RenameFileTests", "4", "+.test"), Path.Combine("GitCommandsTests", "RenameFileTests", "4", "+.testRenamed")); this.FolderShouldExistAndHaveFile("GitCommandsTests", "RenameFileTests", "5", "-.test"); this.MoveFile( - Path.Combine("GitCommandsTests", "RenameFileTests", "5", "-.test"), + Path.Combine("GitCommandsTests", "RenameFileTests", "5", "-.test"), Path.Combine("GitCommandsTests", "RenameFileTests", "5", "-.testRenamed")); this.ValidateGitCommand("status"); diff --git a/GVFS/GVFS.FunctionalTests/Tests/GitCommands/GitRepoTests.cs b/GVFS/GVFS.FunctionalTests/Tests/GitCommands/GitRepoTests.cs index 9200be7c55..aa3960e50d 100644 --- a/GVFS/GVFS.FunctionalTests/Tests/GitCommands/GitRepoTests.cs +++ b/GVFS/GVFS.FunctionalTests/Tests/GitCommands/GitRepoTests.cs @@ -3,8 +3,7 @@ using GVFS.FunctionalTests.Tools; using GVFS.Tests.Should; using NUnit.Framework; -using NUnit.Framework.Interfaces; -using System; +using System.Collections.Generic; using System.IO; using System.Linq; @@ -182,6 +181,16 @@ protected void ValidateGitCommand(string command, params object[] args) args); } + protected void ValidateGitCommand(Dictionary environmentVariables, string command, params object[] args) + { + GitHelpers.ValidateGitCommand( + this.Enlistment, + this.ControlGitRepo, + environmentVariables, + command, + args); + } + protected void CreateEmptyFile() { string filePath = Path.GetRandomFileName() + "emptyFile.txt"; diff --git a/GVFS/GVFS.FunctionalTests/Tools/GitHelpers.cs b/GVFS/GVFS.FunctionalTests/Tools/GitHelpers.cs index 333499ba0e..bbf7686ed5 100644 --- a/GVFS/GVFS.FunctionalTests/Tools/GitHelpers.cs +++ b/GVFS/GVFS.FunctionalTests/Tools/GitHelpers.cs @@ -78,13 +78,23 @@ public static void ValidateGitCommand( ControlGitRepo controlGitRepo, string command, params object[] args) + { + ValidateGitCommand(enlistment, controlGitRepo, null, command, args); + } + + public static void ValidateGitCommand( + GVFSFunctionalTestEnlistment enlistment, + ControlGitRepo controlGitRepo, + Dictionary environmentVariables, + string command, + params object[] args) { command = string.Format(command, args); string controlRepoRoot = controlGitRepo.RootPath; string gvfsRepoRoot = enlistment.RepoRoot; - ProcessResult expectedResult = GitProcess.InvokeProcess(controlRepoRoot, command); - ProcessResult actualResult = GitHelpers.InvokeGitAgainstGVFSRepo(gvfsRepoRoot, command); + ProcessResult expectedResult = GitProcess.InvokeProcess(controlRepoRoot, command, environmentVariables); + ProcessResult actualResult = GitHelpers.InvokeGitAgainstGVFSRepo(gvfsRepoRoot, command, environmentVariables); ErrorsShouldMatch(command, expectedResult, actualResult); actualResult.Output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)