-
Notifications
You must be signed in to change notification settings - Fork 8.1k
Optimize Get-ChildItem -Recurse -Name #12834
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
c544db4
Introduce new file enumerator for Get-ChildItem -Recorse -Name
iSazonov 10e4c32
Process errors while enumerating
iSazonov 0f03d7d
Add more tests
iSazonov f5515f4
Fix MacOS tests
iSazonov 7d4724a
Test 1
iSazonov 003f101
Test 2
iSazonov aaf5581
Revert depth to old code path
iSazonov 61e9eca
Fix compile
iSazonov 595a8d9
Fix compile 2
iSazonov 0de6cd7
Fix style issues
iSazonov e76af74
Fix style issues 2
iSazonov 2d6c4dd
Fix style issues 3
iSazonov c655a63
Fix style issues 4
iSazonov bb83259
Add depth support
iSazonov 14a71e9
Fix style issues 5
iSazonov File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
107 changes: 107 additions & 0 deletions
107
src/System.Management.Automation/namespaces/FileSystemProviderEnumerable.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,107 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
|
|
||
| #nullable enable | ||
|
|
||
| using System; | ||
| using System.Collections; | ||
| using System.Collections.Generic; | ||
| using System.IO; | ||
| using System.IO.Enumeration; | ||
| using System.Threading; | ||
|
|
||
| namespace Microsoft.PowerShell.Commands | ||
| { | ||
| /// <summary> | ||
| /// Enumerable that allows utilizing custom filter predicates and tranform delegates. | ||
| /// </summary> | ||
| /// <typeparam name="TResult">The type of a result.</typeparam> | ||
| internal class FileSystemProviderEnumerable<TResult> : IEnumerable<TResult> | ||
| { | ||
| private readonly FindTransform _transform; | ||
| private readonly EnumerationOptions _options; | ||
| private readonly string _directory; | ||
| private DelegateEnumerator? _enumerator; | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="FileSystemProviderEnumerable{TResult}"/> class. | ||
| /// The class allows utilizing custom filter predicates and tranform delegates. | ||
| /// </summary> | ||
| /// <param name="directory">The path of the starting directory.</param> | ||
| /// <param name="transform">The delegate to transform internal data to a result.</param> | ||
| /// <param name="options">The enumeration options.</param> | ||
| internal FileSystemProviderEnumerable(string directory, FindTransform transform, EnumerationOptions? options = null) | ||
| { | ||
| _directory = directory ?? throw new ArgumentNullException(nameof(directory)); | ||
| _transform = transform ?? throw new ArgumentNullException(nameof(transform)); | ||
| _options = options ?? new EnumerationOptions(); | ||
|
|
||
| // We need to create the enumerator up front to ensure that we throw I/O exceptions for | ||
| // the root directory on creation of the enumerable. | ||
| _enumerator = new DelegateEnumerator(this); | ||
| } | ||
|
|
||
| internal FindPredicate? ShouldIncludePredicate { get; set; } | ||
|
|
||
| internal FindPredicate? ShouldRecursePredicate { get; set; } | ||
|
|
||
| internal ContinueOnErrorPredicate? ShouldContinueOnErrorPredicate { get; set; } | ||
|
|
||
| public IEnumerator<TResult> GetEnumerator() | ||
| { | ||
| return Interlocked.Exchange(ref _enumerator, null) ?? new DelegateEnumerator(this); | ||
| } | ||
|
|
||
| IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); | ||
|
|
||
| /// <summary> | ||
| /// Delegate for filtering out find results. | ||
| /// </summary> | ||
| /// <param name="entry">A lower level view of System.IO.FileSystemInfo for fitering.</param> | ||
| /// <returns>If true include the entry to result.</returns> | ||
| internal delegate bool FindPredicate(ref FileSystemEntry entry); | ||
|
|
||
| /// <summary> | ||
| /// Delegate for calling whenever the end of a directory is reached. | ||
| /// </summary> | ||
| /// <param name="directory">The path of the directory that finished.</param> | ||
| internal delegate void OnDirectoryFinishedDelegate(ReadOnlySpan<char> directory); | ||
|
|
||
| /// <summary> | ||
| /// Delegate for calling whenever on I/O error. | ||
| /// </summary> | ||
| /// <param name="error">I/O error code.</param> | ||
| /// <returns>If true continue the enumeration. If false throw.</returns> | ||
| internal delegate bool ContinueOnErrorPredicate(int error); | ||
|
|
||
| /// <summary> | ||
| /// Delegate for transforming raw find data into a result. | ||
| /// </summary> | ||
| /// <param name="entry">A lower level view of System.IO.FileSystemInfo for transforming to TResult.</param> | ||
| /// <returns>Result of the transformation of TResult type.</returns> | ||
| internal delegate TResult FindTransform(ref FileSystemEntry entry); | ||
|
|
||
| private sealed class DelegateEnumerator : FileSystemEnumerator<TResult> | ||
| { | ||
| private readonly FileSystemProviderEnumerable<TResult> _enumerable; | ||
|
|
||
| internal DelegateEnumerator(FileSystemProviderEnumerable<TResult> enumerable) | ||
| : base(enumerable._directory, enumerable._options) | ||
| { | ||
| _enumerable = enumerable; | ||
| } | ||
|
|
||
| protected override TResult TransformEntry(ref FileSystemEntry entry) => _enumerable._transform(ref entry); | ||
|
|
||
| protected override bool ShouldRecurseIntoEntry(ref FileSystemEntry entry) | ||
| => _enumerable.ShouldRecursePredicate?.Invoke(ref entry) ?? true; | ||
|
|
||
| protected override bool ShouldIncludeEntry(ref FileSystemEntry entry) | ||
| => _enumerable.ShouldIncludePredicate?.Invoke(ref entry) ?? true; | ||
|
|
||
| protected override bool ContinueOnError(int error) | ||
| //// Here _enumerable can be still null because base constructor can throw 'access denied' before we assign _enumerable. | ||
| => _enumerable?.ShouldContinueOnErrorPredicate?.Invoke(error) ?? false; | ||
| } | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.