| 'use strict'; |
| |
| var inherits = require('util').inherits; |
| |
| var glob = require('glob'); |
| var extend = require('extend'); |
| var Readable = require('readable-stream').Readable; |
| var globParent = require('glob-parent'); |
| var toAbsoluteGlob = require('to-absolute-glob'); |
| var removeTrailingSeparator = require('remove-trailing-separator'); |
| |
| var globErrMessage1 = 'File not found with singular glob: '; |
| var globErrMessage2 = ' (if this was purposeful, use `allowEmpty` option)'; |
| |
| function getBasePath(ourGlob, opt) { |
| return globParent(toAbsoluteGlob(ourGlob, opt)); |
| } |
| |
| function globIsSingular(glob) { |
| var globSet = glob.minimatch.set; |
| if (globSet.length !== 1) { |
| return false; |
| } |
| |
| return globSet[0].every(function isString(value) { |
| return typeof value === 'string'; |
| }); |
| } |
| |
| function GlobStream(ourGlob, negatives, opt) { |
| if (!(this instanceof GlobStream)) { |
| return new GlobStream(ourGlob, negatives, opt); |
| } |
| |
| var ourOpt = extend({}, opt); |
| |
| Readable.call(this, { |
| objectMode: true, |
| highWaterMark: ourOpt.highWaterMark || 16, |
| }); |
| |
| // Delete `highWaterMark` after inheriting from Readable |
| delete ourOpt.highWaterMark; |
| |
| var self = this; |
| |
| function resolveNegatives(negative) { |
| return toAbsoluteGlob(negative, ourOpt); |
| } |
| |
| var ourNegatives = negatives.map(resolveNegatives); |
| ourOpt.ignore = ourNegatives; |
| |
| var cwd = ourOpt.cwd; |
| var allowEmpty = ourOpt.allowEmpty || false; |
| |
| // Extract base path from glob |
| var basePath = ourOpt.base || getBasePath(ourGlob, ourOpt); |
| |
| // Remove path relativity to make globs make sense |
| ourGlob = toAbsoluteGlob(ourGlob, ourOpt); |
| // Delete `root` after all resolving done |
| delete ourOpt.root; |
| |
| var globber = new glob.Glob(ourGlob, ourOpt); |
| this._globber = globber; |
| |
| var found = false; |
| |
| globber.on('match', function(filepath) { |
| found = true; |
| var obj = { |
| cwd: cwd, |
| base: basePath, |
| path: removeTrailingSeparator(filepath), |
| }; |
| if (!self.push(obj)) { |
| globber.pause(); |
| } |
| }); |
| |
| globber.once('end', function() { |
| if (allowEmpty !== true && !found && globIsSingular(globber)) { |
| var err = new Error(globErrMessage1 + ourGlob + globErrMessage2); |
| |
| return self.destroy(err); |
| } |
| |
| self.push(null); |
| }); |
| |
| function onError(err) { |
| self.destroy(err); |
| } |
| |
| globber.once('error', onError); |
| } |
| inherits(GlobStream, Readable); |
| |
| GlobStream.prototype._read = function() { |
| this._globber.resume(); |
| }; |
| |
| GlobStream.prototype.destroy = function(err) { |
| var self = this; |
| |
| this._globber.abort(); |
| |
| process.nextTick(function() { |
| if (err) { |
| self.emit('error', err); |
| } |
| self.emit('close'); |
| }); |
| }; |
| |
| module.exports = GlobStream; |