Merge pull request #3212 from ysmood/issue3210

add: Stat polling support while `fs.watch` doesn't work.
This commit is contained in:
Jeremy Ashkenas
2013-11-15 11:09:50 -08:00
2 changed files with 79 additions and 31 deletions

View File

@@ -38,7 +38,7 @@
BANNER = 'Usage: coffee [options] path/to/script.coffee -- [args]\n\nIf called without options, `coffee` will run your script.';
SWITCHES = [['-b', '--bare', 'compile without a top-level function wrapper'], ['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-e', '--eval', 'pass a string from the command line as input'], ['-h', '--help', 'display this help message'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling'], ['-m', '--map', 'generate source map and save as .map files'], ['-n', '--nodes', 'print out the parse tree that the parser produces'], ['--nodejs [ARGS]', 'pass options directly to the "node" binary'], ['--no-header', 'suppress the "Generated by" header'], ['-o', '--output [DIR]', 'set the output directory for compiled JavaScript'], ['-p', '--print', 'print out the compiled JavaScript'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-l', '--literate', 'treat stdio as literate style coffee-script'], ['-t', '--tokens', 'print out the tokens that the lexer/rewriter produce'], ['-v', '--version', 'display the version number'], ['-w', '--watch', 'watch scripts for changes and rerun commands']];
SWITCHES = [['-b', '--bare', 'compile without a top-level function wrapper'], ['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-e', '--eval', 'pass a string from the command line as input'], ['-h', '--help', 'display this help message'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling'], ['-m', '--map', 'generate source map and save as .map files'], ['-n', '--nodes', 'print out the parse tree that the parser produces'], ['--nodejs [ARGS]', 'pass options directly to the "node" binary'], ['--no-header', 'suppress the "Generated by" header'], ['-o', '--output [DIR]', 'set the output directory for compiled JavaScript'], ['-p', '--print', 'print out the compiled JavaScript'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-l', '--literate', 'treat stdio as literate style coffee-script'], ['-t', '--tokens', 'print out the tokens that the lexer/rewriter produce'], ['-v', '--version', 'display the version number'], ['-w', '--watch', 'watch scripts for changes and rerun commands'], ['--watch-polling [SPAN]', 'use the state polling watch mode, span unit is millisecond']];
opts = {};
@@ -286,24 +286,37 @@
});
};
try {
watcher = fs.watch(source, compile);
if (opts['watch-polling']) {
fs.watchFile(source, {
interval: parseInt(opts['watch-polling'])
}, compile);
} else {
watcher = fs.watch(source, compile);
}
} catch (_error) {
e = _error;
watchErr(e);
}
return rewatch = function() {
if (watcher != null) {
watcher.close();
if (opts['watch-polling']) {
fs.unwatchFile(source);
return fs.watchFile(source, {
interval: parseInt(opts['watch-polling'])
}, compile);
} else {
if (watcher != null) {
watcher.close();
}
return watcher = fs.watch(source, compile);
}
return watcher = fs.watch(source, compile);
};
};
watchDir = function(source, base) {
var e, readdirTimeout, watcher;
var compile, e, readdirTimeout, watcher;
readdirTimeout = null;
try {
return watcher = fs.watch(source, function() {
compile = function() {
clearTimeout(readdirTimeout);
return readdirTimeout = wait(25, function() {
return fs.readdir(source, function(err, files) {
@@ -312,7 +325,11 @@
if (err.code !== 'ENOENT') {
throw err;
}
watcher.close();
if (opts['watch-polling']) {
fs.unwatchFile(source);
} else {
watcher.close();
}
return unwatchDir(source, base);
}
_results = [];
@@ -334,7 +351,14 @@
return _results;
});
});
});
};
if (opts['watch-polling']) {
return fs.watchFile(source, {
interval: parseInt(opts['watch-polling'])
}, compile);
} else {
return watcher = fs.watch(source, compile);
}
} catch (_error) {
e = _error;
if (e.code !== 'ENOENT') {

View File

@@ -34,23 +34,24 @@ BANNER = '''
# The list of all the valid option flags that `coffee` knows how to handle.
SWITCHES = [
['-b', '--bare', 'compile without a top-level function wrapper']
['-c', '--compile', 'compile to JavaScript and save as .js files']
['-e', '--eval', 'pass a string from the command line as input']
['-h', '--help', 'display this help message']
['-i', '--interactive', 'run an interactive CoffeeScript REPL']
['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling']
['-m', '--map', 'generate source map and save as .map files']
['-n', '--nodes', 'print out the parse tree that the parser produces']
[ '--nodejs [ARGS]', 'pass options directly to the "node" binary']
[ '--no-header', 'suppress the "Generated by" header']
['-o', '--output [DIR]', 'set the output directory for compiled JavaScript']
['-p', '--print', 'print out the compiled JavaScript']
['-s', '--stdio', 'listen for and compile scripts over stdio']
['-l', '--literate', 'treat stdio as literate style coffee-script']
['-t', '--tokens', 'print out the tokens that the lexer/rewriter produce']
['-v', '--version', 'display the version number']
['-w', '--watch', 'watch scripts for changes and rerun commands']
['-b', '--bare', 'compile without a top-level function wrapper']
['-c', '--compile', 'compile to JavaScript and save as .js files']
['-e', '--eval', 'pass a string from the command line as input']
['-h', '--help', 'display this help message']
['-i', '--interactive', 'run an interactive CoffeeScript REPL']
['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling']
['-m', '--map', 'generate source map and save as .map files']
['-n', '--nodes', 'print out the parse tree that the parser produces']
[ '--nodejs [ARGS]', 'pass options directly to the "node" binary']
[ '--no-header', 'suppress the "Generated by" header']
['-o', '--output [DIR]', 'set the output directory for compiled JavaScript']
['-p', '--print', 'print out the compiled JavaScript']
['-s', '--stdio', 'listen for and compile scripts over stdio']
['-l', '--literate', 'treat stdio as literate style coffee-script']
['-t', '--tokens', 'print out the tokens that the lexer/rewriter produce']
['-v', '--version', 'display the version number']
['-w', '--watch', 'watch scripts for changes and rerun commands']
[ '--watch-polling [SPAN]', 'use the state polling watch mode, span unit is millisecond']
]
# Top-level objects shared by all the functions.
@@ -210,26 +211,43 @@ watch = (source, base) ->
rewatch()
try
watcher = fs.watch source, compile
# If state polling mode is enabled, use it.
# Else use the native api.
#
# This is useful while watching remote directory.
# Such as the `fs.watch` won't catch the SMB server's file change event.
if opts['watch-polling']
fs.watchFile source, { interval: parseInt(opts['watch-polling']) }, compile
else
watcher = fs.watch source, compile
catch e
watchErr e
rewatch = ->
watcher?.close()
watcher = fs.watch source, compile
if opts['watch-polling']
fs.unwatchFile source
fs.watchFile source, { interval: parseInt(opts['watch-polling']) }, compile
else
watcher?.close()
watcher = fs.watch source, compile
# Watch a directory of files for new additions.
watchDir = (source, base) ->
readdirTimeout = null
try
watcher = fs.watch source, ->
compile = ->
clearTimeout readdirTimeout
readdirTimeout = wait 25, ->
fs.readdir source, (err, files) ->
if err
throw err unless err.code is 'ENOENT'
watcher.close()
if opts['watch-polling']
fs.unwatchFile source
else
watcher.close()
return unwatchDir source, base
for file in files when not hidden(file) and not notSources[file]
file = path.join source, file
@@ -237,6 +255,12 @@ watchDir = (source, base) ->
sources.push file
sourceCode.push null
compilePath file, no, base
if opts['watch-polling']
fs.watchFile source, { interval: parseInt(opts['watch-polling']) }, compile
else
watcher = fs.watch source, compile
catch e
throw e unless e.code is 'ENOENT'