From 7bc761a0cc0ecf1a778032ae62ec4490759bd921 Mon Sep 17 00:00:00 2001 From: Ladi Prosek Date: Wed, 10 Mar 2021 15:05:07 +0100 Subject: [PATCH] Make sure that *.* always means all files in FileMatcher (#6235) ### Context #6151 introduced a regression where `FileMatcher` takes the pattern `*.*` too literally and returns only files that have a dot in the name. `*.*` should be special cased to mean all files in the directory, with or without an extension. ### Changes Made Fixed the regression by explicitly testing for `*.*` and added test coverage. ### Testing Existing and modified unit tests, repro project from https://github.com/dotnet/sdk/pull/16185#issuecomment-794428841. ### Notes Testing for both `*` and `*.*` is already happening elsewhere in the class. MSBuild calls `Directory.EnumerateFileSystemEntries` which under the covers uses `MatchType.Win32` and causes this behavior of unifying `*.*` with `*` on all platforms. --- src/Shared/FileMatcher.cs | 2 +- src/Shared/UnitTests/FileMatcher_Tests.cs | 21 +++++++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/Shared/FileMatcher.cs b/src/Shared/FileMatcher.cs index 0784baba45a..1bfdc57490e 100644 --- a/src/Shared/FileMatcher.cs +++ b/src/Shared/FileMatcher.cs @@ -131,7 +131,7 @@ internal FileMatcher(IFileSystem fileSystem, GetFileSystemEntries getFileSystemE "*", directory, false)); - IEnumerable filteredEntriesForPath = (pattern != null && pattern != "*") + IEnumerable filteredEntriesForPath = (pattern != null && pattern != "*" && pattern != "*.*") ? allEntriesForPath.Where(o => IsMatch(Path.GetFileName(o), pattern)) : allEntriesForPath; return stripProjectDirectory diff --git a/src/Shared/UnitTests/FileMatcher_Tests.cs b/src/Shared/UnitTests/FileMatcher_Tests.cs index e44680aac5b..c3d200829e3 100644 --- a/src/Shared/UnitTests/FileMatcher_Tests.cs +++ b/src/Shared/UnitTests/FileMatcher_Tests.cs @@ -5,6 +5,7 @@ using Shouldly; using System; using System.Collections.Generic; +using System.Collections.Concurrent; using System.IO; using System.Linq; using System.Text.RegularExpressions; @@ -77,9 +78,9 @@ public void GetFilesComplexGlobbingMatching(GetFilesComplexGlobbingMatchingInfo File.WriteAllBytes(fullPath, new byte[1]); } - void Verify(string include, string[] excludes, bool shouldHaveNoMatches = false, string customMessage = null) + void VerifyImpl(FileMatcher fileMatcher, string include, string[] excludes, bool shouldHaveNoMatches = false, string customMessage = null) { - string[] matchedFiles = FileMatcher.Default.GetFiles(testFolder.Path, include, excludes?.ToList()); + string[] matchedFiles = fileMatcher.GetFiles(testFolder.Path, include, excludes?.ToList()); if (shouldHaveNoMatches) { @@ -99,6 +100,18 @@ void Verify(string include, string[] excludes, bool shouldHaveNoMatches = false, } } + var fileMatcherWithCache = new FileMatcher(FileSystems.Default, new ConcurrentDictionary>()); + + void Verify(string include, string[] excludes, bool shouldHaveNoMatches = false, string customMessage = null) + { + // Verify using the default non-caching FileMatcher. + VerifyImpl(FileMatcher.Default, include, excludes, shouldHaveNoMatches, customMessage); + + // Verify using a caching FileMatcher and do it twice to exercise the cache. + VerifyImpl(fileMatcherWithCache, include, excludes, shouldHaveNoMatches, customMessage); + VerifyImpl(fileMatcherWithCache, include, excludes, shouldHaveNoMatches, customMessage); + } + // Normal matching Verify(info.Include, info.Excludes); @@ -153,7 +166,7 @@ public class GetFilesComplexGlobbingMatchingInfo @"subdirectory\subdirectory.cs", @"build\baz\foo.cs", @"readme.txt", - @"licence.md" + @"licence" }; /// @@ -355,7 +368,7 @@ public static IEnumerable GetTestData() ExpectedMatches = new[] { @"readme.txt", - @"licence.md" + @"licence" } } };