add: Stat polling support while fs.watch doesn't work.

Add a new cli option: -g --polling [SPAN]

    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.
This commit is contained in:
Yad Smood
2013-10-21 15:26:20 +08:00
parent c22707cd53
commit 2853e718f2
2 changed files with 62 additions and 14 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'], ['-g', '--polling [SPAN]', 'use the state polling watch mode']];
opts = {};
@@ -283,24 +283,37 @@
});
};
try {
watcher = fs.watch(source, compile);
if (opts.polling) {
fs.watchFile(source, {
interval: parseInt(opts.polling)
}, compile);
} else {
watcher = fs.watch(source, compile);
}
} catch (_error) {
e = _error;
watchErr(e);
}
return rewatch = function() {
if (watcher != null) {
watcher.close();
if (opts.polling) {
fs.unwatchFile(source);
return fs.watchFile(source, {
interval: parseInt(opts.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) {
@@ -309,7 +322,11 @@
if (err.code !== 'ENOENT') {
throw err;
}
watcher.close();
if (opts.polling) {
fs.unwatchFile(source);
} else {
watcher.close();
}
return unwatchDir(source, base);
}
_results = [];
@@ -331,7 +348,14 @@
return _results;
});
});
});
};
if (opts.polling) {
return fs.watchFile(source, {
interval: parseInt(opts.polling)
}, compile);
} else {
return watcher = fs.watch(source, compile);
}
} catch (_error) {
e = _error;
if (e.code !== 'ENOENT') {

View File

@@ -51,6 +51,7 @@ SWITCHES = [
['-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']
['-g', '--polling [SPAN]', 'use the state polling watch mode']
]
# Top-level objects shared by all the functions.
@@ -207,26 +208,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.polling
fs.watchFile source, { interval: parseInt(opts.polling) }, compile
else
watcher = fs.watch source, compile
catch e
watchErr e
rewatch = ->
watcher?.close()
watcher = fs.watch source, compile
if opts.polling
fs.unwatchFile source
fs.watchFile source, { interval: parseInt(opts.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.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
@@ -234,6 +252,12 @@ watchDir = (source, base) ->
sources.push file
sourceCode.push null
compilePath file, no, base
if opts.polling
fs.watchFile source, { interval: parseInt(opts.polling) }, compile
else
watcher = fs.watch source, compile
catch e
throw e unless e.code is 'ENOENT'