diff --git a/lib/bsb b/lib/bsb index 0a9f739066..6b642d54de 100755 --- a/lib/bsb +++ b/lib/bsb @@ -102,6 +102,7 @@ function setUpWebSocket() { * @type {string[]} */ var delegate_args = [] +var watch_mode_delegate_args = [] var process_argv = process.argv for (var i = 2; i < process_argv.length; ++i) { var current = process_argv[i] @@ -123,7 +124,9 @@ for (var i = 2; i < process_argv.length; ++i) { watch_mode = true } else if (current === "-verbose") { verbose = true - + watch_mode_delegate_args.push(current) + } else { + watch_mode_delegate_args.push(current) } } } @@ -249,8 +252,36 @@ if (watch_mode) { var sourcedirs = path.join('lib', 'bs', '.sourcedirs.json') var watch_generated = [] + function getDirsForRelativeSymlinkedPackages (pkgs) { + pkgs = pkgs.slice() + var watched_dirs = [] + var visited = {} + var pkg + var cwd = process.cwd() + //noinspection JSAssignmentUsedAsCondition + while (pkg = pkgs.shift()) { + var pkg_dir = pkg[1] + var stats = fs.lstatSync(pkg_dir) + if (!stats.isSymbolicLink()) continue + pkg_dir = fs.realpathSync(pkg[1]) + if (visited[pkg_dir]) continue + visited[pkg_dir] = true + var pkg_sourcedirs = path.join(pkg_dir, sourcedirs) + var watch_files = getWatchFiles(pkg_sourcedirs) + var dirs = watch_files.dirs + for (var i = 0; i < dirs.length; i++) { + var dir = path.join(pkg_dir, dirs[i]) + if (fs.existsSync(dir)) { + watched_dirs.push(dir) + } + } + pkgs.push.apply(pkgs, watch_files.pkgs) + } + return watched_dirs + } + function watch_build(watch_config) { - var watch_files = watch_config.dirs + var watch_files = watch_config.dirs.concat(getDirsForRelativeSymlinkedPackages(watch_config.pkgs)) watch_generated = watch_config.generated // close and remove all unused watchers watchers = watchers.filter(function (watcher) { @@ -382,7 +413,7 @@ if (watch_mode) { } reasons_to_rebuild = []; var p = child_process - .spawn(bsb_exe, [], { stdio: ['inherit', 'inherit', 'pipe'] }); + .spawn(bsb_exe, watch_mode_delegate_args, { stdio: ['inherit', 'inherit', 'pipe'] }); p.on('exit', build_finished_callback) p.stderr .setEncoding('utf8') @@ -400,10 +431,15 @@ if (watch_mode) { if (validEvent(event, reason)) { dlog(`Event ${event} ${reason}`); reasons_to_rebuild.push([event, reason]) - if (needRebuild()) { - if (process.env.BS_WATCH_CLEAR && console.clear) {console.clear()} - build() - } + // Some editors are using temporary files to store edits. + // This results in two sync change events: change + rename and two sync builds. + // Using setImmediate will ensure that only one build done. + setImmediate(() => { + if (needRebuild()) { + if (process.env.BS_WATCH_CLEAR && console.clear) {console.clear()} + build() + } + }) } } @@ -411,7 +447,7 @@ if (watch_mode) { if (fs.existsSync(file)) { return JSON.parse(fs.readFileSync(file, 'utf8')) } else { - return { dirs: [], generated: [] } + return { dirs: [], pkgs: [], generated: [] } } }