From 371e62eb7c33cb099d544f9c45b993a30e825281 Mon Sep 17 00:00:00 2001 From: Kevin Thompson Date: Fri, 3 Jul 2020 09:25:26 -0700 Subject: [PATCH] Update PathTraverser only emit files matching a pattern in multiple ways once Closes #52 --- ChangeLog.md | 4 ++++ src/Glob/Glob.csproj | 5 ++--- src/Glob/PathTraverser.cs | 10 ++++++++-- test/Glob.Tests/GlobTests.cs | 24 ++++++++++++++++++++++++ test/Glob.Tests/PathTraverserTests.cs | 4 ++++ 5 files changed, 42 insertions(+), 5 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 8352f2a..1562a5c 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [Unreleased] +## [1.1.7] +### Fixed +- Issue #52: Files matching a pattern in multiple ways are only emitted once ## [1.1.6] ### Fixed @@ -79,6 +82,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Fix issue where Glob.Directories did not always match properly [Unreleased]: https://github.com/kthompson/glob/compare/1.1.6...HEAD +[1.1.7]: https://github.com/kthompson/glob/compare/1.1.6...1.1.7 [1.1.6]: https://github.com/kthompson/glob/compare/1.1.5...1.1.6 [1.1.5]: https://github.com/kthompson/glob/compare/1.1.4...1.1.5 [1.1.4]: https://github.com/kthompson/glob/compare/1.1.3...1.1.4 diff --git a/src/Glob/Glob.csproj b/src/Glob/Glob.csproj index 5fee286..dbde662 100644 --- a/src/Glob/Glob.csproj +++ b/src/Glob/Glob.csproj @@ -10,8 +10,7 @@ Glob C#;glob;minimatch A C# Glob library for .NET and .NET Core. - Fixed -- Issue #57: Support parentheses, equals, and other miscellaneous characters in file names + Files matching a pattern in multiple ways are only emitted once https://github.com/kthompson/glob/ https://raw.githubusercontent.com/kthompson/glob/master/LICENSE git @@ -26,7 +25,7 @@ true GlobExpressions latest - 1.1.6 + 1.1.7 diff --git a/src/Glob/PathTraverser.cs b/src/Glob/PathTraverser.cs index c860163..979e6bd 100644 --- a/src/Glob/PathTraverser.cs +++ b/src/Glob/PathTraverser.cs @@ -35,6 +35,7 @@ private static IEnumerable Traverse(List roots, S var segmentIndex = 0; var emitDirectories = options.EmitDirectories; var emitFiles = options.EmitFiles; + var cache = new HashSet(); void Swap(ref List other) { @@ -77,8 +78,9 @@ where directorySegment.MatchesSegment(directory.Name, options.CaseSensitive) var noMoreSegments = segmentIndex == segmentsLength; if (emitDirectories && noMoreSegments) { - foreach (var info in roots) + foreach (var info in roots.Where(info => !cache.Contains(info.FullName))) { + cache.Add(info.FullName); yield return info; } } @@ -108,7 +110,11 @@ from file in FilesMatchingSegment(children, segment, options.CaseSensitive) foreach (var info in allFiles) { - yield return info; + if (!cache.Contains(info.FullName)) + { + cache.Add(info.FullName); + yield return info; + } } } rootCache.Clear(); diff --git a/test/Glob.Tests/GlobTests.cs b/test/Glob.Tests/GlobTests.cs index 719e6e7..0d7720c 100644 --- a/test/Glob.Tests/GlobTests.cs +++ b/test/Glob.Tests/GlobTests.cs @@ -379,6 +379,30 @@ public void StarStarFiles() } } + [Fact] + public void StarStarFilesIssue52() + { + Action AssertEqual(string expected) => actual => Assert.Equal(expected, actual); + + var testRoot = Path.Combine(Path.GetTempPath(), "Glob", "PathTraverserTests", "StarStarFilesIssue52"); + try + { + CreateFiles(testRoot, "a/a/a/a/b.txt"); + + // Verify files exist before + Assert.True(File.Exists(Path.Combine(testRoot, "a/a/a/a/b.txt"))); + + Assert.Collection(Glob.Files(testRoot, "**/a/**/b.txt").OrderBy(x => x), + AssertEqual(Path.Combine("a", "a", "a", "a", "b.txt")) + ); + } + finally + { + // Cleanup test + Directory.Delete(testRoot, true); + } + } + private void CreateFiles(string testRoot, string files) { Directory.CreateDirectory(testRoot); diff --git a/test/Glob.Tests/PathTraverserTests.cs b/test/Glob.Tests/PathTraverserTests.cs index c30a984..ce5fa3f 100644 --- a/test/Glob.Tests/PathTraverserTests.cs +++ b/test/Glob.Tests/PathTraverserTests.cs @@ -287,6 +287,10 @@ public void TestGlobExpressions(string pattern, string positiveMatch, string neg [Theory] // Double wildcard tests [InlineData("**/a", @"ab/a/a.cs a/taco.cs b/taco.cs b/ab/a/hat.taco", @"ab\a a b\ab\a")] + + // Issue 52 + [InlineData("**/a/**/b", @"a/a/a/b", @"a\a\a\b")] + [InlineData("**/a/**/b", @"a/a/a/a/b", @"a\a\a\a\b")] public void TestGlobExpressionsWithEmitDirectories(string pattern, string files, string matches) { var parser = new Parser(pattern);