From 23cec1e8e247f8d7f36cad2306fe0b36eae4fc8d Mon Sep 17 00:00:00 2001 From: Caitlin Potter Date: Fri, 8 May 2015 14:20:54 -0400 Subject: [PATCH] build(gulp): use chokidar alone instead of gulp-watch Closes #1759 --- gulpfile.js | 70 ++++++++++++++----------------------- tools/build/watch.js | 83 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 43 deletions(-) create mode 100644 tools/build/watch.js diff --git a/gulpfile.js b/gulpfile.js index e1eae6eb0c..1970b67468 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -16,7 +16,7 @@ var merge = require('merge'); var merge2 = require('merge2'); var path = require('path'); var semver = require('semver'); -var watch = require('gulp-watch'); +var watch = require('./tools/build/watch'); var clean = require('./tools/build/clean'); var transpile = require('./tools/build/transpile'); @@ -222,9 +222,7 @@ gulp.task('build/checkCircularDependencies', function (done) { // ------------------ // web servers gulp.task('serve.js.dev', ['build.js.dev'], function(neverDone) { - watch('modules/**', function() { - gulp.start('!broccoli.js.dev'); - }); + watch('modules/**', '!broccoli.js.dev'); jsserve(gulp, gulpPlugins, { path: CONFIG.dest.js.dev.es5, @@ -304,7 +302,7 @@ function createDocsTasks(publicBuild) { gulp.task(taskPrefix, [taskPrefix + '/assets', taskPrefix + '/app', taskPrefix + '/dgeni']); gulp.task(taskPrefix + '/watch', function() { - return watch('docs/app/**/*', [taskPrefix + '/app']); + return watch('docs/app/**/*', { ignoreInitial: false }, [taskPrefix + '/app']); }); gulp.task(taskPrefix + '/test', function (done) { @@ -372,20 +370,17 @@ gulp.task('test.unit.js', ['build.js.dev'], function (neverDone) { 'check-format' ); - watch('modules/**', function() { - runSequence( - '!broccoli.js.dev', - '!test.unit.js/karma-run' - ); - }); + watch('modules/**', [ + '!broccoli.js.dev', + '!test.unit.js/karma-run' + ]); }); gulp.task('watch.js.dev', ['build.js.dev'], function (neverDone) { - watch('modules/**', function() { - runSequence( - '!broccoli.js.dev' - ); - }); + watch('modules/**', [ + '!broccoli.js.dev', + '!test.unit.js/karma-run', + ]); }); @@ -404,19 +399,16 @@ gulp.task('!test.unit.js/karma-run', function(done) { gulp.task('test.unit.dart', ['build/tree.dart'], function (done) { - runSequence( '!test.unit.dart/karma-server', '!test.unit.dart/karma-run' ); - watch('modules/angular2/**', function() { - runSequence( - '!build/tree.dart', - 'build/format.dart', - '!test.unit.dart/karma-run' - ); - }); + watch('modules/angular2/**', [ + '!build/tree.dart', + 'build/format.dart', + '!test.unit.dart/karma-run' + ]); }); gulp.task('!test.unit.dart/karma-run', function (done) { @@ -454,37 +446,29 @@ gulp.task('test.unit.cjs/ci', function(done) { gulp.task('test.unit.cjs', ['build/clean.js', 'build.tools'], function (done) { - function buildAndTest() { - runSequence( - '!build.js.cjs', - 'test.unit.cjs/ci' - ); - } + var buildAndTest = [ + '!build.js.cjs', + 'test.unit.cjs/ci' + ]; - buildAndTest(); - - watch('modules/**', buildAndTest); + watch('modules/**', { ignoreInitial: false }, buildAndTest); }); gulp.task('test.unit.tools/ci', function(done) { fork('./tools/traceur-jasmine', ['dist/tools/**/*.spec.js'], { stdio: 'inherit' - }).on('close', done); + }).on('close', done.bind(null, null)); }); gulp.task('test.unit.tools', ['build/clean.tools'], function(done) { - function buildAndTest() { - runSequence( - '!build.tools', - 'test.unit.tools/ci' - ); - } + var buildAndTest = [ + '!build.tools', + 'test.unit.tools/ci' + ]; - buildAndTest(); - - watch('tools/**', buildAndTest); + watch(['tools/**', '!tools/**/test-fixtures/**'], {ignoreInitial: false}, buildAndTest); }); diff --git a/tools/build/watch.js b/tools/build/watch.js new file mode 100644 index 0000000000..fb8948c6bd --- /dev/null +++ b/tools/build/watch.js @@ -0,0 +1,83 @@ +var chokidar = require('chokidar'); +var runSequence = require('run-sequence'); +var path = require('path'); + +function watch(globs, opts, tasks) { + if (typeof opts !== 'object' || Array.isArray(opts)) { + tasks = opts; + opts = {}; + } + + var useRunSequence = typeof tasks !== 'function'; + var runTasks; + + if (useRunSequence) { + if (!Array.isArray(tasks)) tasks = [tasks]; + tasks = tasks.slice(); + tasks.push(tasksDone); + runTasks = function runTaskSequence() { + runSequence.apply(null, tasks); + } + } else { + var sync = tasks.length === 0; + runTasks = function runCallback() { + try { + tasks(tasksDone); + if (sync) tasksDone(); + } catch (e) { + return tasksDone(e); + } + } + } + + var events = opts.events = opts.events || ['add', 'change', 'unlink']; + if (opts.ignoreInitial === undefined) opts.ignoreInitial = true; + var delay = opts.delay; + if (delay === undefined) delay = 100; + + var watcher = chokidar.watch(globs, opts). + on('all', handleEvent). + on('error', function(err) { + throw err; + }); + + var close = watcher.close.bind(watcher); + watcher.close = function() { + if (timeoutId !== null) clearTimeout(timeoutId); + close(); + } + + var eventsRecorded = 0; // Number of events recorded + var timeoutId = null; // If non-null, event capture window is open + + return watcher; + + function handleEvent(event, filepath) { + // Ignore unwatched events + if (events.indexOf(event) < 0) return; + + // Increment number of events captured in this window + ++eventsRecorded; + + if (timeoutId === null) { + timeoutId = setTimeout(invokeCallback, delay); + } + } + + function invokeCallback() { + eventsRecorded = 0; + runTasks(); + } + + function tasksDone(err) { + if (err) throw err; + if (eventsRecorded) { + // eventsRecorded has increased during the run, run again on the next turn + timeoutId = setTimeout(invokeCallback, 0); + } else { + timeoutId = null; + } + } +} + +module.exports = watch;