From 7816450e2fbd3c1cea3a31ab854411d32e197ddd Mon Sep 17 00:00:00 2001 From: rameel Date: Thu, 31 Jul 2025 23:50:26 +0500 Subject: [PATCH] Skip enumeration entirely for excluded directories --- .../GlobbingDirectory.cs | 39 ++++++++------ .../GlobingFileSystemTests.cs | 51 +++++++++++++++++++ 2 files changed, 75 insertions(+), 15 deletions(-) diff --git a/src/Ramstack.FileSystem.Globbing/GlobbingDirectory.cs b/src/Ramstack.FileSystem.Globbing/GlobbingDirectory.cs index 20df520..2022fa4 100644 --- a/src/Ramstack.FileSystem.Globbing/GlobbingDirectory.cs +++ b/src/Ramstack.FileSystem.Globbing/GlobbingDirectory.cs @@ -56,18 +56,21 @@ protected override ValueTask DeleteCoreAsync(CancellationToken cancellationToken /// protected override async IAsyncEnumerable GetFileNodesCoreAsync([EnumeratorCancellation] CancellationToken cancellationToken) { - await foreach (var node in _directory.GetFileNodesAsync(cancellationToken).ConfigureAwait(false)) + if (_included) { - if (!_fs.IsExcluded(node.FullName)) + await foreach (var node in _directory.GetFileNodesAsync(cancellationToken).ConfigureAwait(false)) { - if (node is VirtualFile file) - { - if (_fs.IsIncluded(node.FullName)) - yield return new GlobbingFile(_fs, file, true); - } - else + if (!_fs.IsExcluded(node.FullName)) { - yield return new GlobbingDirectory(_fs, (VirtualDirectory)node, true); + if (node is VirtualFile file) + { + if (_fs.IsIncluded(node.FullName)) + yield return new GlobbingFile(_fs, file, true); + } + else + { + yield return new GlobbingDirectory(_fs, (VirtualDirectory)node, true); + } } } } @@ -76,20 +79,26 @@ protected override async IAsyncEnumerable GetFileNodesCoreAsync([En /// protected override async IAsyncEnumerable GetFilesCoreAsync([EnumeratorCancellation] CancellationToken cancellationToken) { - await foreach (var file in _directory.GetFilesAsync(cancellationToken).ConfigureAwait(false)) + if (_included) { - if (_fs.IsFileIncluded(file.FullName)) - yield return new GlobbingFile(_fs, file, true); + await foreach (var file in _directory.GetFilesAsync(cancellationToken).ConfigureAwait(false)) + { + if (_fs.IsFileIncluded(file.FullName)) + yield return new GlobbingFile(_fs, file, true); + } } } /// protected override async IAsyncEnumerable GetDirectoriesCoreAsync([EnumeratorCancellation] CancellationToken cancellationToken) { - await foreach (var directory in _directory.GetDirectoriesAsync(cancellationToken).ConfigureAwait(false)) + if (_included) { - if (_fs.IsDirectoryIncluded(directory.FullName)) - yield return new GlobbingDirectory(_fs, directory, true); + await foreach (var directory in _directory.GetDirectoriesAsync(cancellationToken).ConfigureAwait(false)) + { + if (_fs.IsDirectoryIncluded(directory.FullName)) + yield return new GlobbingDirectory(_fs, directory, true); + } } } } diff --git a/tests/Ramstack.FileSystem.Globbing.Tests/GlobingFileSystemTests.cs b/tests/Ramstack.FileSystem.Globbing.Tests/GlobingFileSystemTests.cs index 3d4f5cb..b12855d 100644 --- a/tests/Ramstack.FileSystem.Globbing.Tests/GlobingFileSystemTests.cs +++ b/tests/Ramstack.FileSystem.Globbing.Tests/GlobingFileSystemTests.cs @@ -29,6 +29,57 @@ public void Setup() public void Cleanup() => _storage.Dispose(); + [Test] + public async Task ExcludedDirectory_HasNoFileNodes() + { + using var storage = new TempFileStorage(); + using var fs = new GlobbingFileSystem(new PhysicalFileSystem(storage.Root), "**", exclude: "/project/src/**"); + + var directories = new[] + { + "/project/src", + "/project/src/App", + "/project/src/Modules", + "/project/src/Modules/Module1", + "/project/src/Modules/Module1/Submodule", + "/project/src/Modules/Module2" + }; + + foreach (var path in directories) + { + var directory = fs.GetDirectory(path); + + Assert.That( + await directory.ExistsAsync(), + Is.False); + + Assert.That( + await directory.GetFileNodesAsync("**").CountAsync(), + Is.Zero); + } + + var files = new[] + { + "/project/src/App/App.csproj", + "/project/src/App/Program.cs", + "/project/src/App/Utils.cs", + "/project/src/Modules/Module1/Module1.cs", + "/project/src/Modules/Module1/Module1.csproj", + "/project/src/Modules/Module1/Submodule/Submodule1.cs", + "/project/src/Modules/Module1/Submodule/Submodule2.cs", + "/project/src/Modules/Module1/Submodule/Submodule.csproj", + "/project/src/Modules/Module2/Module2.cs", + "/project/src/Modules/Module2/Module2.csproj", + "/project/src/App.sln" + }; + + foreach (var path in files) + { + var file = fs.GetFile(path); + Assert.That(await file.ExistsAsync(), Is.False); + } + } + protected override IVirtualFileSystem GetFileSystem() { var fs = new PhysicalFileSystem(_storage.Root);