diff --git a/lib/coffee-script/command.js b/lib/coffee-script/command.js index 8151cdac..8a3f03b7 100644 --- a/lib/coffee-script/command.js +++ b/lib/coffee-script/command.js @@ -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) { diff --git a/src/command.coffee b/src/command.coffee index 3a8fe342..cdefb5d1 100644 --- a/src/command.coffee +++ b/src/command.coffee @@ -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