Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 29 additions & 6 deletions Ramstack.Globbing/Internal/PathHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,17 @@ internal static class PathHelper
/// </summary>
/// <param name="path">The path to match for a match.</param>
/// <param name="patterns">An array of patterns to match against the path.</param>
/// <param name="flags">The matching options to use.</param>
/// <param name="flags">The matching options to use.
/// This parameter must be explicitly set to either <see cref="MatchFlags.Windows"/> or <see cref="MatchFlags.Unix"/>.
/// <see cref="MatchFlags.Auto"/> is not allowed and will result in an assertion failure.</param>
/// <returns>
/// <see langword="true" /> if the path matches any of the patterns;
/// otherwise, <see langword="false" />.
/// </returns>
public static bool IsMatch(ReadOnlySpan<char> path, string[] patterns, MatchFlags flags)
{
Debug.Assert(flags != MatchFlags.Auto);

foreach (var pattern in patterns)
if (Matcher.IsMatch(path, pattern, flags))
return true;
Expand All @@ -40,13 +44,17 @@ public static bool IsMatch(ReadOnlySpan<char> path, string[] patterns, MatchFlag
/// </summary>
/// <param name="path">The path to be partially matched.</param>
/// <param name="patterns">An array of patterns to match against the path.</param>
/// <param name="flags">The matching options to use.</param>
/// <param name="flags">The matching options to use.
/// This parameter must be explicitly set to either <see cref="MatchFlags.Windows"/> or <see cref="MatchFlags.Unix"/>.
/// <see cref="MatchFlags.Auto"/> is not allowed and will result in an assertion failure.</param>
/// <returns>
/// <see langword="true" /> if the path partially matches any of the patterns;
/// otherwise, <see langword="false" />.
/// </returns>
public static bool IsPartialMatch(ReadOnlySpan<char> path, string[] patterns, MatchFlags flags)
{
Debug.Assert(flags != MatchFlags.Auto);

var count = CountPathSegments(path, flags);

foreach (var pattern in patterns)
Expand All @@ -60,12 +68,16 @@ public static bool IsPartialMatch(ReadOnlySpan<char> path, string[] patterns, Ma
/// Counts the number of segments in the specified path.
/// </summary>
/// <param name="path">The path to count segments for.</param>
/// <param name="flags">The flags indicating the type of path separators to match.</param>
/// <param name="flags">The flags indicating the type of path separators to match.
/// This parameter must be explicitly set to either <see cref="MatchFlags.Windows"/> or <see cref="MatchFlags.Unix"/>.
/// <see cref="MatchFlags.Auto"/> is not allowed and will result in an assertion failure.</param>
/// <returns>
/// The number of segments in the path.
/// </returns>
public static int CountPathSegments(scoped ReadOnlySpan<char> path, MatchFlags flags)
{
Debug.Assert(flags != MatchFlags.Auto);

var count = 0;
var iterator = new PathSegmentIterator();
ref var s = ref Unsafe.AsRef(in MemoryMarshal.GetReference(path));
Expand All @@ -92,13 +104,16 @@ public static int CountPathSegments(scoped ReadOnlySpan<char> path, MatchFlags f
/// Returns a partial pattern from the specified pattern string based on the specified depth.
/// </summary>
/// <param name="pattern">The pattern string to extract from.</param>
/// <param name="flags">The flags indicating the type of path separators to match.</param>
/// <param name="flags">The flags indicating the type of path separators to match.
/// This parameter must be explicitly set to either <see cref="MatchFlags.Windows"/> or <see cref="MatchFlags.Unix"/>.
/// <see cref="MatchFlags.Auto"/> is not allowed and will result in an assertion failure.</param>
/// <param name="depth">The depth level to extract the partial pattern up to.</param>
/// <returns>
/// A <see cref="ReadOnlySpan{T}"/> representing the partial pattern.
/// </returns>
public static ReadOnlySpan<char> GetPartialPattern(string pattern, MatchFlags flags, int depth)
{
Debug.Assert(flags != MatchFlags.Auto);
Debug.Assert(depth >= 1);

if (depth < 1)
Expand Down Expand Up @@ -227,12 +242,16 @@ static void ConvertPathToPosixStyleImpl(ref char p, nint length)
/// <summary>
/// Creates a 256-bit bitmask that allows escaping characters based on the specified flags.
/// </summary>
/// <param name="flags">The flags indicating the type of path separators to match.</param>
/// <param name="flags">The flags indicating the type of path separators to match.
/// This parameter must be explicitly set to either <see cref="MatchFlags.Windows"/> or <see cref="MatchFlags.Unix"/>.
/// <see cref="MatchFlags.Auto"/> is not allowed and will result in an assertion failure.</param>
/// <returns>
/// A 256-bit bitmask for escaping characters.
/// </returns>
private static Vector256<ushort> CreateBackslash256Bitmask(MatchFlags flags)
{
Debug.Assert(flags != MatchFlags.Auto);

var mask = Vector256<ushort>.Zero;
if (flags == MatchFlags.Windows)
mask = Vector256<ushort>.AllBitsSet;
Expand All @@ -243,12 +262,16 @@ private static Vector256<ushort> CreateBackslash256Bitmask(MatchFlags flags)
/// <summary>
/// Creates a 128-bit bitmask that allows escaping characters based on the specified flags.
/// </summary>
/// <param name="flags">The flags indicating the type of path separators to match.</param>
/// <param name="flags">The flags indicating the type of path separators to match.
/// This parameter must be explicitly set to either <see cref="MatchFlags.Windows"/> or <see cref="MatchFlags.Unix"/>.
/// <see cref="MatchFlags.Auto"/> is not allowed and will result in an assertion failure.</param>
/// <returns>
/// A 128-bit bitmask for escaping characters.
/// </returns>
private static Vector128<ushort> CreateBackslash128Bitmask(MatchFlags flags)
{
Debug.Assert(flags != MatchFlags.Auto);

var mask = Vector128<ushort>.Zero;
if (flags == MatchFlags.Windows)
mask = Vector128<ushort>.AllBitsSet;
Expand Down
6 changes: 3 additions & 3 deletions Ramstack.Globbing/Traversal/DirectoryInfoExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -753,7 +753,7 @@ public static IEnumerable<FileSystemInfo> EnumerateFileSystemInfos(this Director

private static IEnumerable<FileInfo> EnumerateFiles(string path, string[] patterns, string[] excludes, MatchFlags flags, SearchTarget target, EnumerationOptions options)
{
flags = Files.AdjustMatchFlags(flags);
flags = Files.ResolveMatchFlags(flags);

return new FileSystemEnumerable<FileInfo>(path, (ref entry) => (FileInfo)entry.ToFileSystemInfo(), options)
{
Expand All @@ -764,7 +764,7 @@ private static IEnumerable<FileInfo> EnumerateFiles(string path, string[] patter

private static IEnumerable<DirectoryInfo> EnumerateDirectories(string path, string[] patterns, string[] excludes, MatchFlags flags, SearchTarget target, EnumerationOptions options)
{
flags = Files.AdjustMatchFlags(flags);
flags = Files.ResolveMatchFlags(flags);

return new FileSystemEnumerable<DirectoryInfo>(path, (ref entry) => (DirectoryInfo)entry.ToFileSystemInfo(), options)
{
Expand All @@ -775,7 +775,7 @@ private static IEnumerable<DirectoryInfo> EnumerateDirectories(string path, stri

private static IEnumerable<FileSystemInfo> EnumerateInfos(string path, string[] patterns, string[] excludes, MatchFlags flags, SearchTarget target, EnumerationOptions options)
{
flags = Files.AdjustMatchFlags(flags);
flags = Files.ResolveMatchFlags(flags);

return new FileSystemEnumerable<FileSystemInfo>(path, (ref entry) => entry.ToFileSystemInfo(), options)
{
Expand Down
7 changes: 4 additions & 3 deletions Ramstack.Globbing/Traversal/FileTreeAsyncEnumerable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ private async IAsyncEnumerable<TResult> EnumerateAsync(CancellationTokenSource?
{
try
{
var flags = Files.ResolveMatchFlags(Flags);
var chars = ArrayPool<char>.Shared.Rent(FileTreeEnumerable<TEntry, TResult>.DefaultBufferCapacity);

var queue = new Queue<(TEntry Directory, string Path)>();
Expand All @@ -98,15 +99,15 @@ private async IAsyncEnumerable<TResult> EnumerateAsync(CancellationTokenSource?
var name = FileNameSelector(entry);
var fullName = FileTreeHelper.GetFullName(ref chars, e.Path, name);

if (PathHelper.IsMatch(fullName, Excludes, Flags))
if (PathHelper.IsMatch(fullName, Excludes, flags))
continue;

if (ShouldRecursePredicate == null || ShouldRecursePredicate(entry))
if (PathHelper.IsPartialMatch(fullName, Patterns, Flags))
if (PathHelper.IsPartialMatch(fullName, Patterns, flags))
queue.Enqueue((entry, fullName.ToString()));

if (ShouldIncludePredicate == null || ShouldIncludePredicate(entry))
if (PathHelper.IsMatch(fullName, Patterns, Flags))
if (PathHelper.IsMatch(fullName, Patterns, flags))
yield return ResultSelector(entry);
}
}
Expand Down
8 changes: 4 additions & 4 deletions Ramstack.Globbing/Traversal/FileTreeEnumerable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ IEnumerator IEnumerable.GetEnumerator() =>

private IEnumerable<TResult> Enumerate()
{
var flags = Files.ResolveMatchFlags(Flags);
var chars = ArrayPool<char>.Shared.Rent(DefaultBufferCapacity);

var queue = new Queue<(TEntry Directory, string Path)>();
queue.Enqueue((_directory, ""));

Expand All @@ -89,15 +89,15 @@ private IEnumerable<TResult> Enumerate()
var name = FileNameSelector(entry);
var fullName = FileTreeHelper.GetFullName(ref chars, e.Path, name);

if (PathHelper.IsMatch(fullName, Excludes, Flags))
if (PathHelper.IsMatch(fullName, Excludes, flags))
continue;

if (ShouldRecursePredicate == null || ShouldRecursePredicate(entry))
if (PathHelper.IsPartialMatch(fullName, Patterns, Flags))
if (PathHelper.IsPartialMatch(fullName, Patterns, flags))
queue.Enqueue((entry, fullName.ToString()));

if (ShouldIncludePredicate == null || ShouldIncludePredicate(entry))
if (PathHelper.IsMatch(fullName, Patterns, Flags))
if (PathHelper.IsMatch(fullName, Patterns, flags))
yield return ResultSelector(entry);
}
}
Expand Down
25 changes: 18 additions & 7 deletions Ramstack.Globbing/Traversal/Files.Utilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,18 @@ partial class Files
/// <param name="entry">A file system entry reference.</param>
/// <param name="patterns">An array of glob patterns to match against the names of files.</param>
/// <param name="excludes">Optional array of glob patterns to exclude files.</param>
/// <param name="flags">The matching options to use.</param>
/// <param name="flags">The matching options to use.
/// This parameter must be explicitly set to either <see cref="MatchFlags.Windows"/> or <see cref="MatchFlags.Unix"/>.
/// <see cref="MatchFlags.Auto"/> is not allowed and will result in an assertion failure.</param>
/// <param name="target">The search target.</param>
/// <returns>
/// <see langword="true" /> if the specified file system entry should be included in the results;
/// otherwise, <see langword="false" />.
/// </returns>
internal static bool ShouldInclude(ref FileSystemEntry entry, string[] patterns, string[] excludes, MatchFlags flags, SearchTarget target)
{
Debug.Assert(flags != MatchFlags.Auto);

char[]? rented = null;

var current = entry.IsDirectory
Expand Down Expand Up @@ -60,13 +64,17 @@ internal static bool ShouldInclude(ref FileSystemEntry entry, string[] patterns,
/// <param name="entry">A file system entry reference.</param>
/// <param name="patterns">An array of glob patterns to match against the names of files.</param>
/// <param name="excludes">Optional array of glob patterns to exclude files.</param>
/// <param name="flags">The matching options to use. Default is <see cref="MatchFlags.Auto"/>.</param>
/// <param name="flags">The matching options to use.
/// This parameter must be explicitly set to either <see cref="MatchFlags.Windows"/> or <see cref="MatchFlags.Unix"/>.
/// <see cref="MatchFlags.Auto"/> is not allowed and will result in an assertion failure.</param>
/// <returns>
/// <see langword="true" /> if the specified directory entry should be recursed into;
/// otherwise, <see langword="false" />.
/// </returns>
internal static bool ShouldRecurse(ref FileSystemEntry entry, string[] patterns, string[] excludes, MatchFlags flags)
{
Debug.Assert(flags != MatchFlags.Auto);

char[]? rented = null;

var length = GetRelativePathLength(ref entry);
Expand All @@ -88,15 +96,16 @@ internal static bool ShouldRecurse(ref FileSystemEntry entry, string[] patterns,
}

/// <summary>
/// Adjusts the provided match flags based on the current operating system's directory separator character.
/// Resolves the provided match flags by converting <see cref="MatchFlags.Auto"/>
/// to a concrete value based on the current operating system's directory separator convention.
/// </summary>
/// <param name="flags">The initial match flags to resolve.</param>
/// <returns>
/// The adjusted match flags. If the initial flags are <see cref="MatchFlags.Auto"/>, the method returns
/// <see cref="MatchFlags.Windows"/> for Windows systems and <see cref="MatchFlags.Unix"/> for Unix-like systems;
/// otherwise, it returns the provided flags.
/// The resolved match flags. If the input is <see cref="MatchFlags.Auto"/>, returns
/// <see cref="MatchFlags.Windows"/> on Windows systems and <see cref="MatchFlags.Unix"/>
/// on Unix-like systems. Otherwise, returns the original flags unchanged.
/// </returns>
internal static MatchFlags AdjustMatchFlags(MatchFlags flags)
internal static MatchFlags ResolveMatchFlags(MatchFlags flags)
{
if (flags == MatchFlags.Auto)
return Path.DirectorySeparatorChar == '\\'
Expand Down Expand Up @@ -144,6 +153,8 @@ private static int GetRelativePathLength(ref FileSystemEntry entry)

private static void UpdatePathSeparators(scoped Span<char> path, MatchFlags flags)
{
Debug.Assert(flags != MatchFlags.Auto);

// To enable escaping in Windows systems, we convert backslashes (\) to forward slashes (/).
// This is safe because in Windows, backslashes are only used as path separators.
// Otherwise, the backslash (\) in the path will be treated as an escape character,
Expand Down
2 changes: 1 addition & 1 deletion Ramstack.Globbing/Traversal/Files.cs
Original file line number Diff line number Diff line change
Expand Up @@ -753,7 +753,7 @@ public static IEnumerable<string> EnumerateFileSystemEntries(string path, string

private static IEnumerable<string> EnumerateEntries(string path, string[] patterns, string[] excludes, MatchFlags flags, SearchTarget target, EnumerationOptions options)
{
flags = AdjustMatchFlags(flags);
flags = ResolveMatchFlags(flags);

return new FileSystemEnumerable<string>(Path.GetFullPath(path), (ref entry) => entry.ToFullPath(), options)
{
Expand Down
Loading