diff --git a/services/clsi/Gruntfile.coffee b/services/clsi/Gruntfile.coffee index 90f9be1608..09d37346cf 100644 --- a/services/clsi/Gruntfile.coffee +++ b/services/clsi/Gruntfile.coffee @@ -50,6 +50,7 @@ module.exports = (grunt) -> unit: options: reporter: "spec" + grep: grunt.option("grep") src: ["test/unit/js/**/*.js"] acceptance: options: diff --git a/services/clsi/app/coffee/OutputFileFinder.coffee b/services/clsi/app/coffee/OutputFileFinder.coffee index 6df377584d..634b3421c0 100644 --- a/services/clsi/app/coffee/OutputFileFinder.coffee +++ b/services/clsi/app/coffee/OutputFileFinder.coffee @@ -1,7 +1,7 @@ async = require "async" fs = require "fs" Path = require "path" -wrench = require "wrench" +spawn = require("child_process").spawn module.exports = OutputFileFinder = findOutputFiles: (resources, directory, callback = (error, outputFiles) ->) -> @@ -16,44 +16,37 @@ module.exports = OutputFileFinder = for file in allFiles do (file) -> jobs.push (callback) -> - if incomingResources[file.path] + if incomingResources[file] return callback() else - OutputFileFinder._isDirectory Path.join(directory, file.path), (error, directory) -> - return callback(error) if error? - if !directory - outputFiles.push file - callback() + outputFiles.push { + path: file + type: file.match(/\.([^\.]+)$/)?[1] + } + callback() async.series jobs, (error) -> return callback(error) if error? callback null, outputFiles - _isDirectory: (path, callback = (error, directory) ->) -> - fs.stat path, (error, stat) -> - callback error, stat?.isDirectory() - - _getAllFiles: (directory, _callback = (error, outputFiles) ->) -> - callback = (error, outputFiles) -> - _callback(error, outputFiles) + _getAllFiles: (directory, _callback = (error, fileList) ->) -> + callback = (error, fileList) -> + _callback(error, fileList) _callback = () -> - outputFiles = [] - - wrench.readdirRecursive directory, (error, files) => - if error? - if error.code == "ENOENT" - # Directory doesn't exist, which is not a problem - return callback(null, []) - else - return callback(error) - - # readdirRecursive returns multiple times and finishes with a null response - if !files? - return callback(null, outputFiles) - - for file in files - outputFiles.push - path: file - type: file.match(/\.([^\.]+)$/)?[1] + proc = spawn("find", [directory, "-type", "f"]) + stdout = "" + proc.stdout.on "data", (chunk) -> + stdout += chunk.toString() + proc.on "error", callback + proc.on "close", (code) -> + if code != 0 + error = new Error("find returned non-zero exit code: #{code}") + return callback(error) + + fileList = stdout.trim().split("\n") + fileList = fileList.map (file) -> + # Strip leading directory + path = Path.relative(directory, file) + return callback null, fileList diff --git a/services/clsi/test/unit/coffee/OutputFileFinderTests.coffee b/services/clsi/test/unit/coffee/OutputFileFinderTests.coffee index b429bf1a5e..76adca4dc8 100644 --- a/services/clsi/test/unit/coffee/OutputFileFinderTests.coffee +++ b/services/clsi/test/unit/coffee/OutputFileFinderTests.coffee @@ -4,29 +4,25 @@ require('chai').should() modulePath = require('path').join __dirname, '../../../app/js/OutputFileFinder' path = require "path" expect = require("chai").expect +EventEmitter = require("events").EventEmitter describe "OutputFileFinder", -> beforeEach -> @OutputFileFinder = SandboxedModule.require modulePath, requires: "fs": @fs = {} - "wrench": @wrench = {} + "child_process": spawn: @spawn = sinon.stub() @directory = "/test/dir" @callback = sinon.stub() describe "findOutputFiles", -> beforeEach -> @resource_path = "resource/path.tex" - @output_paths = ["output.pdf", "extra", "extra/file.tex"] + @output_paths = ["output.pdf", "extra/file.tex"] + @all_paths = @output_paths.concat [@resource_path] @resources = [ path: @resource_path = "resource/path.tex" ] - @OutputFileFinder._isDirectory = (dirPath, callback = (error, directory) ->) => - callback null, dirPath == path.join(@directory, "extra") - - @wrench.readdirRecursive = (dir, callback) => - callback(null, [@resource_path].concat(@output_paths)) - callback(null, null) - sinon.spy @wrench, "readdirRecursive" + @OutputFileFinder._getAllFiles = sinon.stub().callsArgWith(1, null, @all_paths) @OutputFileFinder.findOutputFiles @resources, @directory, (error, @outputFiles) => it "should only return the output files, not directories or resource paths", -> @@ -37,5 +33,24 @@ describe "OutputFileFinder", -> path: "extra/file.tex", type: "tex" }] - + + describe "_getAllFiles", -> + beforeEach -> + @proc = new EventEmitter() + @proc.stdout = new EventEmitter() + @spawn.returns @proc + @directory = "/base/dir" + @OutputFileFinder._getAllFiles @directory, @callback + + @proc.stdout.emit( + "data", + ["/base/dir/main.tex", "/base/dir/chapters/chapter1.tex"].join("\n") + "\n" + ) + @proc.emit "close", 0 + + it "should call the callback with the relative file paths", -> + @callback.calledWith( + null, + ["main.tex", "chapters/chapter1.tex"] + ).should.equal true