| 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); |