Skip to content

Failing to find files on MemoryFileSystem (Windows) when running on Linux machine #1998

Open

Description

@aiurovet

I was running unit tests which are including Glob(...).matches(...), and it fails to match files when the mock filesystem is Windows-style, and the actual machine OS is POSIX-style. Even passing fileSystem.path as the context to Glob(...) does not help. When I had a closer look I found that in case of **\*a*, the class constructor appends {,/**} to the pattern. And although this should not produce any harm, I believe, it is not working as expected. I suspect, the machine's directory separator is used instead of the one for the file system. The similar issue happens to Glob(...).listFileStsemSync(...).

Activity

  1. added
    type-bugIncorrect behavior (everything from a crash to more subtle misbehavior)
    on Nov 10, 2022
  2. bartekpacia commented on May 23, 2023

    @bartekpacia

    I'm also encountering this issue.

  3. Varadraj75 commented on Aug 25, 2026

    @Varadraj75

    Hit the mirror image of this in dart-lang/native#3555: a POSIX MemoryFileSystem on a Windows host. listFileSystem throws "Can't list glob ...; it matches posix paths, but this platform uses windows paths", because it compares the glob's style against the host platform rather than the file system it's passed. Passing fileSystem.path as the context doesn't help, same as reported here.

    Net effect is that globbing a MemoryFileSystem isn't possible whenever the fake's style differs from the host, which blocks writing OS agnostic unit tests over an injected file system.

  4. Varadraj75 commented on Aug 25, 2026

    @Varadraj75

    @natebosch this is package:glob, and I'd like to fix it. Here's what I found and what I'd propose, happy to be steered.

    What's happening

    • The listing path never receives the glob's own context. ListTree is constructed in Glob._listTreeForFileSystem, so context is in scope, but list_tree.dart uses the platform globals throughout: it splits with p.context, calls p.isAbsolute, and then uses p.join and p.relative in every node listing branch, plus toPosixPath(p.context, ...) in the validator. The _ListTreeNode list and listSync methods take dir and fileSystem but no context.
    • Matching is already correct. matchAsPrefix goes through context.isAbsolute, context.absolute, context.relative and toPosixPath(context, ...), so only listing is affected.
    • Separately, listFileSystem and listFileSystemSync guard by comparing the glob's style against the platform's, rather than against the file system they were handed.

    What I'd change

    • Thread the glob's context into ListTree and its node listing methods, and use it in place of p.context, p.isAbsolute, p.join, p.relative and the toPosixPath argument. It's around 16 call sites, all mechanical.
    • Change the two guards to compare against fileSystem.path.style, which is the file system actually being listed.
    • Minor: in the ListTree factory there is a text.replaceAll('/', '\\') whose result is discarded, so it currently does nothing.

    Compatibility

    • Globs built without an explicit context keep the platform context, so their listing behavior is unchanged.
    • list() and listSync() delegate to listFileSystem with const LocalFileSystem(), and LocalFileSystem.path is a plain p.Context, so the guard is the same check as today for local listing.
    • The cases this enables currently throw StateError, so nothing that works today starts behaving differently.
    • One change worth flagging honestly: a glob with the platform context listed over a file system of a different style passes the guard today and then silently produces wrong paths, for example joining with \ while walking a POSIX file system. With the guard comparing against the file system, that would throw a clear StateError instead. I think that is better than silent misbehavior, but it is a behavior change.

    Tests

    • The suite has no MemoryFileSystem listing tests today, so I would add them as regression coverage.
    • The POSIX fake on a Windows host direction is the one I hit. For the direction reported here, a Windows style fake on a POSIX host, I will check how far it gets, since glob patterns use forward slashes and a Windows style MemoryFileSystem does not resolve a C:/ prefixed root, which looks like Differences in behaviour between real windows FS and Window-style in-memory FS #632 rather than a glob issue.

    Context for how I ran into this: dart-lang/native#3555 and dart-lang/native#3583, where native_toolchain_c wants to run its tool resolvers over a mocked file system.

    Happy to open a PR if this direction sounds right.

  5. lrhn commented on Aug 26, 2026

    @lrhn
    Member

    I can see that Glob has Glob.context and FileSystem has FileSystem.path that both gives a package:path Context.
    Their styles must agree for listFileSystem to work.

    I agree that the listFileSystem compares the glob's context to the platform context, not the filesystem's context,
    and the ListTree constructor used by listFileSystem also uses p.context directly from package:path. That's wrong. They should all use FileSystem.path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    package:globtype-bugIncorrect behavior (everything from a crash to more subtle misbehavior)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions