From 54633aee3f7066670524203e8688a3be30d5fa17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20H=C3=A4fner?= Date: Sun, 1 Dec 2013 11:30:24 +0100 Subject: [PATCH 1/4] Remove unnecessary parameter --- lib/coffee-script/command.js | 8 ++++---- src/command.coffee | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/coffee-script/command.js b/lib/coffee-script/command.js index 8151cdac1c..1fc492a688 100644 --- a/lib/coffee-script/command.js +++ b/lib/coffee-script/command.js @@ -259,7 +259,7 @@ return compile(); } catch (_error) { e = _error; - removeSource(source, base, true); + removeSource(source, base); return compileJoin(); } } else { @@ -345,7 +345,7 @@ if (!(source === path.dirname(file))) { continue; } - removeSource(file, base, true); + removeSource(file, base); sourcesChanged = true; } if (sourcesChanged) { @@ -353,12 +353,12 @@ } }; - removeSource = function(source, base, removeJs) { + removeSource = function(source, base) { var err, index, jsPath; index = sources.indexOf(source); sources.splice(index, 1); sourceCode.splice(index, 1); - if (removeJs && !opts.join) { + if (!opts.join) { jsPath = outputPath(source, base); try { fs.unlinkSync(jsPath); diff --git a/src/command.coffee b/src/command.coffee index 3a8fe342ca..5ccf65b949 100644 --- a/src/command.coffee +++ b/src/command.coffee @@ -197,7 +197,7 @@ watch = (source, base) -> rewatch() compile() catch e - removeSource source, base, yes + removeSource source, base compileJoin() else throw e @@ -247,17 +247,17 @@ 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 + unless opts.join jsPath = outputPath source, base try fs.unlinkSync jsPath From 73af30b5d83a3326573ca98dfaa7bd88858128a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20H=C3=A4fner?= Date: Sun, 1 Dec 2013 12:03:22 +0100 Subject: [PATCH 2/4] Fixes #3267 -- Remove source maps of deleted source files --- lib/coffee-script/command.js | 27 ++++++++++++++++----------- src/command.coffee | 13 ++++++++----- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/lib/coffee-script/command.js b/lib/coffee-script/command.js index 1fc492a688..dd2354423e 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'); @@ -354,24 +354,29 @@ }; removeSource = function(source, base) { - var err, index, jsPath; + var index; index = sources.indexOf(source); sources.splice(index, 1); sourceCode.splice(index, 1); if (!opts.join) { - jsPath = outputPath(source, base); - try { - fs.unlinkSync(jsPath); - } catch (_error) { - err = _error; - if (err.code !== 'ENOENT') { - throw err; - } - } + silentUnlink(outputPath(source, base)); + silentUnlink(outputPath(source, base, '.map')); return timeLog("removed " + source); } }; + silentUnlink = function(path) { + var err; + try { + return fs.unlinkSync(path); + } catch (_error) { + err = _error; + if (err.code !== 'ENOENT') { + 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 5ccf65b949..dba07d9d7f 100644 --- a/src/command.coffee +++ b/src/command.coffee @@ -258,13 +258,16 @@ removeSource = (source, base) -> sources.splice index, 1 sourceCode.splice index, 1 unless opts.join - jsPath = outputPath source, base - try - fs.unlinkSync jsPath - catch err - throw err unless err.code is 'ENOENT' + 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 is 'ENOENT' + # Get the corresponding output JavaScript path for a source file. outputPath = (source, base, extension=".js") -> basename = helpers.baseFileName source, yes, useWinPathSep From 74cf54a84f2ef1972e6a9edcdb460260a7ff4c19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20H=C3=A4fner?= Date: Mon, 2 Dec 2013 21:05:47 +0100 Subject: [PATCH 3/4] Prettify `watch` --- lib/coffee-script/command.js | 45 ++++++++++++++++++------------------ src/command.coffee | 37 +++++++++++++++-------------- 2 files changed, 40 insertions(+), 42 deletions(-) diff --git a/lib/coffee-script/command.js b/lib/coffee-script/command.js index dd2354423e..a42a00a2f1 100644 --- a/lib/coffee-script/command.js +++ b/lib/coffee-script/command.js @@ -246,24 +246,23 @@ }; watch = function(source, base) { - var compile, compileTimeout, e, prevStats, rewatch, watchErr, watcher; + var compile, compileTimeout, err, prevStats, rewatch, 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); - 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,18 +286,18 @@ }); }); }; - try { - watcher = fs.watch(source, compile); - } catch (_error) { - e = _error; - watchErr(e); - } - return rewatch = function() { + rewatch = function() { if (watcher != null) { watcher.close(); } return watcher = fs.watch(source, compile); }; + try { + return watcher = fs.watch(source, compile); + } catch (_error) { + err = _error; + return watchErr(err); + } }; watchDir = function(source, base) { diff --git a/src/command.coffee b/src/command.coffee index dba07d9d7f..fc7bdfc3d0 100644 --- a/src/command.coffee +++ b/src/command.coffee @@ -186,43 +186,42 @@ 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 - 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 - rewatch = -> watcher?.close() watcher = fs.watch source, compile + try + watcher = fs.watch source, compile + catch err + watchErr err # Watch a directory of files for new additions. watchDir = (source, base) -> From 6804c1065b7136de75800f4af56ba357dd520a0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20H=C3=A4fner?= Date: Wed, 4 Dec 2013 17:11:39 +0100 Subject: [PATCH 4/4] Fix: `EPERM` when deleting watched dirs in Windows * Suppress `EPERM` from watchers * Suppress `EPERM` from `fs.unlink` --- lib/coffee-script/command.js | 48 +++++++++++++++++++++++++----------- src/command.coffee | 39 +++++++++++++++++++++-------- 2 files changed, 63 insertions(+), 24 deletions(-) diff --git a/lib/coffee-script/command.js b/lib/coffee-script/command.js index a42a00a2f1..8a3f03b752 100644 --- a/lib/coffee-script/command.js +++ b/lib/coffee-script/command.js @@ -246,7 +246,7 @@ }; watch = function(source, base) { - var compile, compileTimeout, err, prevStats, rewatch, watchErr, watcher; + var compile, compileTimeout, err, prevStats, rewatch, startWatcher, watchErr, watcher; watcher = null; prevStats = null; compileTimeout = null; @@ -286,14 +286,22 @@ }); }); }; + 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 watcher = fs.watch(source, compile); + return startWatcher(); } catch (_error) { err = _error; return watchErr(err); @@ -301,11 +309,16 @@ }; 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; @@ -316,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++) { @@ -327,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; } } }; @@ -365,12 +385,12 @@ }; silentUnlink = function(path) { - var err; + var err, _ref1; try { return fs.unlinkSync(path); } catch (_error) { err = _error; - if (err.code !== 'ENOENT') { + if ((_ref1 = err.code) !== 'ENOENT' && _ref1 !== 'EPERM') { throw err; } } diff --git a/src/command.coffee b/src/command.coffee index fc7bdfc3d0..cdefb5d1f2 100644 --- a/src/command.coffee +++ b/src/command.coffee @@ -214,33 +214,52 @@ watch = (source, base) -> compileScript(source, code.toString(), base) rewatch() + 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 - watcher = fs.watch source, compile + 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] @@ -265,7 +284,7 @@ silentUnlink = (path) -> try fs.unlinkSync path catch err - throw err unless err.code is 'ENOENT' + throw err unless err.code in ['ENOENT', 'EPERM'] # Get the corresponding output JavaScript path for a source file. outputPath = (source, base, extension=".js") ->