Resolved an issue that could occur while compiling with the --join option which would cause the compiler to silently fail with no resulting output file.

While recursively traversing a source directory, if a directory was encountered containing either no .coffee files (ex. an .svn metadata directory) or where the last file processed in that directory was not a .coffee file, compileJoin() might never be called.

This issue was originally introduced by a (well-needed) optimization in commit dc272a680b.

In join mode, anytime the 'unprocessed' count is decremented, the remaining file count should be evaluated to determine if it is time to run compileJoin().  Previously, compileJoin() would only ever be called in one of the four possible terminating branches of this recursive asynchronous operation.
This commit is contained in:
John Yanarella 2011-08-22 13:32:54 -04:00
parent 3ef0c1c88a
commit 0bf0f6d721
2 changed files with 47 additions and 33 deletions

View File

@ -37,27 +37,39 @@
return compileScripts();
};
compileScripts = function() {
var base, compile, source, unprocessed, _i, _j, _len, _len2, _results;
var base, compile, remaining_files, source, trackCompleteFiles, trackUnprocessedFiles, unprocessed, _i, _j, _len, _len2, _results;
unprocessed = [];
remaining_files = function() {
var total, x, _i, _len;
total = 0;
for (_i = 0, _len = unprocessed.length; _i < _len; _i++) {
x = unprocessed[_i];
total += x;
}
return total;
};
trackUnprocessedFiles = function(sourceIndex, fileCount) {
var _ref2;
if ((_ref2 = unprocessed[sourceIndex]) == null) unprocessed[sourceIndex] = 0;
return unprocessed[sourceIndex] += fileCount;
};
trackCompleteFiles = function(sourceIndex, fileCount) {
unprocessed[sourceIndex] -= fileCount;
if (opts.join) {
if (helpers.compact(contents).length > 0 && remaining_files() === 0) {
return compileJoin();
}
}
};
for (_i = 0, _len = sources.length; _i < _len; _i++) {
source = sources[_i];
unprocessed[sources.indexOf(source)] = 1;
trackUnprocessedFiles(sources.indexOf(source), 1);
}
_results = [];
for (_j = 0, _len2 = sources.length; _j < _len2; _j++) {
source = sources[_j];
base = path.join(source);
compile = function(source, sourceIndex, topLevel) {
var remaining_files;
remaining_files = function() {
var total, x, _k, _len3;
total = 0;
for (_k = 0, _len3 = unprocessed.length; _k < _len3; _k++) {
x = unprocessed[_k];
total += x;
}
return total;
};
return path.exists(source, function(exists) {
if (topLevel && !exists && source.slice(-7) !== '.coffee') {
return compile("" + source + ".coffee", sourceIndex, topLevel);
@ -69,29 +81,26 @@
return fs.readdir(source, function(err, files) {
var file, _k, _len3;
if (err) throw err;
unprocessed[sourceIndex] += files.length;
trackUnprocessedFiles(sourceIndex, files.length);
for (_k = 0, _len3 = files.length; _k < _len3; _k++) {
file = files[_k];
compile(path.join(source, file), sourceIndex);
}
return unprocessed[sourceIndex] -= 1;
return trackCompleteFiles(sourceIndex, 1);
});
} else if (topLevel || path.extname(source) === '.coffee') {
fs.readFile(source, function(err, code) {
if (err) throw err;
unprocessed[sourceIndex] -= 1;
if (opts.join) {
contents[sourceIndex] = helpers.compact([contents[sourceIndex], code.toString()]).join('\n');
if (helpers.compact(contents).length > 0 && remaining_files() === 0) {
return compileJoin();
}
} else {
return compileScript(source, code.toString(), base);
compileScript(source, code.toString(), base);
}
return trackCompleteFiles(sourceIndex, 1);
});
if (opts.watch && !opts.join) return watch(source, base);
} else {
return unprocessed[sourceIndex] -= 1;
return trackCompleteFiles(sourceIndex, 1);
}
});
});

View File

@ -75,42 +75,47 @@ exports.run = ->
# '.coffee' extension source files in it and all subdirectories.
compileScripts = ->
unprocessed = []
remaining_files = ->
total = 0
total += x for x in unprocessed
total
trackUnprocessedFiles = (sourceIndex, fileCount) ->
unprocessed[sourceIndex] ?= 0
unprocessed[sourceIndex] += fileCount
trackCompleteFiles = (sourceIndex, fileCount) ->
unprocessed[sourceIndex] -= fileCount
if opts.join
if helpers.compact(contents).length > 0 and remaining_files() == 0
compileJoin()
for source in sources
unprocessed[sources.indexOf(source)]=1
trackUnprocessedFiles sources.indexOf(source), 1
for source in sources
base = path.join(source)
compile = (source, sourceIndex, topLevel) ->
remaining_files = ->
total = 0
total += x for x in unprocessed
total
path.exists source, (exists) ->
if topLevel and not exists and source[-7..] isnt '.coffee'
return compile "#{source}.coffee", sourceIndex, topLevel
return compile "#{source}.coffee", sourceIndex, topLevel
throw new Error "File not found: #{source}" if topLevel and not exists
fs.stat source, (err, stats) ->
throw err if err
if stats.isDirectory()
fs.readdir source, (err, files) ->
throw err if err
unprocessed[sourceIndex] += files.length
trackUnprocessedFiles sourceIndex, files.length
for file in files
compile path.join(source, file), sourceIndex
unprocessed[sourceIndex] -= 1
trackCompleteFiles sourceIndex, 1
else if topLevel or path.extname(source) is '.coffee'
fs.readFile source, (err, code) ->
throw err if err
unprocessed[sourceIndex] -= 1
if opts.join
contents[sourceIndex] = helpers.compact([contents[sourceIndex], code.toString()]).join('\n')
if helpers.compact(contents).length > 0 and remaining_files() == 0
compileJoin()
else
compileScript(source, code.toString(), base)
trackCompleteFiles sourceIndex, 1
watch source, base if opts.watch and not opts.join
else
unprocessed[sourceIndex] -= 1
trackCompleteFiles sourceIndex, 1
compile source, sources.indexOf(source), true
# Compile a single source script, containing the given code, according to the