You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
117 lines
3.3 KiB
117 lines
3.3 KiB
/*jslint node: true */ |
|
|
|
'use strict'; |
|
|
|
var through2 = require('through2'); |
|
var Combine = require('ordered-read-streams'); |
|
var unique = require('unique-stream'); |
|
|
|
var glob = require('glob'); |
|
var minimatch = require('minimatch'); |
|
var glob2base = require('glob2base'); |
|
var path = require('path'); |
|
|
|
var gs = { |
|
// creates a stream for a single glob or filter |
|
createStream: function(ourGlob, negatives, opt) { |
|
if (!negatives) negatives = []; |
|
if (!opt) opt = {}; |
|
if (typeof opt.cwd !== 'string') opt.cwd = process.cwd(); |
|
if (typeof opt.dot !== 'boolean') opt.dot = false; |
|
if (typeof opt.silent !== 'boolean') opt.silent = true; |
|
if (typeof opt.nonull !== 'boolean') opt.nonull = false; |
|
if (typeof opt.cwdbase !== 'boolean') opt.cwdbase = false; |
|
if (opt.cwdbase) opt.base = opt.cwd; |
|
|
|
// remove path relativity to make globs make sense |
|
ourGlob = unrelative(opt.cwd, ourGlob); |
|
negatives = negatives.map(unrelative.bind(null, opt.cwd)); |
|
|
|
// create globbing stuff |
|
var globber = new glob.Glob(ourGlob, opt); |
|
|
|
// extract base path from glob |
|
var basePath = opt.base ? opt.base : glob2base(globber); |
|
|
|
// create stream and map events from globber to it |
|
var stream = through2.obj(negatives.length ? filterNegatives : undefined); |
|
|
|
globber.on('error', stream.emit.bind(stream, 'error')); |
|
globber.on('end', function(/* some args here so can't use bind directly */){ |
|
stream.end(); |
|
}); |
|
globber.on('match', function(filename) { |
|
stream.write({ |
|
cwd: opt.cwd, |
|
base: basePath, |
|
path: path.resolve(opt.cwd, filename) |
|
}); |
|
}); |
|
|
|
return stream; |
|
|
|
function filterNegatives(filename, enc, cb) { |
|
var matcha = isMatch.bind(null, filename, opt); |
|
if (negatives.every(matcha)) { |
|
cb(null, filename); // pass |
|
} else { |
|
cb(); // ignore |
|
} |
|
} |
|
}, |
|
|
|
// creates a stream for multiple globs or filters |
|
create: function(globs, opt) { |
|
if (!opt) opt = {}; |
|
|
|
// only one glob no need to aggregate |
|
if (!Array.isArray(globs)) return gs.createStream(globs, null, opt); |
|
|
|
var positives = globs.filter(isPositive); |
|
var negatives = globs.filter(isNegative); |
|
|
|
if (positives.length === 0) throw new Error("Missing positive glob"); |
|
|
|
// only one positive glob no need to aggregate |
|
if (positives.length === 1) return gs.createStream(positives[0], negatives, opt); |
|
|
|
// create all individual streams |
|
var streams = positives.map(function(glob){ |
|
return gs.createStream(glob, negatives, opt); |
|
}); |
|
|
|
// then just pipe them to a single unique stream and return it |
|
var aggregate = new Combine(streams); |
|
var uniqueStream = unique('path'); |
|
|
|
return aggregate.pipe(uniqueStream); |
|
} |
|
}; |
|
|
|
function isMatch(file, opt, pattern) { |
|
if (typeof pattern === 'string') return minimatch(file.path, pattern, opt); |
|
if (pattern instanceof RegExp) return pattern.test(file.path); |
|
return true; // unknown glob type? |
|
} |
|
|
|
function isNegative(pattern) { |
|
if (typeof pattern !== 'string') return true; |
|
if (pattern[0] === '!') return true; |
|
return false; |
|
} |
|
|
|
function isPositive(pattern) { |
|
return !isNegative(pattern); |
|
} |
|
|
|
function unrelative(cwd, glob) { |
|
var mod = ''; |
|
if (glob[0] === '!') { |
|
mod = glob[0]; |
|
glob = glob.slice(1); |
|
} |
|
return mod+path.resolve(cwd, glob); |
|
} |
|
|
|
|
|
module.exports = gs;
|
|
|