runtime: FileSystemGlobbing.Matcher is not matching '**/*'

Description

In dotnet/format we use the FileSystemGlobbing.Matcher to allow users the ability to filter the files that are being formatted. We started getting reports that dotnet/format was not formatting the expected files. While troubleshooting it became apparent that the Matcher was no longer matching paths as expected.

Configuration

This simple console app tries to match different path strings using the “Any files in any subdirectory” pattern.

TestConsole.csproj:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.FileSystemGlobbing" Version="5.0.0" />
  </ItemGroup>
</Project>

Program.cs:

using System;
using Microsoft.Extensions.FileSystemGlobbing;

class Program
{
    static void Main()
    {
        var fileMatcher = new Matcher();
        fileMatcher.AddInclude("**/*");

        var fakeWindowsPath = "C:\\This\\is\\a\\nested\\windows-like\\path\\somefile.cs";
        Console.WriteLine($"**/* matches {fakeWindowsPath}: {fileMatcher.Match(fakeWindowsPath).HasMatches}");

        var fakeUnixPath = "/This/is/a/nested/unix-like/path/somefile.cs";
        Console.WriteLine($"**/* matches {fakeUnixPath}: {fileMatcher.Match(fakeUnixPath).HasMatches}");
    }
}

Output running on MacOS:

**/* matches C:\This\is\a\nested\windows-like\path\somefile.cs: True **/* matches /This/is/a/nested/unix-like/path/somefile.cs: False

Output running on Windows:

**/* matches C:\This\is\a\nested\windows-like\path\somefile.cs: False **/* matches /This/is/a/nested/unix-like/path/somefile.cs: False

Regression?

This had worked at least as late as .NET 5 Preview 7.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 16 (16 by maintainers)

Most upvoted comments

I also found that there is a bug if you use a root directory that end with a separator, such as C:\. https://github.com/dotnet/runtime/blob/65d42f04ff696d4fe8b6f1526807537e2326b187/src/libraries/Microsoft.Extensions.FileSystemGlobbing/src/InMemoryDirectoryInfo.cs#L122-L123

Files won’t match rootDir in said case because of the second condition. That can be fixed by avoiding the filePath.IndexOf(Path.DirectorySeparatorChar, rootDir.Length) != rootDir.Length check when rootDir ends with separator.