node-ignore icon indicating copy to clipboard operation
node-ignore copied to clipboard

Need Support of pattern **folder

Open genoud opened this issue 5 years ago • 8 comments

The pattern **folder is currently not respected. This pattern is not documented in the official git documentation here https://git-scm.com/docs/gitignore but is enforced by git and is different from the pattern **/folder.

The difference

**/subfolder \n
!folder/subfolder/testFile.txt

Will ignore the folder subfolder and the negation pattern will not work, as explained in the gitignore documentation.

It is not possible to re-include a file if a parent directory of that file is excluded.

While with those lines the file folder/subfolder/testFile.txt will be re-included as the pattern **subfolder does not match the folder subfolder but any file containing the string subfolder.

**subfolder
!folder/subfolder/testFile.txt

Actual behaviour:

const ignore = require('ignore') ;
const ig = ignore().add(['**subfolder']);

let isIgnored = ig.ignores('folder/subfolder/testFile.txt') // false

const ignore = require('ignore') ;
const ig = ignore().add(['**/subfolder']);

let isIgnored = ig.ignores('folder/subfolder/testFile.txt') // true

Expected behaviour

const ignore = require('ignore') ;
const ig = ignore().add(['**subfolder']);

let isIgnored = ig.ignores('folder/subfolder/testFile.txt') // true

const ignore = require('ignore') ;
const ig = ignore().add(['**/subfolder']);

let isIgnored = ig.ignores('folder/subfolder/testFile.txt') // true

genoud avatar Sep 19 '19 19:09 genoud

https://git-scm.com/docs/gitignore does always miss rules.

I'm not sure if **folder is a rule of gitignore or only a side effect of git.

kaelzhang avatar Sep 20 '19 02:09 kaelzhang

I've hit this issue now trying to use ESLint's no-restricted-imports rule. In files where I apply this rule I'd like to forbid all imports except for **/*.i18n ones. Normally I'd configure patterns to something like:

[ '*', '!*.i18n' ]

but it won't work as for an import:

import 'src/my-feature/translations.i18n';

the star will match src so the exclusion won't override the parent. Note that import paths don't specify the file extension so there's no way to distinguish between a directory and a file - and hence no way to exclude all files except for the ones ending in i18n.

mgol avatar Nov 19 '19 00:11 mgol

@mgol Your case is not an issue of node-ignore, and might not be discussed here.

* makes src ignored as well as everything inside src and the things inside src could not be re-included if the parent directory is ignored which is a rule of .gitignore.

# You could change * to *.* because *.* will not match directories in your case.
*.*
!*.i18n

It is better to read gitignore spec carefully.

kaelzhang avatar Nov 19 '19 05:11 kaelzhang

I posted it here because ESLint uses the ignore package under the hood for the rule in question. Your workaround won't work there as imports paths may not (and often do not) include extensions so there's no easy pattern to exclude just files.

If you consider this particular feature out of scope as it's not included in Git docs, I take it that maybe ESLint just shouldn't use the ignore package for the purpose of that rule (and this should be discussed in the ESLint repo, I agree).

mgol avatar Nov 22 '19 20:11 mgol

This topic had already been discussed in the eslint repo. To support both .gitignore-style pattern and fnmatch(3), or mutually translate these 2 kinds of patterns is not even possible.

kaelzhang avatar Nov 24 '19 10:11 kaelzhang

The docs mention that trailing /** matches all files inside a directory/subdirs. They don't explicitly say that it doesn't match directories, but if that's the case, **/subfolder/** would allow files to be re-included.

jedwards1211 avatar Nov 28 '20 03:11 jedwards1211

Okay, I confirmed that in git and in node-ignore I can re-include files ignored by **/subfolder/**.

jedwards1211 avatar Nov 28 '20 03:11 jedwards1211

I'm not sure if **folder is a rule of gitignore or only a side effect of git.

It looks to me that this sentence from https://git-scm.com/docs/gitignore is relevant:

Other consecutive asterisks are considered regular asterisks and will match according to the previous rules.

So for **folder matched against a path component "folder", both of the * match nothing and the whole thing matches. Matched against "foofolder", the first * should match "foo" and the second "" (although it doesn't really matter).

In regex terms, each * should become [^\/]*, giving a total regex of /(?:^|\/)[^\/]*[^\/]*folder(?=$|\/$)/i. Instead node-ignore is producing /(?:^|\/)[^\/]*\*folder(?=$|\/$)/i. But note that may be an inefficient regex, you should probably recognize this case and collapse that into just /(?:^|\/)[^\/]*folder(?=$|\/$)/i.

anomiex avatar May 25 '21 23:05 anomiex

Could it be related to this? https://github.com/isomorphic-git/isomorphic-git/issues/1641

folder/other-folder/**/**js does not ignore folder/other-folder/dir/main.js. Double asterisks should be interpreted here as two asterisks, which match anything - see https://git-scm.com/docs/gitignore#_pattern_format

NomarCub avatar Oct 22 '22 10:10 NomarCub