109 lines
3.3 KiB
JavaScript
109 lines
3.3 KiB
JavaScript
|
var util = require('util');
|
||
|
var minimatch = require('minimatch');
|
||
|
var glob = require('glob');
|
||
|
var Glob = glob.Glob;
|
||
|
var EventEmitter = require('events').EventEmitter;
|
||
|
|
||
|
module.exports = fileset;
|
||
|
|
||
|
// Async API
|
||
|
function fileset(include, exclude, options, cb) {
|
||
|
if (typeof exclude === 'function') cb = exclude, exclude = '';
|
||
|
else if (typeof options === 'function') cb = options, options = {};
|
||
|
|
||
|
var includes = (typeof include === 'string') ? include.split(' ') : include;
|
||
|
var excludes = (typeof exclude === 'string') ? exclude.split(' ') : exclude;
|
||
|
|
||
|
var em = new EventEmitter;
|
||
|
var remaining = includes.length;
|
||
|
var results = [];
|
||
|
|
||
|
if (!includes.length) return cb(new Error('Must provide an include pattern'));
|
||
|
|
||
|
em.includes = includes.map(function(pattern) {
|
||
|
return new fileset.Fileset(pattern, options)
|
||
|
.on('error', cb ? cb : em.emit.bind(em, 'error'))
|
||
|
.on('match', em.emit.bind(em, 'match'))
|
||
|
.on('match', em.emit.bind(em, 'include'))
|
||
|
.on('end', next.bind({}, pattern))
|
||
|
});
|
||
|
|
||
|
function next(pattern, matches) {
|
||
|
results = results.concat(matches);
|
||
|
|
||
|
if (!(--remaining)) {
|
||
|
results = results.filter(function(file) {
|
||
|
return !excludes.filter(function(glob) {
|
||
|
var match = minimatch(file, glob, { matchBase: true });
|
||
|
if(match) em.emit('exclude', file);
|
||
|
return match;
|
||
|
}).length;
|
||
|
});
|
||
|
|
||
|
if(cb) cb(null, results);
|
||
|
em.emit('end', results);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return em;
|
||
|
}
|
||
|
|
||
|
// Sync API
|
||
|
fileset.sync = function filesetSync(include, exclude) {
|
||
|
if (!exclude) exclude = '';
|
||
|
|
||
|
// includes / excludes, either an array or string separated by comma or whitespace
|
||
|
var includes = (typeof include === 'string') ? include.split(/[\s,]/g) : include;
|
||
|
var excludes = (typeof exclude === 'string') ? exclude.split(/[\s,]/g) : exclude;
|
||
|
|
||
|
// Filter out any false positive '' empty strings
|
||
|
includes = includes.filter(function(pattern) { return pattern; });
|
||
|
excludes = excludes.filter(function(pattern) { return pattern; });
|
||
|
|
||
|
// - todo: pass in glob options as last param
|
||
|
var options = { matchBase: true };
|
||
|
|
||
|
// always ignore node_modules for sync api
|
||
|
options.ignore = ['node_modules/**/*'];
|
||
|
|
||
|
// First, glob match on all include patters into a single array
|
||
|
var results = includes.map(function(include) {
|
||
|
return glob.sync(include, options);
|
||
|
}).reduce(function(a, b) {
|
||
|
return a.concat(b);
|
||
|
}, []);
|
||
|
|
||
|
// Then filters out on any exclude match
|
||
|
var ignored = excludes.map(function(exclude) {
|
||
|
return glob.sync(exclude, options);
|
||
|
}).reduce(function(a, b) {
|
||
|
return a.concat(b);
|
||
|
}, []);
|
||
|
|
||
|
// And filter any exclude match
|
||
|
results = results.filter(function(file) {
|
||
|
return !ignored.filter(function(glob) {
|
||
|
return minimatch(file, glob, { matchBase: true });
|
||
|
}).length;
|
||
|
});
|
||
|
|
||
|
return results;
|
||
|
};
|
||
|
|
||
|
fileset.Fileset = function Fileset(pattern, options, cb) {
|
||
|
if (typeof options === 'function') cb = options, options = {};
|
||
|
if (!options) options = {};
|
||
|
|
||
|
// ignore node_modules by default, unless specified
|
||
|
options.ignore = options.ignore || ['node_modules/**/*'];
|
||
|
|
||
|
Glob.call(this, pattern, options);
|
||
|
|
||
|
if (typeof cb === 'function') {
|
||
|
this.on('error', cb);
|
||
|
this.on('end', function(matches) { cb(null, matches); });
|
||
|
}
|
||
|
};
|
||
|
|
||
|
util.inherits(fileset.Fileset, Glob);
|