5 var through2 = require('through2');
6 var Combine = require('ordered-read-streams');
7 var unique = require('unique-stream');
9 var glob = require('glob');
10 var minimatch = require('minimatch');
11 var glob2base = require('glob2base');
12 var path = require('path');
15 // creates a stream for a single glob or filter
16 createStream: function(ourGlob, negatives, opt) {
17 if (!negatives) negatives = [];
19 if (typeof opt.cwd !== 'string') opt.cwd = process.cwd();
20 if (typeof opt.dot !== 'boolean') opt.dot = false;
21 if (typeof opt.silent !== 'boolean') opt.silent = true;
22 if (typeof opt.nonull !== 'boolean') opt.nonull = false;
23 if (typeof opt.cwdbase !== 'boolean') opt.cwdbase = false;
24 if (opt.cwdbase) opt.base = opt.cwd;
26 // remove path relativity to make globs make sense
27 ourGlob = unrelative(opt.cwd, ourGlob);
28 negatives = negatives.map(unrelative.bind(null, opt.cwd));
30 // create globbing stuff
31 var globber = new glob.Glob(ourGlob, opt);
33 // extract base path from glob
34 var basePath = opt.base ? opt.base : glob2base(globber);
36 // create stream and map events from globber to it
37 var stream = through2.obj(negatives.length ? filterNegatives : undefined);
39 globber.on('error', stream.emit.bind(stream, 'error'));
40 globber.on('end', function(/* some args here so can't use bind directly */){
43 globber.on('match', function(filename) {
47 path: path.resolve(opt.cwd, filename)
53 function filterNegatives(filename, enc, cb) {
54 var matcha = isMatch.bind(null, filename, opt);
55 if (negatives.every(matcha)) {
56 cb(null, filename); // pass
63 // creates a stream for multiple globs or filters
64 create: function(globs, opt) {
67 // only one glob no need to aggregate
68 if (!Array.isArray(globs)) return gs.createStream(globs, null, opt);
70 var positives = globs.filter(isPositive);
71 var negatives = globs.filter(isNegative);
73 if (positives.length === 0) throw new Error("Missing positive glob");
75 // only one positive glob no need to aggregate
76 if (positives.length === 1) return gs.createStream(positives[0], negatives, opt);
78 // create all individual streams
79 var streams = positives.map(function(glob){
80 return gs.createStream(glob, negatives, opt);
83 // then just pipe them to a single unique stream and return it
84 var aggregate = new Combine(streams);
85 var uniqueStream = unique('path');
87 return aggregate.pipe(uniqueStream);
91 function isMatch(file, opt, pattern) {
92 if (typeof pattern === 'string') return minimatch(file.path, pattern, opt);
93 if (pattern instanceof RegExp) return pattern.test(file.path);
94 return true; // unknown glob type?
97 function isNegative(pattern) {
98 if (typeof pattern !== 'string') return true;
99 if (pattern[0] === '!') return true;
103 function isPositive(pattern) {
104 return !isNegative(pattern);
107 function unrelative(cwd, glob) {
109 if (glob[0] === '!') {
111 glob = glob.slice(1);
113 return mod+path.resolve(cwd, glob);