Skip to content

Commit

Permalink
Merge 84257b8 into 2df9956
Browse files Browse the repository at this point in the history
  • Loading branch information
floatdrop committed Jan 21, 2015
2 parents 2df9956 + 84257b8 commit df9b22a
Show file tree
Hide file tree
Showing 10 changed files with 115 additions and 136 deletions.
7 changes: 0 additions & 7 deletions .npmignore

This file was deleted.

32 changes: 9 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ All incoming files that piped in will be grouped and passed to `events` stream a

#### Options

This object is passed to [`gaze` options](https://github.com/shama/gaze#properties) directly (refer to [`gaze` documentation](https://github.com/shama/gaze)). Options for [`gulp.src`](https://github.com/gulpjs/gulp#gulpsrcglobs-options) are used. If you do not want content from `watch`, then add `read: false` to the `options` object.
This object is passed to [`chokidar` options](https://github.com/paulmillr/chokidar#api) directly. Options for [`gulp.src`](https://github.com/gulpjs/gulp#gulpsrcglobs-options) are also available. If you do not want content from `watch`, then add `read: false` to the `options` object.

#### options.base
Type: `String`
Expand All @@ -73,33 +73,19 @@ This options will enable more verbose output (on `true`) or disable it completly

Returned `Stream` from constructor have some useful methods:

* `close()` — calling `gaze.close` and emitting `end`, after `gaze.close` is done.

Also it has `_gaze` property to access Gaze instance.
* `add(path / paths)`
* `unwatch(path / paths)`
* `close()`

### Events

* `end` — all files are stop being watched.
* `ready` — just re-emitted event from `gaze`.
* `error` — when something happened inside callback, you will get notified.

### 3.0.0 Changes

[gulp-batch](https://github.com/floatdrop/gulp-batch) was removed, so `callback` is changed. Now it passes just [vinyl](https://github.com/wearefractal/vinyl) object to you. Also `callback` now not catching errors inside and reemits them to stream.

### 2.0.0 Changes

Before `2.0.0` version there was a bug in `gulp-batch` - it does not prevent tasks to execute in same time. In `2.0.0` version of `gulp-batch` was bumped.

This can cause your watch tasks to hang, if you do not calling `done` in callback or returning `Stream`/`Promise` from it.

### Migration to 1.0.0
* `end`
* `ready`
* `error`

* __watch is not emmiting files at start__ - read «[Starting tasks on events](/docs/readme.md#starting-tasks-on-events)» and «[Incremental build](https://github.com/floatdrop/gulp-watch/tree/master/docs#incremental-build)» for workarounds.
* __watch is now pass through stream__ - which means that streaming files into watch will not add them to gaze. It is very hard to maintain, because watch is not aware about `glob`, from which this files come from and can not re-create vinyl object properly without maintaining cache of the `base` properties of incoming files (yuck).
* __array of tasks is not accepted as callback__ - this was not working anyway, but rationale behind it - requiring gulp and calling internal method start is bad. This feature will become more clear, when gulp 4.0.0 will be released with new task system. Read «[Starting tasks on events](/docs/readme.md#starting-tasks-on-events)» for right way to do it.
### [Changelog](https://github.com/floatdrop/gulp-watch/releases)

# License
## License

MIT (c) 2014 Vsevolod Strukchinsky (floatdrop@gmail.com)

Expand Down
Binary file removed img/2014-01-09.gif
Binary file not shown.
82 changes: 45 additions & 37 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
'use strict';

function nop() {}

var util = require('gulp-util'),
PluginError = require('gulp-util').PluginError,
chokidar = require('chokidar'),
Duplex = require('readable-stream').Duplex,
vinyl = require('vinyl-file'),
File = require('vinyl'),
glob2base = require('glob2base'),
path2glob = require('path2glob'),
sep = require('path').sep;

function isDirectory(path) {
return path[path.length - 1] === sep;
}
anymatch = require('anymatch'),
Glob = require('glob').Glob;

module.exports = function (globs, opts, cb) {
if (!globs) throw new PluginError('gulp-watch', 'glob argument required');

if (typeof globs === 'string') globs = [ globs ];
if (typeof globs === 'string') globs = [globs];

if (!Array.isArray(globs)) {
throw new PluginError('gulp-watch', 'glob should be String or Array, not ' + (typeof globs));
Expand All @@ -29,12 +23,11 @@ module.exports = function (globs, opts, cb) {
opts = {};
}

if (!opts) opts = {};
opts = opts || {};
cb = cb || function () {};

var baseForced = !!opts.base;
var outputStream = new Duplex({ objectMode: true, allowHalfOpen: true });

cb = cb || nop;
var outputStream = new Duplex({objectMode: true, allowHalfOpen: true});

outputStream._write = function _write(file, enc, done) {
cb(file);
Expand All @@ -44,46 +37,61 @@ module.exports = function (globs, opts, cb) {

outputStream._read = function _read() { };

var Gaze = require('gaze');
var gaze = outputStream._gaze = new Gaze(globs, opts);
var watcher = chokidar.watch(globs, opts)
.on('all', processEvent)
.on('error', outputStream.emit.bind(outputStream, 'error'))
.on('ready', outputStream.emit.bind(outputStream, 'ready'));

gaze.on('all', processEvent);

function write(event, err, file) {
if (err) { return outputStream.emit('error', err); }
if (opts.verbose !== false) { log(event, file); }
file.event = event;
outputStream.push(file);
cb(file);
}
outputStream.add = watcher.add.bind(watcher);
outputStream.unwatch = watcher.unwatch.bind(watcher);
outputStream.close = function () {
watcher.close();
outputStream.emit('end');
};

function processEvent(event, filepath) {
var glob = path2glob(filepath, globs, opts);

if (!glob && opts.verbose !== false) {
log('not matched by globs', { relative: filepath });
}
var glob = globs[anymatch(globs, filepath, true)];

opts.path = filepath;

if (!baseForced) opts.base = glob ? glob2base(glob) : undefined;
if (!baseForced) {
opts.base = glob2base(new Glob(glob, opts));
}

if (event === 'deleted' || isDirectory(filepath)) {
// Do not react on directories
if (event === 'addDir' || event === 'unlinkDir') {
return;
}

// Do not stat deleted files
if (event === 'unlink') {
return write(event, null, new File(opts));
}

vinyl.read(filepath, opts, write.bind(null, event));
}

gaze.on('error', outputStream.emit.bind(outputStream, 'error'));
gaze.on('ready', outputStream.emit.bind(outputStream, 'ready'));
gaze.on('end', outputStream.emit.bind(outputStream, 'end'));
function write(event, err, file) {
if (err) {
return outputStream.emit('error', err);
}

outputStream.close = function () { gaze.close(); };
if (opts.verbose !== false) {
log(event, file);
}

file.event = event;
outputStream.push(file);
cb(file);
}

function log(event, file) {
var msg = [util.colors.magenta(file.relative), 'was', event];
if (opts.name) { msg.unshift(util.colors.cyan(opts.name) + ' saw'); }

if (opts.name) {
msg.unshift(util.colors.cyan(opts.name) + ' saw');
}

util.log.apply(util, msg);
}

Expand Down
8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
"coverage": "istanbul cover node_modules/.bin/_mocha --report html -- -R spec",
"coveralls": "istanbul cover _mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | coveralls && rm -rf ./coverage"
},
"files": [
"index.js"
],
"repository": {
"type": "git",
"url": "git://github.com/floatdrop/gulp-watch.git"
Expand All @@ -36,10 +39,11 @@
"touch": "0.0.3"
},
"dependencies": {
"gaze": "0.5.x",
"anymatch": "^1.1.0",
"chokidar": "https://github.com/paulmillr/chokidar/tarball/bb1ceee4044aa6a0e275adbb12ebc08fc28ac784",
"glob": "^4.3.5",
"glob2base": "~0.0.11",
"gulp-util": "~3.0.0",
"path2glob": "0.0.2",
"readable-stream": "^1.0.31",
"vinyl": "^0.4.3",
"vinyl-file": "~1.1.0"
Expand Down
18 changes: 15 additions & 3 deletions test/callback.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,24 @@ describe('callback', function () {
w.close();
});

it('should be called on event', function (done) {
it('should be called on add event', function (done) {
w = watch(fixtures('*.js'), function (file) {
file.relative.should.eql('index.js');
file.event.should.eql('changed');
file.event.should.eql('add');
done();
});
w.on('ready', touch(fixtures('index.js')));
});

it('should be called on add event', function (done) {
w = watch(fixtures('*.js'), function (file) {
if (file.event === 'add') {
touch(fixtures('index.js'))();
}

if (file.event === 'change') {
file.relative.should.eql('index.js');
done();
}
});
});
});
31 changes: 0 additions & 31 deletions test/directory.js

This file was deleted.

19 changes: 9 additions & 10 deletions test/log.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,30 +34,29 @@ describe('log', function () {

it('should print file name', function (done) {
w = watch(fixtures('*.js'));
w.on('ready', touch(fixtures('index.js')));
w.on('data', function () {
w.once('data', function () {
gutilStub.log.calledOnce.should.be.eql(true);
strip(gutilStub.log.firstCall.args.join(' ')).should.eql('index.js was changed');
strip(gutilStub.log.firstCall.args.join(' ')).should.eql('index.js was add');
done();
});
});

it('should print relative file name', function (done) {
w = watch(fixtures('**/*.js'));
w.on('ready', touch(fixtures('folder/index.js')));
w.on('data', function () {
gutilStub.log.calledOnce.should.be.eql(true);
strip(gutilStub.log.firstCall.args.join(' ')).should.eql('folder/index.js was changed');
done();
w.on('data', function (file) {
if (file.relative === 'folder/index.js') {
strip(gutilStub.log.secondCall.args.join(' ')).should.eql('folder/index.js was add');
done();
}
});
});

it('should print custom watcher name', function (done) {
w = watch(fixtures('*.js'), { name: 'Watch' });
w.on('ready', touch(fixtures('index.js')));
w.on('data', function () {
w.once('data', function () {
gutilStub.log.calledOnce.should.be.eql(true);
strip(gutilStub.log.firstCall.args.join(' ')).should.eql('Watch saw index.js was changed');
strip(gutilStub.log.firstCall.args.join(' ')).should.eql('Watch saw index.js was add');
done();
});
});
Expand Down
48 changes: 29 additions & 19 deletions test/stream.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,52 +29,62 @@ describe('stream', function () {

it('should emit added file', function (done) {
w = watch('test/fixtures/*.js');
w.on('ready', touch(fixtures('new.js')));
w.on('data', function (file) {
file.relative.should.eql('new.js');
file.event.should.eql('added');
file.relative.should.eql('index.js');
file.event.should.eql('add');
done();
});
});

it('should emit changed file', function (done) {
it('should emit change event on file change', function (done) {
w = watch(fixtures('*.js'));
w.on('ready', touch(fixtures('index.js')));
w.on('data', function (file) {
file.relative.should.eql('index.js');
file.event.should.eql('changed');
done();
if (file.event === 'change') {
file.relative.should.eql('index.js');
done();
}
});
});

it('should emit changed file with stream contents', function (done) {
w = watch(fixtures('*.js'), { buffer: false });
w.on('ready', touch(fixtures('index.js')));
w.on('data', function (file) {
file.contents.should.have.property('readable', true);
done();
if (file.event === 'add') {
touch(fixtures('index.js'))();
}
if (file.event === 'change') {
file.contents.should.have.property('readable', true);
done();
}
});
});

it('should emit changed file with stats', function (done) {
w = watch(fixtures('*.js'), { buffer: false });
w.on('ready', touch(fixtures('index.js')));
w.on('data', function (file) {
file.should.have.property('stat');
done();
if (file.event === 'add') {
touch(fixtures('index.js'))();
}
if (file.event === 'change') {
file.should.have.property('stat');
done();
}
});
});

it('should emit deleted file with stats', function (done) {
touch(fixtures('created.js'), function () {
w = watch(fixtures('*.js'), { buffer: false });
w.on('ready', function () {
fs.unlinkSync(fixtures('created.js'));
});
w.on('data', function (file) {
file.should.have.property('event', 'deleted');
file.should.have.property('contents', null);
done();
if (file.event === 'add' && file.relative === 'created.js') {
fs.unlinkSync(fixtures('created.js'));
}

if (file.event === 'unlink') {
file.should.have.property('contents', null);
done();
}
});
})();
});
Expand Down

0 comments on commit df9b22a

Please sign in to comment.