(I'm not sure if this is a valid feature request as my scenario is somewhat of an edge case, and there may be a better way to work around it. With that said...)
In my initial glob, I specify the option {dot: true}
before piping to gulp-exclude-gitignore as follows:
return gulp.src('**/*.json', {dot: true})
.pipe(excludeGitignore())
// etc...
The resulting stream contains the files from my project that I expect, but it also includes JSON dot files from directories listed in my .gitignore
file. For example, even though node_modules
is ignored, the stream contains the file node_modules/extend/.jscs.json
.
I believe the root cause of this problem is an unfortunate side effect of using a blacklist via the gulp-ignore package's exclude
function and the fact that minimatch excludes dot files by default. That is, without additional options, minimatch will always indicate that a dot file does not match, but the gulp-ignore exclude
function negates minimatch's status (via gulp-match), and thus includes all dot files present in the stream.
The following test case demonstrates the problem (the file paths come from an actual project, so this example could be improved to be more generic):
describe('when file paths contain dot files', function () {
it('excludes dot files covered by .gitignore', function (done) {
this.stub = sinon.stub(fs, 'readFileSync');
var contents = [
'build',
'node_modules',
'server.pid'
].join('\n');
this.stub.withArgs(path.resolve('.gitignore'), 'utf8').returns(contents);
var stream = excludeGitignore();
var filePaths = [];
stream.on('data', function (file) {
filePaths.push(file.relative);
});
stream.on('finish', function () {
assert.deepEqual(filePaths, [
'.eslintrc-gulpfile.json',
'package.json',
'test/server/.eslintrc.json',
'test/server/jasmine.json'
]);
done();
});
stream.write(fakeFile('.eslintrc-gulpfile.json'));
stream.write(fakeFile('package.json'));
stream.write(fakeFile('node_modules/extend/.jscs.json'));
stream.write(fakeFile('test/server/.eslintrc.json'));
stream.write(fakeFile('test/server/jasmine.json'));
stream.end();
this.stub.restore();
});
});
The test fails with the following message:
1) when file paths contain dot files excludes dot files covered by .gitignore:
Uncaught AssertionError: [ '.eslintrc-gulpfile.json',
'package.json',
'node_modules/extend/.jscs.json',
'test/server/.eslintrc.json',
'test/serve deepEqual [ '.eslintrc-gulpfile.json',
'package.json',
'test/server/.eslintrc.json',
'test/server/jasmine.json' ]
+ expected - actual
[
".eslintrc-gulpfile.json"
"package.json"
- "node_modules/extend/.jscs.json"
"test/server/.eslintrc.json"
"test/server/jasmine.json"
]
If I were able to pass minimatch options to excludeGitignore
, such that they were passed through to gulpIgnore.exclude
, and thus all the way to minimatch, I could get my scenario to work as expected. For example, the following minimal change seems to work:
diff --git a/lib/index.js b/lib/index.js
index 5ab76a9..08ccbd1 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -14,8 +14,9 @@ var appendStars = function (dirname, str) {
];
};
-module.exports = function (gitignorePath) {
+module.exports = function (gitignorePath, minimatchOptions) {
gitignorePath = path.resolve(gitignorePath || '.gitignore');
+ minimatchOptions = minimatchOptions || {};
var dirname = path.dirname(path.relative(process.cwd(), gitignorePath));
if (dirname === '.') {
dirname = '';
@@ -32,5 +33,5 @@ module.exports = function (gitignorePath) {
return m.concat(paths);
}, []);
- return gulpIgnore.exclude(ignoredFiles);
+ return gulpIgnore.exclude(ignoredFiles, minimatchOptions);
};
(As is, if you want to specify minimatchOptions
, you have to also specify gitignorePath
. If I were to submit a PR, I probably would write it such that both parameters could be optional. That is, the signature would be excludeGitignore([gitignorePath][, minimatchOptions])
.)
Now, updating the call to excludeGitignore
in the above test case to the following:
var stream = excludeGitignore('.gitignore', {dot: true});
results in a passing test.
Sorry for making you wade through all that. π¬
In summary, would you consider the addition of minimatchOptions
to be a bad smell because I'm coupling the gulp.src
minimatch options to excludeGitignore
? Or am I just overcomplicating this, and there's a better solution that doesn't require modifying gulp-exclude-gitignore?