forked from gulpjs/glob-stream
-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
171 lines (137 loc) · 3.95 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
'use strict';
var through2 = require('through2');
var Combine = require('ordered-read-streams');
var unique = require('unique-stream');
var glob = require('glob');
var resolveGlob = require('to-absolute-glob');
var globParent = require('glob-parent');
var extend = require('extend');
var gs = {
// Creates a stream for a single glob or filter
createStream: function(ourGlob, negatives, opt) {
function resolveNegatives(negative) {
return resolveGlob(negative,opt);
}
// Remove path relativity to make globs make sense
ourGlob = resolveGlob(ourGlob, opt);
var ourNegatives = negatives.map(resolveNegatives);
var ourOpt = extend({}, opt);
delete ourOpt.root;
ourOpt.ignore = ourNegatives;
// Create globbing stuff
var globber = new glob.Glob(ourGlob, ourOpt);
// Extract base path from glob
var basePath = opt.base || globParent(ourGlob) + '/';
// Create stream and map events from globber to it
var stream = through2.obj(ourOpt);
var found = false;
globber.on('error', stream.emit.bind(stream, 'error'));
globber.once('end', function() {
if (opt.allowEmpty !== true && !found && globIsSingular(globber)) {
stream.emit('error',
new Error('File not found with singular glob: ' + ourGlob));
}
stream.end();
});
globber.on('match', function(filename) {
found = true;
stream.write({
cwd: opt.cwd,
base: basePath,
path: filename,
});
});
return stream;
},
// Creates a stream for multiple globs or filters
create: function(globs, opt) {
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;
}
// Only one glob no need to aggregate
if (!Array.isArray(globs)) {
globs = [globs];
}
var positives = [];
var negatives = [];
var ourOpt = extend({}, opt);
delete ourOpt.root;
globs.forEach(function(glob, index) {
if (typeof glob !== 'string') {
throw new Error('Invalid glob at index ' + index);
}
var globArray = isNegative(glob) ? negatives : positives;
globArray.push({
index: index,
glob: glob,
});
});
if (positives.length === 0) {
throw new Error('Missing positive glob');
}
// Only one positive glob no need to aggregate
if (positives.length === 1) {
return streamFromPositive(positives[0]);
}
// Create all individual streams
var streams = positives.map(streamFromPositive);
// Then just pipe them to a single unique stream and return it
var aggregate = new Combine(streams);
var uniqueStream = unique('path');
var returnStream = aggregate.pipe(uniqueStream);
aggregate.on('error', function(err) {
returnStream.emit('error', err);
});
return returnStream;
function streamFromPositive(positive) {
var negativeGlobs = negatives.filter(indexGreaterThan(positive.index))
.map(toGlob)
.map(stripExclamationMark);
return gs.createStream(positive.glob, negativeGlobs, opt);
}
},
};
function isNegative(pattern) {
if (typeof pattern === 'string') {
return pattern[0] === '!';
}
}
function indexGreaterThan(index) {
return function(obj) {
return obj.index > index;
};
}
function toGlob(obj) {
return obj.glob;
}
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 stripExclamationMark(glob) {
return glob.slice(1);
}
module.exports = gs;