Skip to content

Commit

Permalink
Breaking: Remove functions-as-globs support & improve glob negation
Browse files Browse the repository at this point in the history
  • Loading branch information
yocontra authored and phated committed Feb 16, 2017
1 parent 03d6324 commit f475e3a
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 90 deletions.
16 changes: 1 addition & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,7 @@ stream.on('data', function(file){
});
```

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)

#### Function

```javascript
var stream = gs.create(["./files/**/*.coffee", function(path){
return path.indexOf("something") === -1;
}]);
```

#### RegExp

```javascript
var stream = gs.create(["./files/**/*.coffee", /stuff/]);
```
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)

#### Glob

Expand Down
74 changes: 52 additions & 22 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,52 +5,82 @@ var path = require('path');

var isMatch = function(file, pattern) {
if (typeof pattern === 'string') return minimatch(file.path, pattern);
if (typeof pattern === 'function') return fn(file.path);
if (pattern instanceof RegExp) return pattern.test(file.path);
return true; // unknown glob type?
};

var matchAll = "**/*.*";
var isNegative = function(pattern) {
if (typeof pattern !== 'string') return true;
if (pattern[0] === '!') return true;
return false;
};

module.exports = {
create: function(globs, opt) {
if (!Array.isArray(globs)) globs = [globs];
var isPositive = function(pattern) {
return !isNegative(pattern);
};

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


var stream = es.pause();
var globber = new glob.Glob(matchAll, opt);

// extract base path because we are too lazy lol
var rules = globber.minimatch.set[0];
var basePath = path.normalize(rules.map(function(s, idx) {
if (typeof s === 'string' && idx !== rules.length-1) {
return s;
} else {
return '';
}
}).join(path.sep));
// create globbing stuff
var globber = new glob.Glob(ourGlob, opt);

// create stream and map events from globber to it
var stream = es.pause();
globber.on('error', stream.emit.bind(stream, 'error'));
globber.on('end', function(){
stream.end();
});
globber.on('match', function(filename) {
stream.write({
base: basePath,
path: filename
base: path.join(opt.cwd, path.dirname(filename)),
path: path.join(opt.cwd, filename)
});
});

if (negatives.length === 0) return stream; // no filtering needed

// stream to check against negatives
var filterStream = es.map(function(filename, cb) {
var matcha = isMatch.bind(null, filename);
if (globs.every(matcha)) return cb(null, filename); // pass
var matcha = function(pattern) {
return isMatch(filename, pattern);
};
if (!negatives.every(matcha)) return cb(null, filename); // pass
cb(); // ignore
});

return stream.pipe(filterStream);
},

// creates a stream for multiple globs or filters
create: function(globs, opt) {
// only one glob no need to aggregate
if (!Array.isArray(globs)) return us.createStream(globs, null, opt);

var positives = globs.filter(isPositive);
var negatives = globs.filter(isNegative);

if (positives.length === 0) throw new Error("Missing positive glob");

// only one positive glob no need to aggregate
if (positives.length === 1) return us.createStream(positives[0], negatives, opt);

// create all individual streams
var streams = positives.map(function(glob){
return us.createStream(glob, negatives, opt);
});

// then just pipe them to a single stream and return it
var aggregate = es.pause();
streams.forEach(function(gStream){
gStream.pipe(aggregate);
});
return aggregate;
}
};
70 changes: 17 additions & 53 deletions test/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ var join = require('path').join;

describe('glob-stream', function() {
describe('create()', function() {
it('should return a file name stream from a glob', function(done) {
var stream = gs.create(join(__dirname, "./fixtures/*.coffee"));
it('should return a folder name stream from a glob', function(done) {
var stream = gs.create("./fixtures/whatsgoingon", {cwd: __dirname});
should.exist(stream);
stream.on('error', function(err) {
throw err;
Expand All @@ -15,16 +15,14 @@ describe('glob-stream', function() {
should.exist(file);
should.exist(file.path);
should.exist(file.base);
String(file.path).should.equal(join(__dirname, "./fixtures/test.coffee"));
String(file.base).should.equal(join(__dirname, "./fixtures/"));
});
stream.on('end', function() {
String(file.path).should.equal(join(__dirname, "./fixtures/whatsgoingon"));
String(file.base).should.equal(join(__dirname, "./fixtures"));
done();
});
});

it('should return a file name stream from a deep glob', function(done) {
var stream = gs.create(join(__dirname, "./fixtures/**/*.js"));
it('should return a file name stream from a glob', function(done) {
var stream = gs.create("./fixtures/*.coffee", {cwd: __dirname});
should.exist(stream);
stream.on('error', function(err) {
throw err;
Expand All @@ -33,46 +31,30 @@ describe('glob-stream', function() {
should.exist(file);
should.exist(file.path);
should.exist(file.base);
String(file.path).should.equal(join(__dirname, "./fixtures/whatsgoingon/test.js"));
String(file.base).should.equal(join(__dirname, "./fixtures/"));
});
stream.on('end', function() {
done();
});
});

it('should return a file name stream with negation from a glob', function(done) {
var stream = gs.create([join(__dirname, "./fixtures/**/*.js"), "!"+join(__dirname, "./fixtures/**/test.js")]);
should.exist(stream);
stream.on('error', function(err) {
throw err;
});
stream.on('data', function(file) {
throw "file should have been negated";
});
stream.on('end', function() {
String(file.path).should.equal(join(__dirname, "./fixtures/test.coffee"));
String(file.base).should.equal(join(__dirname, "./fixtures"));
done();
});
});

it('should return a file name stream with negation from a regex', function(done) {
var stream = gs.create([join(__dirname, "./fixtures/**/*.js"), /nomatch.js/]);
it('should return a file name stream from a direct path', function(done) {
var stream = gs.create("./fixtures/test.coffee", {cwd: __dirname});
should.exist(stream);
stream.on('error', function(err) {
throw err;
});
stream.on('data', function(file) {
throw "file should have been negated";
});
stream.on('end', function() {
should.exist(file);
should.exist(file.path);
should.exist(file.base);
String(file.path).should.equal(join(__dirname, "./fixtures/test.coffee"));
String(file.base).should.equal(join(__dirname, "./fixtures"));
done();
});
});

it('should return a file name stream with negation from a regex', function(done) {
var stream = gs.create([join(__dirname, "./fixtures/**/*.js"), function(){
return false;
}]);
it('should return a file name stream with negation from a glob', function(done) {
var stream = gs.create(["./fixtures/**/*.js", "!./fixtures/**/test.js"], {cwd: __dirname});
should.exist(stream);
stream.on('error', function(err) {
throw err;
Expand All @@ -85,23 +67,5 @@ describe('glob-stream', function() {
});
});

it('should return a file name stream from a direct path', function(done) {
var stream = gs.create(join(__dirname, "./fixtures/test.coffee"));
should.exist(stream);
stream.on('error', function(err) {
throw err;
});
stream.on('data', function(file) {
should.exist(file);
should.exist(file.path);
should.exist(file.base);
String(file.path).should.equal(join(__dirname, "./fixtures/test.coffee"));
String(file.base).should.equal(join(__dirname, "./fixtures/"));
});
stream.on('end', function() {
done();
});
});

});
});

0 comments on commit f475e3a

Please sign in to comment.