Skip to content

Conversation

webpro
Copy link

@webpro webpro commented Oct 31, 2024

Making the case for negated ignore patterns.

Glob libraries like fast-glob, node-glob and tinyglobby use the ignore option to exclude matches from the results. Yet there's also a case to be made to un-ignore such results. For instance, when .gitignore files should be taken into account.

Let's say we have the following

.
├── index.js
└── .yarn
    ├── plugins
    │   └── my-plugin.js
    └── index.js

Or just

index.js
.yarn/plugins/my-plugin.js
.yarn/index.js

Projects may have files like .gitignore (or other ignore files) like so:

**/.yarn/*
!.yarn/releases
!.yarn/plugins
!.yarn/sdks
!.yarn/versions

The semantics of .gitignore items differ from glob patterns, but let's ignore that here, not picomatch's problem.

What downstream packages might want to do is take such patterns into account like this:

picomatch("**/*.js", {
  ignore: ["**/.yarn/**", "!.yarn/plugins/**"]
});

There's currently just no feasible way to make the negated items from .gitignore slip through.

So that's where this PR comes in. We can filter out the negated patterns and:

const unignores = [".yarn/plugins/**"];

picomatch("**/*.js", {
  ignore: ["**/.yarn/**"],
  onUnignore: ({input}) => isMatch(input, unignores) && picomatch.constants.UNIGNORE;
});

By returning the token, the item is un-ignored and slips through. The implementation of onUnignore should be optimized, this is just an example to illustrate the idea.

A solution like this with a token is guaranteed to be a non-breaking change. An alternative I thought of first would be to simply return true which would probably also not be a breaking change, but it's not guaranteed.

Relevant issues:

Part of why globby got so popular is because of it's support for .gitignore files, but the implementation is rather tedious and slow. Solving this in picomatch directly would be a major advantage in terms of both simplicity and performance.

I think the implementation is relatively clean and low-impact while non-breaking. Needless to say I'm open to suggestion to improve if you have any!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant