Merge pull request #3275 from marchaefner/CLI

Fix --watch handling of deleted sources
This commit is contained in:
Jeremy Ashkenas 2013-12-07 22:28:19 -08:00
commit 94e22ab819
2 changed files with 126 additions and 81 deletions

View File

@ -1,6 +1,6 @@
// Generated by CoffeeScript 1.6.3 // Generated by CoffeeScript 1.6.3
(function() { (function() {
var BANNER, CoffeeScript, EventEmitter, SWITCHES, compileJoin, compileOptions, compilePath, compileScript, compileStdio, exec, forkNode, fs, helpers, hidden, joinTimeout, mkdirp, notSources, optionParser, optparse, opts, outputPath, parseOptions, path, printLine, printTokens, printWarn, removeSource, removeSourceDir, sourceCode, sources, spawn, timeLog, usage, useWinPathSep, version, wait, watch, watchDir, watchedDirs, writeJs, _ref, var BANNER, CoffeeScript, EventEmitter, SWITCHES, compileJoin, compileOptions, compilePath, compileScript, compileStdio, exec, forkNode, fs, helpers, hidden, joinTimeout, mkdirp, notSources, optionParser, optparse, opts, outputPath, parseOptions, path, printLine, printTokens, printWarn, removeSource, removeSourceDir, silentUnlink, sourceCode, sources, spawn, timeLog, usage, useWinPathSep, version, wait, watch, watchDir, watchedDirs, writeJs, _ref,
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
fs = require('fs'); fs = require('fs');
@ -246,24 +246,23 @@
}; };
watch = function(source, base) { watch = function(source, base) {
var compile, compileTimeout, e, prevStats, rewatch, watchErr, watcher; var compile, compileTimeout, err, prevStats, rewatch, startWatcher, watchErr, watcher;
watcher = null;
prevStats = null; prevStats = null;
compileTimeout = null; compileTimeout = null;
watchErr = function(e) { watchErr = function(err) {
if (e.code === 'ENOENT') { if (err.code !== 'ENOENT') {
if (sources.indexOf(source) === -1) { throw err;
return; }
} if (__indexOf.call(sources, source) < 0) {
try { return;
rewatch(); }
return compile(); try {
} catch (_error) { rewatch();
e = _error; return compile();
removeSource(source, base, true); } catch (_error) {
return compileJoin(); removeSource(source, base);
} return compileJoin();
} else {
throw e;
} }
}; };
compile = function() { compile = function() {
@ -287,26 +286,39 @@
}); });
}); });
}; };
try { startWatcher = function() {
watcher = fs.watch(source, compile); return watcher = fs.watch(source).on('change', compile).on('error', function(err) {
} catch (_error) { if (err.code !== 'EPERM') {
e = _error; throw err;
watchErr(e); }
} return removeSource(source, base);
return rewatch = function() { });
};
rewatch = function() {
if (watcher != null) { if (watcher != null) {
watcher.close(); watcher.close();
} }
return watcher = fs.watch(source, compile); return startWatcher();
}; };
try {
return startWatcher();
} catch (_error) {
err = _error;
return watchErr(err);
}
}; };
watchDir = function(source, base) { watchDir = function(source, base) {
var e, readdirTimeout, watcher; var err, readdirTimeout, startWatcher, stopWatcher, watcher;
watcher = null;
readdirTimeout = null; readdirTimeout = null;
try { startWatcher = function() {
watchedDirs[source] = true; return watcher = fs.watch(source).on('error', function(err) {
return watcher = fs.watch(source, function() { if (err.code !== 'EPERM') {
throw err;
}
return stopWatcher();
}).on('change', function() {
clearTimeout(readdirTimeout); clearTimeout(readdirTimeout);
return readdirTimeout = wait(25, function() { return readdirTimeout = wait(25, function() {
var err, file, files, _i, _len, _results; var err, file, files, _i, _len, _results;
@ -317,8 +329,7 @@
if (err.code !== 'ENOENT') { if (err.code !== 'ENOENT') {
throw err; throw err;
} }
watcher.close(); return stopWatcher();
return removeSourceDir(source, base);
} }
_results = []; _results = [];
for (_i = 0, _len = files.length; _i < _len; _i++) { for (_i = 0, _len = files.length; _i < _len; _i++) {
@ -328,10 +339,18 @@
return _results; return _results;
}); });
}); });
};
stopWatcher = function() {
watcher.close();
return removeSourceDir(source, base);
};
watchedDirs[source] = true;
try {
return startWatcher();
} catch (_error) { } catch (_error) {
e = _error; err = _error;
if (e.code !== 'ENOENT') { if (err.code !== 'ENOENT') {
throw e; throw err;
} }
} }
}; };
@ -345,7 +364,7 @@
if (!(source === path.dirname(file))) { if (!(source === path.dirname(file))) {
continue; continue;
} }
removeSource(file, base, true); removeSource(file, base);
sourcesChanged = true; sourcesChanged = true;
} }
if (sourcesChanged) { if (sourcesChanged) {
@ -353,25 +372,30 @@
} }
}; };
removeSource = function(source, base, removeJs) { removeSource = function(source, base) {
var err, index, jsPath; var index;
index = sources.indexOf(source); index = sources.indexOf(source);
sources.splice(index, 1); sources.splice(index, 1);
sourceCode.splice(index, 1); sourceCode.splice(index, 1);
if (removeJs && !opts.join) { if (!opts.join) {
jsPath = outputPath(source, base); silentUnlink(outputPath(source, base));
try { silentUnlink(outputPath(source, base, '.map'));
fs.unlinkSync(jsPath);
} catch (_error) {
err = _error;
if (err.code !== 'ENOENT') {
throw err;
}
}
return timeLog("removed " + source); return timeLog("removed " + source);
} }
}; };
silentUnlink = function(path) {
var err, _ref1;
try {
return fs.unlinkSync(path);
} catch (_error) {
err = _error;
if ((_ref1 = err.code) !== 'ENOENT' && _ref1 !== 'EPERM') {
throw err;
}
}
};
outputPath = function(source, base, extension) { outputPath = function(source, base, extension) {
var basename, dir, srcDir; var basename, dir, srcDir;
if (extension == null) { if (extension == null) {

View File

@ -186,85 +186,106 @@ compileJoin = ->
# time the file is updated. May be used in combination with other options, # time the file is updated. May be used in combination with other options,
# such as `--print`. # such as `--print`.
watch = (source, base) -> watch = (source, base) ->
watcher = null
prevStats = null prevStats = null
compileTimeout = null compileTimeout = null
watchErr = (e) -> watchErr = (err) ->
if e.code is 'ENOENT' throw err unless err.code is 'ENOENT'
return if sources.indexOf(source) is -1 return unless source in sources
try try
rewatch() rewatch()
compile() compile()
catch e catch
removeSource source, base, yes removeSource source, base
compileJoin() compileJoin()
else throw e
compile = -> compile = ->
clearTimeout compileTimeout clearTimeout compileTimeout
compileTimeout = wait 25, -> compileTimeout = wait 25, ->
fs.stat source, (err, stats) -> fs.stat source, (err, stats) ->
return watchErr err if err return watchErr err if err
return rewatch() if prevStats and stats.size is prevStats.size and return rewatch() if prevStats and
stats.mtime.getTime() is prevStats.mtime.getTime() stats.size is prevStats.size and
stats.mtime.getTime() is prevStats.mtime.getTime()
prevStats = stats prevStats = stats
fs.readFile source, (err, code) -> fs.readFile source, (err, code) ->
return watchErr err if err return watchErr err if err
compileScript(source, code.toString(), base) compileScript(source, code.toString(), base)
rewatch() rewatch()
try startWatcher = ->
watcher = fs.watch source, compile watcher = fs.watch source
catch e .on 'change', compile
watchErr e .on 'error', (err) ->
throw err unless err.code is 'EPERM'
removeSource source, base
rewatch = -> rewatch = ->
watcher?.close() watcher?.close()
watcher = fs.watch source, compile startWatcher()
try
startWatcher()
catch err
watchErr err
# Watch a directory of files for new additions. # Watch a directory of files for new additions.
watchDir = (source, base) -> watchDir = (source, base) ->
watcher = null
readdirTimeout = null readdirTimeout = null
try
watchedDirs[source] = yes startWatcher = ->
watcher = fs.watch source, -> watcher = fs.watch source
.on 'error', (err) ->
throw err unless err.code is 'EPERM'
stopWatcher()
.on 'change', ->
clearTimeout readdirTimeout clearTimeout readdirTimeout
readdirTimeout = wait 25, -> readdirTimeout = wait 25, ->
try try
files = fs.readdirSync source files = fs.readdirSync source
catch err catch err
throw err unless err.code is 'ENOENT' throw err unless err.code is 'ENOENT'
watcher.close() return stopWatcher()
return removeSourceDir source, base
for file in files for file in files
compilePath (path.join source, file), no, base compilePath (path.join source, file), no, base
catch e
throw e unless e.code is 'ENOENT' stopWatcher = ->
watcher.close()
removeSourceDir source, base
watchedDirs[source] = yes
try
startWatcher()
catch err
throw err unless err.code is 'ENOENT'
removeSourceDir = (source, base) -> removeSourceDir = (source, base) ->
delete watchedDirs[source] delete watchedDirs[source]
sourcesChanged = no sourcesChanged = no
for file in sources when source is path.dirname file for file in sources when source is path.dirname file
removeSource file, base, yes removeSource file, base
sourcesChanged = yes sourcesChanged = yes
compileJoin() if sourcesChanged compileJoin() if sourcesChanged
# Remove a file from our source list, and source code cache. Optionally remove # Remove a file from our source list, and source code cache. Optionally remove
# the compiled JS version as well. # the compiled JS version as well.
removeSource = (source, base, removeJs) -> removeSource = (source, base) ->
index = sources.indexOf source index = sources.indexOf source
sources.splice index, 1 sources.splice index, 1
sourceCode.splice index, 1 sourceCode.splice index, 1
if removeJs and not opts.join unless opts.join
jsPath = outputPath source, base silentUnlink outputPath source, base
try silentUnlink outputPath source, base, '.map'
fs.unlinkSync jsPath
catch err
throw err unless err.code is 'ENOENT'
timeLog "removed #{source}" timeLog "removed #{source}"
silentUnlink = (path) ->
try
fs.unlinkSync path
catch err
throw err unless err.code in ['ENOENT', 'EPERM']
# Get the corresponding output JavaScript path for a source file. # Get the corresponding output JavaScript path for a source file.
outputPath = (source, base, extension=".js") -> outputPath = (source, base, extension=".js") ->
basename = helpers.baseFileName source, yes, useWinPathSep basename = helpers.baseFileName source, yes, useWinPathSep