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
(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; };
fs = require('fs');
@ -246,24 +246,23 @@
};
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;
compileTimeout = null;
watchErr = function(e) {
if (e.code === 'ENOENT') {
if (sources.indexOf(source) === -1) {
return;
}
try {
rewatch();
return compile();
} catch (_error) {
e = _error;
removeSource(source, base, true);
return compileJoin();
}
} else {
throw e;
watchErr = function(err) {
if (err.code !== 'ENOENT') {
throw err;
}
if (__indexOf.call(sources, source) < 0) {
return;
}
try {
rewatch();
return compile();
} catch (_error) {
removeSource(source, base);
return compileJoin();
}
};
compile = function() {
@ -287,26 +286,39 @@
});
});
};
try {
watcher = fs.watch(source, compile);
} catch (_error) {
e = _error;
watchErr(e);
}
return rewatch = function() {
startWatcher = function() {
return watcher = fs.watch(source).on('change', compile).on('error', function(err) {
if (err.code !== 'EPERM') {
throw err;
}
return removeSource(source, base);
});
};
rewatch = function() {
if (watcher != null) {
watcher.close();
}
return watcher = fs.watch(source, compile);
return startWatcher();
};
try {
return startWatcher();
} catch (_error) {
err = _error;
return watchErr(err);
}
};
watchDir = function(source, base) {
var e, readdirTimeout, watcher;
var err, readdirTimeout, startWatcher, stopWatcher, watcher;
watcher = null;
readdirTimeout = null;
try {
watchedDirs[source] = true;
return watcher = fs.watch(source, function() {
startWatcher = function() {
return watcher = fs.watch(source).on('error', function(err) {
if (err.code !== 'EPERM') {
throw err;
}
return stopWatcher();
}).on('change', function() {
clearTimeout(readdirTimeout);
return readdirTimeout = wait(25, function() {
var err, file, files, _i, _len, _results;
@ -317,8 +329,7 @@
if (err.code !== 'ENOENT') {
throw err;
}
watcher.close();
return removeSourceDir(source, base);
return stopWatcher();
}
_results = [];
for (_i = 0, _len = files.length; _i < _len; _i++) {
@ -328,10 +339,18 @@
return _results;
});
});
};
stopWatcher = function() {
watcher.close();
return removeSourceDir(source, base);
};
watchedDirs[source] = true;
try {
return startWatcher();
} catch (_error) {
e = _error;
if (e.code !== 'ENOENT') {
throw e;
err = _error;
if (err.code !== 'ENOENT') {
throw err;
}
}
};
@ -345,7 +364,7 @@
if (!(source === path.dirname(file))) {
continue;
}
removeSource(file, base, true);
removeSource(file, base);
sourcesChanged = true;
}
if (sourcesChanged) {
@ -353,25 +372,30 @@
}
};
removeSource = function(source, base, removeJs) {
var err, index, jsPath;
removeSource = function(source, base) {
var index;
index = sources.indexOf(source);
sources.splice(index, 1);
sourceCode.splice(index, 1);
if (removeJs && !opts.join) {
jsPath = outputPath(source, base);
try {
fs.unlinkSync(jsPath);
} catch (_error) {
err = _error;
if (err.code !== 'ENOENT') {
throw err;
}
}
if (!opts.join) {
silentUnlink(outputPath(source, base));
silentUnlink(outputPath(source, base, '.map'));
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) {
var basename, dir, srcDir;
if (extension == null) {

View File

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