fix: behavior of global ignores#126
Conversation
| it('should return false when file has the same name as a directory that is ignored by a pattern that ends with `/`', () => { | ||
| configs = new ConfigArray([ | ||
| { | ||
| files: ['**/foo'] | ||
| }, | ||
| { | ||
| ignores: [ | ||
| 'foo/' | ||
| ] | ||
| } | ||
| ], { | ||
| basePath | ||
| }); | ||
|
|
||
| configs.normalizeSync(); | ||
|
|
||
| expect(configs.isFileIgnored(path.join(basePath, 'foo'))).to.be.false; | ||
| }); | ||
|
|
||
| it('should return false when file is in the parent directory of directories that are ignored by a pattern that ends with `/`', () => { | ||
| configs = new ConfigArray([ | ||
| { | ||
| files: ['**/*.js'] | ||
| }, | ||
| { | ||
| ignores: [ | ||
| 'foo/*/' | ||
| ] | ||
| } | ||
| ], { | ||
| basePath | ||
| }); | ||
|
|
||
| configs.normalizeSync(); | ||
|
|
||
| expect(configs.isFileIgnored(path.join(basePath, 'foo/a.js'))).to.be.false; | ||
| }); |
There was a problem hiding this comment.
These two tests were failing before this change (the files were considered ignored).
| it('should return true when file is in a directory that is ignored by a pattern that ends with `/`', () => { | ||
| configs = new ConfigArray([ | ||
| { | ||
| files: ['**/*.js'] | ||
| }, | ||
| { | ||
| ignores: [ | ||
| 'foo/' | ||
| ] | ||
| } | ||
| ], { | ||
| basePath | ||
| }); | ||
|
|
||
| configs.normalizeSync(); | ||
|
|
||
| expect(configs.isFileIgnored(path.join(basePath, 'foo/a.js'))).to.be.true; | ||
| }); | ||
|
|
||
| it('should return true when file is in a directory that is ignored by a pattern that does not end with `/`', () => { | ||
| configs = new ConfigArray([ | ||
| { | ||
| files: ['**/*.js'] | ||
| }, | ||
| { | ||
| ignores: [ | ||
| 'foo' | ||
| ] | ||
| } | ||
| ], { | ||
| basePath | ||
| }); | ||
|
|
||
| configs.normalizeSync(); | ||
|
|
||
| expect(configs.isFileIgnored(path.join(basePath, 'foo/a.js'))).to.be.true; | ||
| }); | ||
|
|
||
| it('should return false when file is in a directory that is ignored and then unignord by pattern that end with `/`', () => { | ||
| configs = new ConfigArray([ | ||
| { | ||
| files: ['**/*.js'] | ||
| }, | ||
| { | ||
| ignores: [ | ||
| 'foo/', | ||
| '!foo/' | ||
| ] | ||
| } | ||
| ], { | ||
| basePath | ||
| }); | ||
|
|
||
| configs.normalizeSync(); | ||
|
|
||
| expect(configs.isFileIgnored(path.join(basePath, 'foo/a.js'))).to.be.false; | ||
| }); |
There was a problem hiding this comment.
These three tests were already passing before the change. I added them just to verify that the cases the transformations were targeting still work as intended when the transformations are removed.
tests/config-array.test.js
Outdated
| it('should return true when file is in a directory that is ignored along its files by pattern that ends with `/**` and than unignored by pattern that ends with `/`', () => { | ||
| configs = new ConfigArray([ | ||
| { | ||
| files: ['**/*.js'] | ||
| }, | ||
| { | ||
| ignores: [ | ||
| 'foo/**', | ||
|
|
||
| // only the directory is unignored, files are not | ||
| '!foo/' | ||
| ] | ||
| } | ||
| ], { | ||
| basePath | ||
| }); | ||
|
|
||
| configs.normalizeSync(); | ||
|
|
||
| expect(configs.isFileIgnored(path.join(basePath, 'foo/a.js'))).to.be.true; | ||
| }); | ||
|
|
||
| it('should return true when file is in a directory that is ignored along its files by pattern that ends with `/**` and then unignored by pattern that does not ends with `/`', () => { | ||
| configs = new ConfigArray([ | ||
| { | ||
| files: ['**/*.js'] | ||
| }, | ||
| { | ||
| ignores: [ | ||
| 'foo/**', | ||
|
|
||
| // only the directory is unignored, files are not | ||
| '!foo' | ||
| ] | ||
| } | ||
| ], { | ||
| basePath | ||
| }); | ||
|
|
||
| configs.normalizeSync(); | ||
|
|
||
| expect(configs.isFileIgnored(path.join(basePath, 'foo/a.js'))).to.be.true; | ||
| }); |
There was a problem hiding this comment.
These two tests were failing before this change (the files were considered not ignored).
| it('should return false when file is in a directory that is ignored along its files by pattern that ends with `/**` and then unignored along its files by pattern that ends with `/**`', () => { | ||
| configs = new ConfigArray([ | ||
| { | ||
| files: ['**/*.js'] | ||
| }, | ||
| { | ||
| ignores: [ | ||
| 'foo/**', | ||
|
|
||
| // both the directory and the files are unignored | ||
| '!foo/**' | ||
| ] | ||
| } | ||
| ], { | ||
| basePath | ||
| }); | ||
|
|
||
| configs.normalizeSync(); | ||
|
|
||
| expect(configs.isFileIgnored(path.join(basePath, 'foo/a.js'))).to.be.false; | ||
| }); |
There was a problem hiding this comment.
This one was already passing before the change.
| it('should return true when file is ignored by a pattern and there are unignore patterns that target files of a directory with the same name', () => { | ||
| configs = new ConfigArray([ | ||
| { | ||
| files: ['**/foo'] | ||
| }, | ||
| { | ||
| ignores: [ | ||
| 'foo', | ||
| '!foo/*', | ||
| '!foo/**' | ||
| ] | ||
| } | ||
| ], { | ||
| basePath | ||
| }); | ||
|
|
||
| configs.normalizeSync(); | ||
|
|
||
| expect(configs.isFileIgnored(path.join(basePath, 'foo'))).to.be.true; | ||
| }); | ||
|
|
||
| it('should return true when file is in a directory that is ignored even if an unignore pattern that ends with `/*` matches the file', () => { | ||
| configs = new ConfigArray([ | ||
| { | ||
| files: ['**/*.js'] | ||
| }, | ||
| { | ||
| ignores: [ | ||
| 'foo', | ||
| '!foo/*' | ||
| ] | ||
| } | ||
| ], { | ||
| basePath | ||
| }); | ||
|
|
||
| configs.normalizeSync(); | ||
|
|
||
| expect(configs.isFileIgnored(path.join(basePath, 'foo/a.js'))).to.be.true; | ||
| }); | ||
|
|
||
| // https://github.com/eslint/eslint/issues/17964#issuecomment-1879840650 | ||
| it('should return true for all files ignored in a directory tree except for explicitly unignored ones', () => { | ||
| configs = new ConfigArray([ | ||
| { | ||
| files: ['**/*.js'] | ||
| }, | ||
| { | ||
| ignores: [ | ||
|
|
||
| // ignore all files and directories | ||
| 'tests/format/**/*', | ||
|
|
||
| // unignore all directories | ||
| '!tests/format/**/*/', | ||
|
|
||
| // unignore specific files | ||
| '!tests/format/**/jsfmt.spec.js' | ||
| ] | ||
| } | ||
| ], { | ||
| basePath | ||
| }); | ||
|
|
||
| configs.normalizeSync(); | ||
|
|
||
| expect(configs.isFileIgnored(path.join(basePath, 'tests/format/foo.js'))).to.be.true; | ||
| expect(configs.isFileIgnored(path.join(basePath, 'tests/format/jsfmt.spec.js'))).to.be.false; | ||
| expect(configs.isFileIgnored(path.join(basePath, 'tests/format/subdir/foo.js'))).to.be.true; | ||
| expect(configs.isFileIgnored(path.join(basePath, 'tests/format/subdir/jsfmt.spec.js'))).to.be.false; | ||
| }); |
There was a problem hiding this comment.
These three tests were failing before this change (the files that should have been ignored were considered not ignored).
| it('should return false when a directory is later negated with **', () => { | ||
| configs = new ConfigArray([ | ||
| { | ||
| files: ['**/*.js'] | ||
| }, | ||
| { | ||
| ignores: [ | ||
| '**/node_modules/**' | ||
| ] | ||
| }, | ||
| { | ||
| ignores: [ | ||
| '!node_modules/**' | ||
| ] | ||
| } | ||
| ], { | ||
| basePath | ||
| }); | ||
|
|
||
| configs.normalizeSync(); | ||
|
|
||
| expect(configs.isDirectoryIgnored(path.join(basePath, 'node_modules'))).to.be.false; | ||
| expect(configs.isDirectoryIgnored(path.join(basePath, 'node_modules/'))).to.be.false; | ||
| }); |
There was a problem hiding this comment.
This one was already passing before this change.
tests/config-array.test.js
Outdated
| it('should return true when a directory content is later negated with *', () => { | ||
| configs = new ConfigArray([ | ||
| { | ||
| files: ['**/*.js'] | ||
| }, | ||
| { | ||
| ignores: [ | ||
| '**/node_modules/**' | ||
| ] | ||
| }, | ||
| { | ||
| ignores: [ | ||
| '!node_modules/*' | ||
| ] | ||
| } | ||
| ], { | ||
| basePath | ||
| }); | ||
|
|
||
| configs.normalizeSync(); | ||
|
|
||
| expect(configs.isDirectoryIgnored(path.join(basePath, 'node_modules'))).to.be.true; | ||
| expect(configs.isDirectoryIgnored(path.join(basePath, 'node_modules/'))).to.be.true; | ||
| }); |
There was a problem hiding this comment.
This one was failing before this change (the directory was considered not ignored).
nzakas
left a comment
There was a problem hiding this comment.
Thanks for looking into this. I like how this simplifies the code. Left a few suggestions for cleaning up the language in the tests and had one question about the functionality.
Co-authored-by: Nicholas C. Zakas <nicholas@humanwhocodes.com>
Co-authored-by: Nicholas C. Zakas <nicholas@humanwhocodes.com>
Co-authored-by: Nicholas C. Zakas <nicholas@humanwhocodes.com>
Co-authored-by: Nicholas C. Zakas <nicholas@humanwhocodes.com>
Fixes the problem in eslint/eslint#17964 (comment)
In the code that calculates global ignores, there were still some transformations of patterns that, I believe, were needed in some previous versions, but are now causing unintended behavior.
For example, ignore pattern
foo/*/should not match filefoo/a.js.I removed all those transformations and added several tests that demonstrate the difference in behavior after this change, and also a few regression tests.