From e6eb0547da8e279fdaada69d34b96cc65a321043 Mon Sep 17 00:00:00 2001 From: Ashe Connor Date: Wed, 12 Jun 2019 11:59:34 +1000 Subject: [PATCH] use platform-specific property for case matching This only applies to on-disk operations like locating the ".git" directory or ".idx" files, etc. -- the repository contents remain case-insensitive. Co-authored-by: Chris Darroch --- GVFS/FastFetch/Index.cs | 4 ++-- GVFS/FastFetch/WorkingTree.cs | 2 +- GVFS/GVFS.Common/FileSystem/HooksInstaller.cs | 2 +- GVFS/GVFS.Common/GVFSPlatform.cs | 22 +++++++++++++++++++ GVFS/GVFS.Common/GitHubUpgrader.cs | 8 +++---- .../Maintenance/GitMaintenanceStep.cs | 4 ++-- .../Maintenance/GitProcessChecker.cs | 2 +- .../Maintenance/PackfileMaintenanceStep.cs | 2 +- GVFS/GVFS.Common/Maintenance/PrefetchStep.cs | 2 +- GVFS/GVFS.Common/RepoMetadata.cs | 2 +- GVFS/GVFS.Platform.Mac/MacPlatform.cs | 2 ++ GVFS/GVFS.Platform.POSIX/POSIXPlatform.cs | 2 +- GVFS/GVFS.Platform.Windows/ProjFSFilter.cs | 2 +- .../WindowsFileSystem.cs | 2 +- GVFS/GVFS.Platform.Windows/WindowsPlatform.cs | 4 +++- GVFS/GVFS.Service/RepoRegistry.cs | 4 ++-- .../Category/CategoryConstants.cs | 1 + .../Common/FileBasedDictionaryTests.cs | 8 +++---- .../Mock/Common/MockPlatform.cs | 5 ++++- .../Mock/FileSystem/MockFileSystem.cs | 2 +- .../GVFS.UnitTests/Mock/MockGitHubUpgrader.cs | 12 +++++----- .../Prefetch/DiffHelperTests.cs | 4 +++- GVFS/GVFS.UnitTests/Program.cs | 8 ++++++- .../FileSystemCallbacksTests.cs | 11 ++++++++-- .../Background/FileSystemTaskQueue.cs | 2 +- .../FileSystem/FileSystemVirtualizer.cs | 18 +++++++-------- .../FileSystemCallbacks.cs | 8 +++---- GVFS/GVFS/CommandLine/CloneVerb.cs | 4 ++-- GVFS/GVFS/CommandLine/DehydrateVerb.cs | 2 +- GVFS/GVFS/CommandLine/DiagnoseVerb.cs | 2 +- GVFS/GVFS/CommandLine/GVFSVerb.cs | 2 +- GVFS/GVFS/CommandLine/HealthVerb.cs | 2 +- .../MacFileSystemVirtualizer.cs | 2 ++ .../WindowsFileSystemVirtualizer.cs | 2 ++ .../MirrorProvider/FileSystemVirtualizer.cs | 4 +++- 35 files changed, 108 insertions(+), 57 deletions(-) diff --git a/GVFS/FastFetch/Index.cs b/GVFS/FastFetch/Index.cs index cb897aa7e6..b02c1362f2 100644 --- a/GVFS/FastFetch/Index.cs +++ b/GVFS/FastFetch/Index.cs @@ -377,7 +377,7 @@ private void ParseIndex(Stream indexStream) this.tracer.RelatedEvent(EventLevel.Informational, "IndexData", new EventMetadata() { { "Index", this.updatedIndexPath }, { "Version", this.IndexVersion }, { "entryCount", this.entryCount } }, Keywords.Telemetry); - this.indexEntryOffsets = new Dictionary((int)this.entryCount, StringComparer.OrdinalIgnoreCase); + this.indexEntryOffsets = new Dictionary((int)this.entryCount, GVFSPlatform.Instance.Constants.PathComparer); int previousPathLength = 0; byte[] pathBuffer = new byte[MaxPathBufferSize]; @@ -736,4 +736,4 @@ private class IndexEntryTime } } } -} \ No newline at end of file +} diff --git a/GVFS/FastFetch/WorkingTree.cs b/GVFS/FastFetch/WorkingTree.cs index 3026623618..47528618cd 100644 --- a/GVFS/FastFetch/WorkingTree.cs +++ b/GVFS/FastFetch/WorkingTree.cs @@ -26,7 +26,7 @@ public static void ForAllDirectories(DirectoryInfo dir, Action - (!subdir.Name.Equals(GVFSConstants.DotGit.Root, StringComparison.OrdinalIgnoreCase) && + (!subdir.Name.Equals(GVFSConstants.DotGit.Root, GVFSPlatform.Instance.Constants.PathComparison) && !subdir.Attributes.HasFlag(FileAttributes.ReparsePoint))), subdir => { ForAllDirectories(subdir, asyncParallelCallback); }); } diff --git a/GVFS/GVFS.Common/FileSystem/HooksInstaller.cs b/GVFS/GVFS.Common/FileSystem/HooksInstaller.cs index 3930594374..c9d691397e 100644 --- a/GVFS/GVFS.Common/FileSystem/HooksInstaller.cs +++ b/GVFS/GVFS.Common/FileSystem/HooksInstaller.cs @@ -29,7 +29,7 @@ public static string MergeHooksData(string[] defaultHooksLines, string filename, { IEnumerable valuableHooksLines = defaultHooksLines.Where(line => !string.IsNullOrEmpty(line.Trim())); - if (valuableHooksLines.Contains(GVFSPlatform.Instance.Constants.GVFSHooksExecutableName, StringComparer.OrdinalIgnoreCase)) + if (valuableHooksLines.Contains(GVFSPlatform.Instance.Constants.GVFSHooksExecutableName, GVFSPlatform.Instance.Constants.PathComparer)) { throw new HooksConfigurationException( $"{GVFSPlatform.Instance.Constants.GVFSHooksExecutableName} should not be specified in the configuration for " diff --git a/GVFS/GVFS.Common/GVFSPlatform.cs b/GVFS/GVFS.Common/GVFSPlatform.cs index fb7df70d2c..798bff5d2b 100644 --- a/GVFS/GVFS.Common/GVFSPlatform.cs +++ b/GVFS/GVFS.Common/GVFSPlatform.cs @@ -176,6 +176,28 @@ public abstract class GVFSPlatformConstants /// public abstract HashSet UpgradeBlockingProcesses { get; } + public abstract bool CaseSensitiveFileSystem { get; } + + public StringComparison PathComparison + { + get + { + return this.CaseSensitiveFileSystem ? + StringComparison.Ordinal : + StringComparison.OrdinalIgnoreCase; + } + } + + public StringComparer PathComparer + { + get + { + return this.CaseSensitiveFileSystem ? + StringComparer.Ordinal : + StringComparer.OrdinalIgnoreCase; + } + } + public string GVFSHooksExecutableName { get { return "GVFS.Hooks" + this.ExecutableExtension; } diff --git a/GVFS/GVFS.Common/GitHubUpgrader.cs b/GVFS/GVFS.Common/GitHubUpgrader.cs index f85b9414f9..b2543db256 100644 --- a/GVFS/GVFS.Common/GitHubUpgrader.cs +++ b/GVFS/GVFS.Common/GitHubUpgrader.cs @@ -29,7 +29,7 @@ public class GitHubUpgrader : ProductUpgrader private const string GitSigner = "Johannes Schindelin"; private const string GitCertIssuer = "COMODO RSA Code Signing CA"; - private static readonly HashSet GVFSInstallerFileNamePrefixCandidates = new HashSet(StringComparer.OrdinalIgnoreCase) + private static readonly HashSet GVFSInstallerFileNamePrefixCandidates = new HashSet(GVFSPlatform.Instance.Constants.PathComparer) { "SetupGVFS", "VFSForGit" @@ -152,7 +152,7 @@ public override bool TryDownloadNewestVersion(out string errorMessage) foreach (Asset asset in this.newestRelease.Assets) { - bool targetOSMatch = string.Equals(Path.GetExtension(asset.Name), GVFSPlatform.Instance.Constants.InstallerExtension, StringComparison.OrdinalIgnoreCase); + bool targetOSMatch = string.Equals(Path.GetExtension(asset.Name), GVFSPlatform.Instance.Constants.InstallerExtension, GVFSPlatform.Instance.Constants.PathComparison); bool isGitAsset = this.IsGitAsset(asset); bool isGVFSAsset = isGitAsset ? false : this.IsGVFSAsset(asset); if (!targetOSMatch || (!isGVFSAsset && !isGitAsset)) @@ -461,7 +461,7 @@ private bool TryGetLocalInstallerPath(string assetId, out string path, out strin { foreach (Asset asset in this.newestRelease.Assets) { - if (string.Equals(Path.GetExtension(asset.Name), GVFSPlatform.Instance.Constants.InstallerExtension, StringComparison.OrdinalIgnoreCase)) + if (string.Equals(Path.GetExtension(asset.Name), GVFSPlatform.Instance.Constants.InstallerExtension, GVFSPlatform.Instance.Constants.PathComparison)) { path = asset.LocalPath; if (assetId == GitAssetId && this.IsGitAsset(asset)) @@ -497,7 +497,7 @@ private bool AssetInstallerNameCompare(Asset asset, IEnumerable expected { foreach (string fileNamePrefix in expectedFileNamePrefixes) { - if (asset.Name.StartsWith(fileNamePrefix, StringComparison.OrdinalIgnoreCase)) + if (asset.Name.StartsWith(fileNamePrefix, GVFSPlatform.Instance.Constants.PathComparison)) { return true; } diff --git a/GVFS/GVFS.Common/Maintenance/GitMaintenanceStep.cs b/GVFS/GVFS.Common/Maintenance/GitMaintenanceStep.cs index dcbd0597b7..10eb001e0c 100644 --- a/GVFS/GVFS.Common/Maintenance/GitMaintenanceStep.cs +++ b/GVFS/GVFS.Common/Maintenance/GitMaintenanceStep.cs @@ -150,12 +150,12 @@ public void GetPackFilesInfo(out int count, out long size, out bool hasKeep) { string extension = Path.GetExtension(info.Name); - if (string.Equals(extension, ".pack", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(extension, ".pack", GVFSPlatform.Instance.Constants.PathComparison)) { count++; size += info.Length; } - else if (string.Equals(extension, ".keep", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(extension, ".keep", GVFSPlatform.Instance.Constants.PathComparison)) { hasKeep = true; } diff --git a/GVFS/GVFS.Common/Maintenance/GitProcessChecker.cs b/GVFS/GVFS.Common/Maintenance/GitProcessChecker.cs index 54aa7cd588..e4bcbd1ab4 100644 --- a/GVFS/GVFS.Common/Maintenance/GitProcessChecker.cs +++ b/GVFS/GVFS.Common/Maintenance/GitProcessChecker.cs @@ -11,7 +11,7 @@ public virtual IEnumerable GetRunningGitProcessIds() { Process[] allProcesses = Process.GetProcesses(); return allProcesses - .Where(x => x.ProcessName.Equals("git", StringComparison.OrdinalIgnoreCase)) + .Where(x => x.ProcessName.Equals("git", GVFSPlatform.Instance.Constants.PathComparison)) .Select(x => x.Id); } } diff --git a/GVFS/GVFS.Common/Maintenance/PackfileMaintenanceStep.cs b/GVFS/GVFS.Common/Maintenance/PackfileMaintenanceStep.cs index 998b82d6b2..a5fc5b54a6 100644 --- a/GVFS/GVFS.Common/Maintenance/PackfileMaintenanceStep.cs +++ b/GVFS/GVFS.Common/Maintenance/PackfileMaintenanceStep.cs @@ -66,7 +66,7 @@ public List CleanStaleIdxFiles(out int numDeletionBlocked) foreach (DirectoryItemInfo info in packDirContents) { - if (string.Equals(Path.GetExtension(info.Name), ".idx", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(Path.GetExtension(info.Name), ".idx", GVFSPlatform.Instance.Constants.PathComparison)) { string pairedPack = Path.ChangeExtension(info.FullName, ".pack"); diff --git a/GVFS/GVFS.Common/Maintenance/PrefetchStep.cs b/GVFS/GVFS.Common/Maintenance/PrefetchStep.cs index 39ac2aa6b1..901ec4cf20 100644 --- a/GVFS/GVFS.Common/Maintenance/PrefetchStep.cs +++ b/GVFS/GVFS.Common/Maintenance/PrefetchStep.cs @@ -325,7 +325,7 @@ private void UpdateKeepPacks() .FileSystem .ItemsInDirectory(this.Context.Enlistment.GitPackRoot) .Where(item => item.Name.StartsWith(prefix) - && string.Equals(Path.GetExtension(item.Name), ".pack", StringComparison.OrdinalIgnoreCase)) + && string.Equals(Path.GetExtension(item.Name), ".pack", GVFSPlatform.Instance.Constants.PathComparison)) .FirstOrDefault(); if (info == null) { diff --git a/GVFS/GVFS.Common/RepoMetadata.cs b/GVFS/GVFS.Common/RepoMetadata.cs index 9aeea0e914..ea3d3ebf1e 100644 --- a/GVFS/GVFS.Common/RepoMetadata.cs +++ b/GVFS/GVFS.Common/RepoMetadata.cs @@ -48,7 +48,7 @@ public static bool TryInitialize(ITracer tracer, PhysicalFileSystem fileSystem, string dictionaryPath = Path.Combine(dotGVFSPath, GVFSConstants.DotGVFS.Databases.RepoMetadata); if (Instance != null) { - if (!Instance.repoMetadata.DataFilePath.Equals(dictionaryPath, StringComparison.OrdinalIgnoreCase)) + if (!Instance.repoMetadata.DataFilePath.Equals(dictionaryPath, GVFSPlatform.Instance.Constants.PathComparison)) { throw new InvalidOperationException( string.Format( diff --git a/GVFS/GVFS.Platform.Mac/MacPlatform.cs b/GVFS/GVFS.Platform.Mac/MacPlatform.cs index f07747f5de..b1588d1bb1 100644 --- a/GVFS/GVFS.Platform.Mac/MacPlatform.cs +++ b/GVFS/GVFS.Platform.Mac/MacPlatform.cs @@ -234,6 +234,8 @@ public override string RunUpdateMessage { get { return $"Run {UpgradeConfirmMessage}."; } } + + public override bool CaseSensitiveFileSystem => false; } } } diff --git a/GVFS/GVFS.Platform.POSIX/POSIXPlatform.cs b/GVFS/GVFS.Platform.POSIX/POSIXPlatform.cs index 4183bb5bf8..823157616e 100644 --- a/GVFS/GVFS.Platform.POSIX/POSIXPlatform.cs +++ b/GVFS/GVFS.Platform.POSIX/POSIXPlatform.cs @@ -293,7 +293,7 @@ public override string ProgramLocaterCommand public override HashSet UpgradeBlockingProcesses { - get { return new HashSet(StringComparer.OrdinalIgnoreCase) { "GVFS.Mount", "git", "wish" }; } + get { return new HashSet(GVFSPlatform.Instance.Constants.PathComparer) { "GVFS.Mount", "git", "wish" }; } } public override bool SupportsUpgradeWhileRunning => true; diff --git a/GVFS/GVFS.Platform.Windows/ProjFSFilter.cs b/GVFS/GVFS.Platform.Windows/ProjFSFilter.cs index d255f4de64..a3ba15a4a3 100644 --- a/GVFS/GVFS.Platform.Windows/ProjFSFilter.cs +++ b/GVFS/GVFS.Platform.Windows/ProjFSFilter.cs @@ -436,7 +436,7 @@ public bool TryPrepareFolderForCallbacks(string folderPath, out string error, ou { exception = e; - if (e.FileName.Equals(ProjFSManagedLibFileName, StringComparison.OrdinalIgnoreCase)) + if (e.FileName.Equals(ProjFSManagedLibFileName, GVFSPlatform.Instance.Constants.PathComparison)) { error = $"Failed to load {ProjFSManagedLibFileName}. Ensure that ProjFS is installed and enabled"; } diff --git a/GVFS/GVFS.Platform.Windows/WindowsFileSystem.cs b/GVFS/GVFS.Platform.Windows/WindowsFileSystem.cs index 00d77863c2..3696e3f476 100644 --- a/GVFS/GVFS.Platform.Windows/WindowsFileSystem.cs +++ b/GVFS/GVFS.Platform.Windows/WindowsFileSystem.cs @@ -109,7 +109,7 @@ public bool HydrateFile(string fileName, byte[] buffer) public bool IsExecutable(string fileName) { string fileExtension = Path.GetExtension(fileName); - return string.Equals(fileExtension, ".exe", StringComparison.OrdinalIgnoreCase); + return string.Equals(fileExtension, ".exe", GVFSPlatform.Instance.Constants.PathComparison); } public bool IsSocket(string fileName) diff --git a/GVFS/GVFS.Platform.Windows/WindowsPlatform.cs b/GVFS/GVFS.Platform.Windows/WindowsPlatform.cs index 3992b48b1d..6bf77778f6 100644 --- a/GVFS/GVFS.Platform.Windows/WindowsPlatform.cs +++ b/GVFS/GVFS.Platform.Windows/WindowsPlatform.cs @@ -494,7 +494,7 @@ public override string ProgramLocaterCommand public override HashSet UpgradeBlockingProcesses { - get { return new HashSet(StringComparer.OrdinalIgnoreCase) { "GVFS", "GVFS.Mount", "git", "ssh-agent", "wish", "bash" }; } + get { return new HashSet(GVFSPlatform.Instance.Constants.PathComparer) { "GVFS", "GVFS.Mount", "git", "ssh-agent", "wish", "bash" }; } } // Tests show that 250 is the max supported pipe name length @@ -519,6 +519,8 @@ public override string RunUpdateMessage { get { return $"Run {UpgradeConfirmMessage} from an elevated command prompt."; } } + + public override bool CaseSensitiveFileSystem => false; } } } diff --git a/GVFS/GVFS.Service/RepoRegistry.cs b/GVFS/GVFS.Service/RepoRegistry.cs index d46ba4cf00..169c0b2da2 100644 --- a/GVFS/GVFS.Service/RepoRegistry.cs +++ b/GVFS/GVFS.Service/RepoRegistry.cs @@ -192,7 +192,7 @@ public void AutoMountRepos(string userId, int sessionId) public Dictionary ReadRegistry() { - Dictionary allRepos = new Dictionary(StringComparer.OrdinalIgnoreCase); + Dictionary allRepos = new Dictionary(GVFSPlatform.Instance.Constants.PathComparer); using (Stream stream = this.fileSystem.OpenFileStream( Path.Combine(this.registryParentFolderPath, RegistryName), @@ -233,7 +233,7 @@ public Dictionary ReadRegistry() string normalizedEnlistmentRootPath = registration.EnlistmentRoot; if (this.fileSystem.TryGetNormalizedPath(registration.EnlistmentRoot, out normalizedEnlistmentRootPath, out errorMessage)) { - if (!normalizedEnlistmentRootPath.Equals(registration.EnlistmentRoot, StringComparison.OrdinalIgnoreCase)) + if (!normalizedEnlistmentRootPath.Equals(registration.EnlistmentRoot, GVFSPlatform.Instance.Constants.PathComparison)) { EventMetadata metadata = new EventMetadata(); metadata.Add("registration.EnlistmentRoot", registration.EnlistmentRoot); diff --git a/GVFS/GVFS.UnitTests/Category/CategoryConstants.cs b/GVFS/GVFS.UnitTests/Category/CategoryConstants.cs index 7a9001c2b3..116d92a725 100644 --- a/GVFS/GVFS.UnitTests/Category/CategoryConstants.cs +++ b/GVFS/GVFS.UnitTests/Category/CategoryConstants.cs @@ -3,5 +3,6 @@ public static class CategoryConstants { public const string ExceptionExpected = "ExceptionExpected"; + public const string CaseInsensitiveFileSystemOnly = "CaseInsensitiveFileSystemOnly"; } } diff --git a/GVFS/GVFS.UnitTests/Common/FileBasedDictionaryTests.cs b/GVFS/GVFS.UnitTests/Common/FileBasedDictionaryTests.cs index 511a379df4..f31778e8f6 100644 --- a/GVFS/GVFS.UnitTests/Common/FileBasedDictionaryTests.cs +++ b/GVFS/GVFS.UnitTests/Common/FileBasedDictionaryTests.cs @@ -329,7 +329,7 @@ public override bool FileExists(string path) if (this.maxFileExistsFailures > 0) { if (this.fileExistsFailureCount < this.maxFileExistsFailures && - string.Equals(path, this.fileExistsFailurePath, System.StringComparison.OrdinalIgnoreCase)) + string.Equals(path, this.fileExistsFailurePath, GVFSPlatform.Instance.Constants.PathComparison)) { if (this.ExpectedFiles.ContainsKey(path)) { @@ -342,7 +342,7 @@ public override bool FileExists(string path) else if (this.failuresAcrossOpenExistsAndOverwritePath != null) { if (this.failuresAcrossOpenExistsAndOverwriteCount == 1 && - string.Equals(path, this.failuresAcrossOpenExistsAndOverwritePath, System.StringComparison.OrdinalIgnoreCase)) + string.Equals(path, this.failuresAcrossOpenExistsAndOverwritePath, GVFSPlatform.Instance.Constants.PathComparison)) { if (this.ExpectedFiles.ContainsKey(path)) { @@ -391,7 +391,7 @@ public override Stream OpenFileStream(string path, FileMode fileMode, FileAccess if (this.maxOpenFileStreamFailures > 0) { if (this.openFileStreamFailureCount < this.maxOpenFileStreamFailures && - string.Equals(path, this.openFileStreamFailurePath, System.StringComparison.OrdinalIgnoreCase)) + string.Equals(path, this.openFileStreamFailurePath, GVFSPlatform.Instance.Constants.PathComparison)) { ++this.openFileStreamFailureCount; @@ -408,7 +408,7 @@ public override Stream OpenFileStream(string path, FileMode fileMode, FileAccess else if (this.failuresAcrossOpenExistsAndOverwritePath != null) { if (this.failuresAcrossOpenExistsAndOverwriteCount == 0 && - string.Equals(path, this.failuresAcrossOpenExistsAndOverwritePath, System.StringComparison.OrdinalIgnoreCase)) + string.Equals(path, this.failuresAcrossOpenExistsAndOverwritePath, GVFSPlatform.Instance.Constants.PathComparison)) { ++this.failuresAcrossOpenExistsAndOverwriteCount; throw new IOException(); diff --git a/GVFS/GVFS.UnitTests/Mock/Common/MockPlatform.cs b/GVFS/GVFS.UnitTests/Mock/Common/MockPlatform.cs index c4108c3f83..6118691b19 100644 --- a/GVFS/GVFS.UnitTests/Mock/Common/MockPlatform.cs +++ b/GVFS/GVFS.UnitTests/Mock/Common/MockPlatform.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.IO; using System.IO.Pipes; +using System.Runtime.InteropServices; namespace GVFS.UnitTests.Mock.Common { @@ -237,7 +238,7 @@ public override string ProgramLocaterCommand public override HashSet UpgradeBlockingProcesses { - get { return new HashSet(StringComparer.OrdinalIgnoreCase) { "GVFS", "GVFS.Mount", "git", "wish", "bash" }; } + get { return new HashSet(this.PathComparer) { "GVFS", "GVFS.Mount", "git", "wish", "bash" }; } } public override bool SupportsUpgradeWhileRunning => false; @@ -263,6 +264,8 @@ public override string RunUpdateMessage { get { return "MockRunUpdateMessage"; } } + + public override bool CaseSensitiveFileSystem => RuntimeInformation.IsOSPlatform(OSPlatform.Linux); } } } diff --git a/GVFS/GVFS.UnitTests/Mock/FileSystem/MockFileSystem.cs b/GVFS/GVFS.UnitTests/Mock/FileSystem/MockFileSystem.cs index 488ddcc31d..fa40882b7e 100644 --- a/GVFS/GVFS.UnitTests/Mock/FileSystem/MockFileSystem.cs +++ b/GVFS/GVFS.UnitTests/Mock/FileSystem/MockFileSystem.cs @@ -231,7 +231,7 @@ public override bool TryCreateOrUpdateDirectoryToAdminModifyPermissions(ITracer // if it's called for one of those paths remap the paths to be inside the mock: root string mockDirectoryPath = directoryPath; string gvfsProgramData = @"C:\ProgramData\GVFS"; - if (directoryPath.StartsWith(gvfsProgramData, StringComparison.OrdinalIgnoreCase)) + if (directoryPath.StartsWith(gvfsProgramData, GVFSPlatform.Instance.Constants.PathComparison)) { mockDirectoryPath = mockDirectoryPath.Substring(gvfsProgramData.Length); mockDirectoryPath = "mock:" + mockDirectoryPath; diff --git a/GVFS/GVFS.UnitTests/Mock/MockGitHubUpgrader.cs b/GVFS/GVFS.UnitTests/Mock/MockGitHubUpgrader.cs index 5b37d8cf31..56d6520e0f 100644 --- a/GVFS/GVFS.UnitTests/Mock/MockGitHubUpgrader.cs +++ b/GVFS/GVFS.UnitTests/Mock/MockGitHubUpgrader.cs @@ -124,7 +124,7 @@ protected override bool TryCreateAndConfigureDownloadDirectory(ITracer tracer, o protected override bool TryDownloadAsset(Asset asset, out string errorMessage) { bool validAsset = true; - if (this.expectedGVFSAssetName.Equals(asset.Name, StringComparison.OrdinalIgnoreCase)) + if (this.expectedGVFSAssetName.Equals(asset.Name, GVFSPlatform.Instance.Constants.PathComparison)) { if (this.failActionTypes.HasFlag(ActionType.GVFSDownload)) { @@ -132,7 +132,7 @@ protected override bool TryDownloadAsset(Asset asset, out string errorMessage) return false; } } - else if (this.expectedGitAssetName.Equals(asset.Name, StringComparison.OrdinalIgnoreCase)) + else if (this.expectedGitAssetName.Equals(asset.Name, GVFSPlatform.Instance.Constants.PathComparison)) { if (this.failActionTypes.HasFlag(ActionType.GitDownload)) { @@ -161,7 +161,7 @@ protected override bool TryDownloadAsset(Asset asset, out string errorMessage) protected override bool TryDeleteDownloadedAsset(Asset asset, out Exception exception) { - if (this.expectedGVFSAssetName.Equals(asset.Name, StringComparison.OrdinalIgnoreCase)) + if (this.expectedGVFSAssetName.Equals(asset.Name, GVFSPlatform.Instance.Constants.PathComparison)) { if (this.failActionTypes.HasFlag(ActionType.GVFSCleanup)) { @@ -172,7 +172,7 @@ protected override bool TryDeleteDownloadedAsset(Asset asset, out Exception exce exception = null; return true; } - else if (this.expectedGitAssetName.Equals(asset.Name, StringComparison.OrdinalIgnoreCase)) + else if (this.expectedGitAssetName.Equals(asset.Name, GVFSPlatform.Instance.Constants.PathComparison)) { if (this.failActionTypes.HasFlag(ActionType.GitCleanup)) { @@ -215,7 +215,7 @@ protected override void RunInstaller(string path, string args, string certCN, st exitCode = 0; error = null; - if (fileName.Equals(this.expectedGitAssetName, StringComparison.OrdinalIgnoreCase)) + if (fileName.Equals(this.expectedGitAssetName, GVFSPlatform.Instance.Constants.PathComparison)) { this.InstallerArgs.Add("Git", installationInfo); this.InstallerExeLaunched = true; @@ -234,7 +234,7 @@ protected override void RunInstaller(string path, string args, string certCN, st return; } - if (fileName.Equals(this.expectedGVFSAssetName, StringComparison.OrdinalIgnoreCase)) + if (fileName.Equals(this.expectedGVFSAssetName, GVFSPlatform.Instance.Constants.PathComparison)) { this.InstallerArgs.Add("GVFS", installationInfo); this.InstallerExeLaunched = true; diff --git a/GVFS/GVFS.UnitTests/Prefetch/DiffHelperTests.cs b/GVFS/GVFS.UnitTests/Prefetch/DiffHelperTests.cs index 99983ed18d..f452b4c445 100644 --- a/GVFS/GVFS.UnitTests/Prefetch/DiffHelperTests.cs +++ b/GVFS/GVFS.UnitTests/Prefetch/DiffHelperTests.cs @@ -2,6 +2,7 @@ using GVFS.Common.Prefetch.Git; using GVFS.Tests; using GVFS.Tests.Should; +using GVFS.UnitTests.Category; using GVFS.UnitTests.Mock.Common; using GVFS.UnitTests.Mock.Git; using NUnit.Framework; @@ -102,6 +103,7 @@ public void CanParseBackwardsDiff() // Delete a folder with two sub folders each with a single file // Readd it with a different casing and same contents [TestCase] + [Category(CategoryConstants.CaseInsensitiveFileSystemOnly)] public void ParsesCaseChangesAsAdds() { MockTracer tracer = new MockTracer(); @@ -148,4 +150,4 @@ private static string GetDataPath(string fileName) return Path.Combine(workingDirectory, "Data", fileName); } } -} \ No newline at end of file +} diff --git a/GVFS/GVFS.UnitTests/Program.cs b/GVFS/GVFS.UnitTests/Program.cs index 6e7a559b22..a0c4440e3e 100644 --- a/GVFS/GVFS.UnitTests/Program.cs +++ b/GVFS/GVFS.UnitTests/Program.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Runtime.InteropServices; namespace GVFS.UnitTests { @@ -20,6 +21,11 @@ public static void Main(string[] args) excludeCategories.Add(CategoryConstants.ExceptionExpected); } + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + excludeCategories.Add(CategoryConstants.CaseInsensitiveFileSystemOnly); + } + Environment.ExitCode = runner.RunTests(includeCategories: null, excludeCategories: excludeCategories); if (Debugger.IsAttached) @@ -29,4 +35,4 @@ public static void Main(string[] args) } } } -} \ No newline at end of file +} diff --git a/GVFS/GVFS.UnitTests/Virtualization/FileSystemCallbacksTests.cs b/GVFS/GVFS.UnitTests/Virtualization/FileSystemCallbacksTests.cs index d57d0a8edf..45f04a6db4 100644 --- a/GVFS/GVFS.UnitTests/Virtualization/FileSystemCallbacksTests.cs +++ b/GVFS/GVFS.UnitTests/Virtualization/FileSystemCallbacksTests.cs @@ -3,6 +3,7 @@ using GVFS.Common.NamedPipes; using GVFS.Common.Tracing; using GVFS.Tests.Should; +using GVFS.UnitTests.Category; using GVFS.UnitTests.Mock.Common; using GVFS.UnitTests.Mock.Virtualization.Background; using GVFS.UnitTests.Mock.Virtualization.BlobSize; @@ -33,10 +34,16 @@ public void EmptyStringIsNotInsideDotGitPath() public void IsPathInsideDotGitIsTrueForDotGitPath() { FileSystemCallbacks.IsPathInsideDotGit(@".git" + Path.DirectorySeparatorChar).ShouldEqual(true); - FileSystemCallbacks.IsPathInsideDotGit(@".GIT" + Path.DirectorySeparatorChar).ShouldEqual(true); FileSystemCallbacks.IsPathInsideDotGit(Path.Combine(".git", "test_file.txt")).ShouldEqual(true); + FileSystemCallbacks.IsPathInsideDotGit(Path.Combine(".git", "test_folder", "test_file.txt")).ShouldEqual(true); + } + + [TestCase] + [Category(CategoryConstants.CaseInsensitiveFileSystemOnly)] + public void IsPathInsideDotGitIsTrueForDifferentCaseDotGitPath() + { + FileSystemCallbacks.IsPathInsideDotGit(@".GIT" + Path.DirectorySeparatorChar).ShouldEqual(true); FileSystemCallbacks.IsPathInsideDotGit(Path.Combine(".GIT", "test_file.txt")).ShouldEqual(true); - FileSystemCallbacks.IsPathInsideDotGit(Path.Combine(".git", "test_folder", "test_file.txt")).ShouldEqual(true); FileSystemCallbacks.IsPathInsideDotGit(Path.Combine(".GIT", "test_folder", "test_file.txt")).ShouldEqual(true); } diff --git a/GVFS/GVFS.Virtualization/Background/FileSystemTaskQueue.cs b/GVFS/GVFS.Virtualization/Background/FileSystemTaskQueue.cs index fc6a0db98c..4f93a8b56b 100644 --- a/GVFS/GVFS.Virtualization/Background/FileSystemTaskQueue.cs +++ b/GVFS/GVFS.Virtualization/Background/FileSystemTaskQueue.cs @@ -123,7 +123,7 @@ public bool TryPeek(out FileSystemTask value) private bool TryParseAddLine(string line, out long key, out FileSystemTask value, out string error) { // Expected: \0 - int idx = line.IndexOf(ValueTerminator, StringComparison.OrdinalIgnoreCase); + int idx = line.IndexOf(ValueTerminator, StringComparison.Ordinal); if (idx < 0) { key = 0; diff --git a/GVFS/GVFS.Virtualization/FileSystem/FileSystemVirtualizer.cs b/GVFS/GVFS.Virtualization/FileSystem/FileSystemVirtualizer.cs index 3e2450fd84..058f66422f 100644 --- a/GVFS/GVFS.Virtualization/FileSystem/FileSystemVirtualizer.cs +++ b/GVFS/GVFS.Virtualization/FileSystem/FileSystemVirtualizer.cs @@ -150,17 +150,17 @@ protected bool CanCreatePlaceholder() protected bool IsSpecialGitFile(string fileName) { return - fileName.Equals(GVFSConstants.SpecialGitFiles.GitAttributes, StringComparison.OrdinalIgnoreCase) || - fileName.Equals(GVFSConstants.SpecialGitFiles.GitIgnore, StringComparison.OrdinalIgnoreCase); + fileName.Equals(GVFSConstants.SpecialGitFiles.GitAttributes, GVFSPlatform.Instance.Constants.PathComparison) || + fileName.Equals(GVFSConstants.SpecialGitFiles.GitIgnore, GVFSPlatform.Instance.Constants.PathComparison); } protected void OnDotGitFileOrFolderChanged(string relativePath) { - if (relativePath.Equals(GVFSConstants.DotGit.Index, StringComparison.OrdinalIgnoreCase)) + if (relativePath.Equals(GVFSConstants.DotGit.Index, GVFSPlatform.Instance.Constants.PathComparison)) { this.FileSystemCallbacks.OnIndexFileChange(); } - else if (relativePath.Equals(GVFSConstants.DotGit.Logs.Head, StringComparison.OrdinalIgnoreCase)) + else if (relativePath.Equals(GVFSConstants.DotGit.Logs.Head, GVFSPlatform.Instance.Constants.PathComparison)) { this.FileSystemCallbacks.OnLogsHeadChange(); } @@ -168,7 +168,7 @@ protected void OnDotGitFileOrFolderChanged(string relativePath) { this.FileSystemCallbacks.OnHeadOrRefChanged(); } - else if (relativePath.Equals(GVFSConstants.DotGit.Info.ExcludePath, StringComparison.OrdinalIgnoreCase)) + else if (relativePath.Equals(GVFSConstants.DotGit.Info.ExcludePath, GVFSPlatform.Instance.Constants.PathComparison)) { this.FileSystemCallbacks.OnExcludeFileChanged(); } @@ -180,7 +180,7 @@ protected void OnDotGitFileOrFolderDeleted(string relativePath) { this.FileSystemCallbacks.OnHeadOrRefChanged(); } - else if (relativePath.Equals(GVFSConstants.DotGit.Info.ExcludePath, StringComparison.OrdinalIgnoreCase)) + else if (relativePath.Equals(GVFSConstants.DotGit.Info.ExcludePath, GVFSPlatform.Instance.Constants.PathComparison)) { this.FileSystemCallbacks.OnExcludeFileChanged(); } @@ -364,9 +364,9 @@ protected void LogUnhandledExceptionAndExit(string methodName, EventMetadata met private static bool IsPathHeadOrLocalBranch(string relativePath) { - if (!relativePath.EndsWith(GVFSConstants.DotGit.LockExtension, StringComparison.OrdinalIgnoreCase) && - (relativePath.Equals(GVFSConstants.DotGit.Head, StringComparison.OrdinalIgnoreCase) || - relativePath.StartsWith(GVFSConstants.DotGit.Refs.Heads.RootFolder, StringComparison.OrdinalIgnoreCase))) + if (!relativePath.EndsWith(GVFSConstants.DotGit.LockExtension, GVFSPlatform.Instance.Constants.PathComparison) && + (relativePath.Equals(GVFSConstants.DotGit.Head, GVFSPlatform.Instance.Constants.PathComparison) || + relativePath.StartsWith(GVFSConstants.DotGit.Refs.Heads.RootFolder, GVFSPlatform.Instance.Constants.PathComparison))) { return true; } diff --git a/GVFS/GVFS.Virtualization/FileSystemCallbacks.cs b/GVFS/GVFS.Virtualization/FileSystemCallbacks.cs index 3317db5deb..978ccf5aed 100644 --- a/GVFS/GVFS.Virtualization/FileSystemCallbacks.cs +++ b/GVFS/GVFS.Virtualization/FileSystemCallbacks.cs @@ -62,9 +62,9 @@ public FileSystemCallbacks( this.context = context; this.fileSystemVirtualizer = fileSystemVirtualizer; - this.filePlaceHolderCreationCount = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); - this.folderPlaceHolderCreationCount = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); - this.fileHydrationCount = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + this.filePlaceHolderCreationCount = new ConcurrentDictionary(GVFSPlatform.Instance.Constants.PathComparer); + this.folderPlaceHolderCreationCount = new ConcurrentDictionary(GVFSPlatform.Instance.Constants.PathComparer); + this.fileHydrationCount = new ConcurrentDictionary(GVFSPlatform.Instance.Constants.PathComparer); this.newlyCreatedFileAndFolderPaths = new ConcurrentHashSet(StringComparer.OrdinalIgnoreCase); string error; @@ -151,7 +151,7 @@ public int BackgroundOperationCount /// public static bool IsPathInsideDotGit(string relativePath) { - return relativePath.StartsWith(GVFSConstants.DotGit.Root + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase); + return relativePath.StartsWith(GVFSConstants.DotGit.Root + Path.DirectorySeparatorChar, GVFSPlatform.Instance.Constants.PathComparison); } public bool TryStart(out string error) diff --git a/GVFS/GVFS/CommandLine/CloneVerb.cs b/GVFS/GVFS/CommandLine/CloneVerb.cs index d608c003e3..ff1d54ac88 100644 --- a/GVFS/GVFS/CommandLine/CloneVerb.cs +++ b/GVFS/GVFS/CommandLine/CloneVerb.cs @@ -102,7 +102,7 @@ public override void Execute() if (normalizedLocalCacheRootPath.StartsWith( Path.Combine(normalizedEnlistmentRootPath, GVFSConstants.WorkingDirectoryRootName), - StringComparison.OrdinalIgnoreCase)) + GVFSPlatform.Instance.Constants.PathComparison)) { this.ReportErrorAndExit("'--local-cache-path' cannot be inside the src folder"); } @@ -293,7 +293,7 @@ private Result TryCreateEnlistment( // LogFileEventListener will create a file in EnlistmentRootPath if (Directory.Exists(normalizedEnlistementRootPath) && Directory.EnumerateFileSystemEntries(normalizedEnlistementRootPath).Any()) { - if (fullEnlistmentRootPathParameter.Equals(normalizedEnlistementRootPath, StringComparison.OrdinalIgnoreCase)) + if (fullEnlistmentRootPathParameter.Equals(normalizedEnlistementRootPath, GVFSPlatform.Instance.Constants.PathComparison)) { return new Result($"Clone directory '{fullEnlistmentRootPathParameter}' exists and is not empty"); } diff --git a/GVFS/GVFS/CommandLine/DehydrateVerb.cs b/GVFS/GVFS/CommandLine/DehydrateVerb.cs index bbcaa83c58..8cd7a1ef5a 100644 --- a/GVFS/GVFS/CommandLine/DehydrateVerb.cs +++ b/GVFS/GVFS/CommandLine/DehydrateVerb.cs @@ -363,7 +363,7 @@ private bool TryBackupFilesInFolder(ITracer tracer, string folderPath, string ba foreach (string file in Directory.GetFiles(folderPath, searchPattern)) { string fileName = Path.GetFileName(file); - if (!filenamesToSkip.Any(x => x.Equals(fileName, StringComparison.OrdinalIgnoreCase))) + if (!filenamesToSkip.Any(x => x.Equals(fileName, GVFSPlatform.Instance.Constants.PathComparison))) { if (!this.TryIO( tracer, diff --git a/GVFS/GVFS/CommandLine/DiagnoseVerb.cs b/GVFS/GVFS/CommandLine/DiagnoseVerb.cs index 496b6a07be..4e64df2c95 100644 --- a/GVFS/GVFS/CommandLine/DiagnoseVerb.cs +++ b/GVFS/GVFS/CommandLine/DiagnoseVerb.cs @@ -561,7 +561,7 @@ private void PrintDiskSpaceInfo(string localCacheRoot, string enlistmentRootPara DriveInfo enlistmentDrive = new DriveInfo(enlistmentNormalizedPathRoot); string enlistmentDriveDiskSpace = this.FormatByteCount(enlistmentDrive.AvailableFreeSpace); - if (string.Equals(enlistmentNormalizedPathRoot, localCacheNormalizedPathRoot, StringComparison.OrdinalIgnoreCase)) + if (string.Equals(enlistmentNormalizedPathRoot, localCacheNormalizedPathRoot, GVFSPlatform.Instance.Constants.PathComparison)) { this.WriteMessage("Available space on " + enlistmentDrive.Name + " drive(enlistment and local cache): " + enlistmentDriveDiskSpace); } diff --git a/GVFS/GVFS/CommandLine/GVFSVerb.cs b/GVFS/GVFS/CommandLine/GVFSVerb.cs index ac6b09f70c..96159aaadf 100644 --- a/GVFS/GVFS/CommandLine/GVFSVerb.cs +++ b/GVFS/GVFS/CommandLine/GVFSVerb.cs @@ -961,7 +961,7 @@ private void EnsureLocalCacheIsHealthy( while (!reader.EndOfStream) { string alternatesLine = reader.ReadLine(); - if (string.Equals(alternatesLine, enlistment.GitObjectsRoot, StringComparison.OrdinalIgnoreCase)) + if (string.Equals(alternatesLine, enlistment.GitObjectsRoot, GVFSPlatform.Instance.Constants.PathComparison)) { gitObjectsRootInAlternates = true; } diff --git a/GVFS/GVFS/CommandLine/HealthVerb.cs b/GVFS/GVFS/CommandLine/HealthVerb.cs index 1ae9e35bbf..b12b58d2c0 100644 --- a/GVFS/GVFS/CommandLine/HealthVerb.cs +++ b/GVFS/GVFS/CommandLine/HealthVerb.cs @@ -36,7 +36,7 @@ protected override void Execute(GVFSEnlistment enlistment) // Now default to the current working directory when running the verb without a specified path if (string.IsNullOrEmpty(this.Directory) || this.Directory.Equals(".")) { - if (Environment.CurrentDirectory.StartsWith(enlistment.WorkingDirectoryRoot, StringComparison.OrdinalIgnoreCase)) + if (Environment.CurrentDirectory.StartsWith(enlistment.WorkingDirectoryRoot, GVFSPlatform.Instance.Constants.PathComparison)) { this.Directory = Environment.CurrentDirectory.Substring(enlistment.WorkingDirectoryRoot.Length); } diff --git a/MirrorProvider/MirrorProvider.Mac/MacFileSystemVirtualizer.cs b/MirrorProvider/MirrorProvider.Mac/MacFileSystemVirtualizer.cs index 77a9a5e239..f8624b084e 100644 --- a/MirrorProvider/MirrorProvider.Mac/MacFileSystemVirtualizer.cs +++ b/MirrorProvider/MirrorProvider.Mac/MacFileSystemVirtualizer.cs @@ -10,6 +10,8 @@ public class MacFileSystemVirtualizer : FileSystemVirtualizer { private VirtualizationInstance virtualizationInstance = new VirtualizationInstance(); + protected override StringComparison PathComparison => StringComparison.OrdinalIgnoreCase; + public override bool TryConvertVirtualizationRoot(string directory, out string error) { Result result = VirtualizationInstance.ConvertDirectoryToVirtualizationRoot(directory); diff --git a/MirrorProvider/MirrorProvider.Windows/WindowsFileSystemVirtualizer.cs b/MirrorProvider/MirrorProvider.Windows/WindowsFileSystemVirtualizer.cs index fd2de3c1ee..8b44069d8b 100644 --- a/MirrorProvider/MirrorProvider.Windows/WindowsFileSystemVirtualizer.cs +++ b/MirrorProvider/MirrorProvider.Windows/WindowsFileSystemVirtualizer.cs @@ -12,6 +12,8 @@ public class WindowsFileSystemVirtualizer : FileSystemVirtualizer, IRequiredCall private VirtualizationInstance virtualizationInstance; private ConcurrentDictionary activeEnumerations = new ConcurrentDictionary(); + protected override StringComparison PathComparison => StringComparison.OrdinalIgnoreCase; + public override bool TryConvertVirtualizationRoot(string directory, out string error) { error = string.Empty; diff --git a/MirrorProvider/MirrorProvider/FileSystemVirtualizer.cs b/MirrorProvider/MirrorProvider/FileSystemVirtualizer.cs index cb73aa0b01..f4a3f5f81b 100644 --- a/MirrorProvider/MirrorProvider/FileSystemVirtualizer.cs +++ b/MirrorProvider/MirrorProvider/FileSystemVirtualizer.cs @@ -8,6 +8,8 @@ namespace MirrorProvider public abstract class FileSystemVirtualizer { protected Enlistment Enlistment { get; private set; } + + protected abstract StringComparison PathComparison { get; } public abstract bool TryConvertVirtualizationRoot(string directory, out string error); public virtual bool TryStartVirtualizationInstance(Enlistment enlistment, out string error) @@ -147,7 +149,7 @@ private bool FileOrDirectoryExists( FileSystemInfo fileSystemInfo = dirInfo .GetFileSystemInfos() - .FirstOrDefault(fsInfo => fsInfo.Name.Equals(fileName, StringComparison.OrdinalIgnoreCase)); + .FirstOrDefault(fsInfo => fsInfo.Name.Equals(fileName, PathComparison)); if (fileSystemInfo == null) {