readable.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. 'use strict';
  2. var inherits = require('util').inherits;
  3. var glob = require('glob');
  4. var extend = require('extend');
  5. var Readable = require('readable-stream').Readable;
  6. var globParent = require('glob-parent');
  7. var toAbsoluteGlob = require('to-absolute-glob');
  8. var removeTrailingSeparator = require('remove-trailing-separator');
  9. var globErrMessage1 = 'File not found with singular glob: ';
  10. var globErrMessage2 = ' (if this was purposeful, use `allowEmpty` option)';
  11. function getBasePath(ourGlob, opt) {
  12. return globParent(toAbsoluteGlob(ourGlob, opt));
  13. }
  14. function globIsSingular(glob) {
  15. var globSet = glob.minimatch.set;
  16. if (globSet.length !== 1) {
  17. return false;
  18. }
  19. return globSet[0].every(function isString(value) {
  20. return typeof value === 'string';
  21. });
  22. }
  23. function GlobStream(ourGlob, negatives, opt) {
  24. if (!(this instanceof GlobStream)) {
  25. return new GlobStream(ourGlob, negatives, opt);
  26. }
  27. var ourOpt = extend({}, opt);
  28. Readable.call(this, {
  29. objectMode: true,
  30. highWaterMark: ourOpt.highWaterMark || 16,
  31. });
  32. // Delete `highWaterMark` after inheriting from Readable
  33. delete ourOpt.highWaterMark;
  34. var self = this;
  35. function resolveNegatives(negative) {
  36. return toAbsoluteGlob(negative, ourOpt);
  37. }
  38. var ourNegatives = negatives.map(resolveNegatives);
  39. ourOpt.ignore = ourNegatives;
  40. var cwd = ourOpt.cwd;
  41. var allowEmpty = ourOpt.allowEmpty || false;
  42. // Extract base path from glob
  43. var basePath = ourOpt.base || getBasePath(ourGlob, ourOpt);
  44. // Remove path relativity to make globs make sense
  45. ourGlob = toAbsoluteGlob(ourGlob, ourOpt);
  46. // Delete `root` after all resolving done
  47. delete ourOpt.root;
  48. var globber = new glob.Glob(ourGlob, ourOpt);
  49. this._globber = globber;
  50. var found = false;
  51. globber.on('match', function(filepath) {
  52. found = true;
  53. var obj = {
  54. cwd: cwd,
  55. base: basePath,
  56. path: removeTrailingSeparator(filepath),
  57. };
  58. if (!self.push(obj)) {
  59. globber.pause();
  60. }
  61. });
  62. globber.once('end', function() {
  63. if (allowEmpty !== true && !found && globIsSingular(globber)) {
  64. var err = new Error(globErrMessage1 + ourGlob + globErrMessage2);
  65. return self.destroy(err);
  66. }
  67. self.push(null);
  68. });
  69. function onError(err) {
  70. self.destroy(err);
  71. }
  72. globber.once('error', onError);
  73. }
  74. inherits(GlobStream, Readable);
  75. GlobStream.prototype._read = function() {
  76. this._globber.resume();
  77. };
  78. GlobStream.prototype.destroy = function(err) {
  79. var self = this;
  80. this._globber.abort();
  81. process.nextTick(function() {
  82. if (err) {
  83. self.emit('error', err);
  84. }
  85. self.emit('close');
  86. });
  87. };
  88. module.exports = GlobStream;