Skip to content

Commit f475e3a

Browse files
yocontraphated
authored andcommitted
Breaking: Remove functions-as-globs support & improve glob negation
1 parent 03d6324 commit f475e3a

File tree

3 files changed

+70
-90
lines changed

3 files changed

+70
-90
lines changed

README.md

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,7 @@ stream.on('data', function(file){
3030
});
3131
```
3232

33-
You can pass a single one of these (or an array with any combination). All given must match for the file to be returned. Optional options argument is passed directly to [node-glob](https://github.com/isaacs/node-glob)
34-
35-
#### Function
36-
37-
```javascript
38-
var stream = gs.create(["./files/**/*.coffee", function(path){
39-
return path.indexOf("something") === -1;
40-
}]);
41-
```
42-
43-
#### RegExp
44-
45-
```javascript
46-
var stream = gs.create(["./files/**/*.coffee", /stuff/]);
47-
```
33+
You can pass any combination of globs. One caveat is that you can not only pass a glob negation, you must give it at least one positive glob so it knows where to start. All given must match for the file to be returned. Optional options argument is passed directly to [node-glob](https://github.com/isaacs/node-glob)
4834

4935
#### Glob
5036

index.js

Lines changed: 52 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,52 +5,82 @@ var path = require('path');
55

66
var isMatch = function(file, pattern) {
77
if (typeof pattern === 'string') return minimatch(file.path, pattern);
8-
if (typeof pattern === 'function') return fn(file.path);
98
if (pattern instanceof RegExp) return pattern.test(file.path);
109
return true; // unknown glob type?
1110
};
1211

13-
var matchAll = "**/*.*";
12+
var isNegative = function(pattern) {
13+
if (typeof pattern !== 'string') return true;
14+
if (pattern[0] === '!') return true;
15+
return false;
16+
};
1417

15-
module.exports = {
16-
create: function(globs, opt) {
17-
if (!Array.isArray(globs)) globs = [globs];
18+
var isPositive = function(pattern) {
19+
return !isNegative(pattern);
20+
};
1821

22+
module.exports = us = {
23+
// creates a stream for a single glob or filter
24+
createStream: function(ourGlob, negatives, opt) {
25+
if (!negatives) negatives = [];
1926
if (!opt) opt = {};
27+
if (typeof opt.cwd !== 'string') opt.cwd = process.cwd();
2028
if (typeof opt.silent !== 'boolean') opt.silent = true;
2129
if (typeof opt.nonull !== 'boolean') opt.nonull = false;
2230

23-
24-
var stream = es.pause();
25-
var globber = new glob.Glob(matchAll, opt);
26-
27-
// extract base path because we are too lazy lol
28-
var rules = globber.minimatch.set[0];
29-
var basePath = path.normalize(rules.map(function(s, idx) {
30-
if (typeof s === 'string' && idx !== rules.length-1) {
31-
return s;
32-
} else {
33-
return '';
34-
}
35-
}).join(path.sep));
31+
// create globbing stuff
32+
var globber = new glob.Glob(ourGlob, opt);
3633

34+
// create stream and map events from globber to it
35+
var stream = es.pause();
3736
globber.on('error', stream.emit.bind(stream, 'error'));
3837
globber.on('end', function(){
3938
stream.end();
4039
});
4140
globber.on('match', function(filename) {
4241
stream.write({
43-
base: basePath,
44-
path: filename
42+
base: path.join(opt.cwd, path.dirname(filename)),
43+
path: path.join(opt.cwd, filename)
4544
});
4645
});
4746

47+
if (negatives.length === 0) return stream; // no filtering needed
48+
49+
// stream to check against negatives
4850
var filterStream = es.map(function(filename, cb) {
49-
var matcha = isMatch.bind(null, filename);
50-
if (globs.every(matcha)) return cb(null, filename); // pass
51+
var matcha = function(pattern) {
52+
return isMatch(filename, pattern);
53+
};
54+
if (!negatives.every(matcha)) return cb(null, filename); // pass
5155
cb(); // ignore
5256
});
5357

5458
return stream.pipe(filterStream);
59+
},
60+
61+
// creates a stream for multiple globs or filters
62+
create: function(globs, opt) {
63+
// only one glob no need to aggregate
64+
if (!Array.isArray(globs)) return us.createStream(globs, null, opt);
65+
66+
var positives = globs.filter(isPositive);
67+
var negatives = globs.filter(isNegative);
68+
69+
if (positives.length === 0) throw new Error("Missing positive glob");
70+
71+
// only one positive glob no need to aggregate
72+
if (positives.length === 1) return us.createStream(positives[0], negatives, opt);
73+
74+
// create all individual streams
75+
var streams = positives.map(function(glob){
76+
return us.createStream(glob, negatives, opt);
77+
});
78+
79+
// then just pipe them to a single stream and return it
80+
var aggregate = es.pause();
81+
streams.forEach(function(gStream){
82+
gStream.pipe(aggregate);
83+
});
84+
return aggregate;
5585
}
5686
};

test/main.js

Lines changed: 17 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ var join = require('path').join;
55

66
describe('glob-stream', function() {
77
describe('create()', function() {
8-
it('should return a file name stream from a glob', function(done) {
9-
var stream = gs.create(join(__dirname, "./fixtures/*.coffee"));
8+
it('should return a folder name stream from a glob', function(done) {
9+
var stream = gs.create("./fixtures/whatsgoingon", {cwd: __dirname});
1010
should.exist(stream);
1111
stream.on('error', function(err) {
1212
throw err;
@@ -15,16 +15,14 @@ describe('glob-stream', function() {
1515
should.exist(file);
1616
should.exist(file.path);
1717
should.exist(file.base);
18-
String(file.path).should.equal(join(__dirname, "./fixtures/test.coffee"));
19-
String(file.base).should.equal(join(__dirname, "./fixtures/"));
20-
});
21-
stream.on('end', function() {
18+
String(file.path).should.equal(join(__dirname, "./fixtures/whatsgoingon"));
19+
String(file.base).should.equal(join(__dirname, "./fixtures"));
2220
done();
2321
});
2422
});
2523

26-
it('should return a file name stream from a deep glob', function(done) {
27-
var stream = gs.create(join(__dirname, "./fixtures/**/*.js"));
24+
it('should return a file name stream from a glob', function(done) {
25+
var stream = gs.create("./fixtures/*.coffee", {cwd: __dirname});
2826
should.exist(stream);
2927
stream.on('error', function(err) {
3028
throw err;
@@ -33,46 +31,30 @@ describe('glob-stream', function() {
3331
should.exist(file);
3432
should.exist(file.path);
3533
should.exist(file.base);
36-
String(file.path).should.equal(join(__dirname, "./fixtures/whatsgoingon/test.js"));
37-
String(file.base).should.equal(join(__dirname, "./fixtures/"));
38-
});
39-
stream.on('end', function() {
40-
done();
41-
});
42-
});
43-
44-
it('should return a file name stream with negation from a glob', function(done) {
45-
var stream = gs.create([join(__dirname, "./fixtures/**/*.js"), "!"+join(__dirname, "./fixtures/**/test.js")]);
46-
should.exist(stream);
47-
stream.on('error', function(err) {
48-
throw err;
49-
});
50-
stream.on('data', function(file) {
51-
throw "file should have been negated";
52-
});
53-
stream.on('end', function() {
34+
String(file.path).should.equal(join(__dirname, "./fixtures/test.coffee"));
35+
String(file.base).should.equal(join(__dirname, "./fixtures"));
5436
done();
5537
});
5638
});
5739

58-
it('should return a file name stream with negation from a regex', function(done) {
59-
var stream = gs.create([join(__dirname, "./fixtures/**/*.js"), /nomatch.js/]);
40+
it('should return a file name stream from a direct path', function(done) {
41+
var stream = gs.create("./fixtures/test.coffee", {cwd: __dirname});
6042
should.exist(stream);
6143
stream.on('error', function(err) {
6244
throw err;
6345
});
6446
stream.on('data', function(file) {
65-
throw "file should have been negated";
66-
});
67-
stream.on('end', function() {
47+
should.exist(file);
48+
should.exist(file.path);
49+
should.exist(file.base);
50+
String(file.path).should.equal(join(__dirname, "./fixtures/test.coffee"));
51+
String(file.base).should.equal(join(__dirname, "./fixtures"));
6852
done();
6953
});
7054
});
7155

72-
it('should return a file name stream with negation from a regex', function(done) {
73-
var stream = gs.create([join(__dirname, "./fixtures/**/*.js"), function(){
74-
return false;
75-
}]);
56+
it('should return a file name stream with negation from a glob', function(done) {
57+
var stream = gs.create(["./fixtures/**/*.js", "!./fixtures/**/test.js"], {cwd: __dirname});
7658
should.exist(stream);
7759
stream.on('error', function(err) {
7860
throw err;
@@ -85,23 +67,5 @@ describe('glob-stream', function() {
8567
});
8668
});
8769

88-
it('should return a file name stream from a direct path', function(done) {
89-
var stream = gs.create(join(__dirname, "./fixtures/test.coffee"));
90-
should.exist(stream);
91-
stream.on('error', function(err) {
92-
throw err;
93-
});
94-
stream.on('data', function(file) {
95-
should.exist(file);
96-
should.exist(file.path);
97-
should.exist(file.base);
98-
String(file.path).should.equal(join(__dirname, "./fixtures/test.coffee"));
99-
String(file.base).should.equal(join(__dirname, "./fixtures/"));
100-
});
101-
stream.on('end', function() {
102-
done();
103-
});
104-
});
105-
10670
});
10771
});

0 commit comments

Comments
 (0)