Merge branch 'master' into sk-node-upgrade
This commit is contained in:
@@ -56,6 +56,7 @@ app.param 'build_id', (req, res, next, build_id) ->
|
|||||||
|
|
||||||
|
|
||||||
app.post "/project/:project_id/compile", bodyParser.json(limit: "5mb"), CompileController.compile
|
app.post "/project/:project_id/compile", bodyParser.json(limit: "5mb"), CompileController.compile
|
||||||
|
app.post "/project/:project_id/compile/stop", CompileController.stopCompile
|
||||||
app.delete "/project/:project_id", CompileController.clearCache
|
app.delete "/project/:project_id", CompileController.clearCache
|
||||||
|
|
||||||
app.get "/project/:project_id/sync/code", CompileController.syncFromCode
|
app.get "/project/:project_id/sync/code", CompileController.syncFromCode
|
||||||
@@ -65,6 +66,7 @@ app.get "/project/:project_id/status", CompileController.status
|
|||||||
|
|
||||||
# Per-user containers
|
# Per-user containers
|
||||||
app.post "/project/:project_id/user/:user_id/compile", bodyParser.json(limit: "5mb"), CompileController.compile
|
app.post "/project/:project_id/user/:user_id/compile", bodyParser.json(limit: "5mb"), CompileController.compile
|
||||||
|
app.post "/project/:project_id/user/:user_id/compile/stop", CompileController.stopCompile
|
||||||
app.delete "/project/:project_id/user/:user_id", CompileController.clearCache
|
app.delete "/project/:project_id/user/:user_id", CompileController.clearCache
|
||||||
|
|
||||||
app.get "/project/:project_id/user/:user_id/sync/code", CompileController.syncFromCode
|
app.get "/project/:project_id/user/:user_id/sync/code", CompileController.syncFromCode
|
||||||
|
|||||||
@@ -4,14 +4,41 @@ logger = require "logger-sharelatex"
|
|||||||
logger.info "using standard command runner"
|
logger.info "using standard command runner"
|
||||||
|
|
||||||
module.exports = CommandRunner =
|
module.exports = CommandRunner =
|
||||||
run: (project_id, command, directory, image, timeout, callback = (error) ->) ->
|
run: (project_id, command, directory, image, timeout, environment, callback = (error) ->) ->
|
||||||
command = (arg.replace('$COMPILE_DIR', directory) for arg in command)
|
command = (arg.replace('$COMPILE_DIR', directory) for arg in command)
|
||||||
logger.log project_id: project_id, command: command, directory: directory, "running command"
|
logger.log project_id: project_id, command: command, directory: directory, "running command"
|
||||||
logger.warn "timeouts and sandboxing are not enabled with CommandRunner"
|
logger.warn "timeouts and sandboxing are not enabled with CommandRunner"
|
||||||
|
|
||||||
proc = spawn command[0], command.slice(1), stdio: "inherit", cwd: directory
|
# merge environment settings
|
||||||
|
env = {}
|
||||||
|
env[key] = value for key, value of process.env
|
||||||
|
env[key] = value for key, value of environment
|
||||||
|
|
||||||
|
# run command as detached process so it has its own process group (which can be killed if needed)
|
||||||
|
proc = spawn command[0], command.slice(1), stdio: "inherit", cwd: directory, detached: true, env: env
|
||||||
|
|
||||||
proc.on "error", (err)->
|
proc.on "error", (err)->
|
||||||
logger.err err:err, project_id:project_id, command: command, directory: directory, "error running command"
|
logger.err err:err, project_id:project_id, command: command, directory: directory, "error running command"
|
||||||
callback(err)
|
callback(err)
|
||||||
proc.on "close", () ->
|
|
||||||
callback()
|
proc.on "close", (code, signal) ->
|
||||||
|
logger.info code:code, signal:signal, project_id:project_id, "command exited"
|
||||||
|
if signal is 'SIGTERM' # signal from kill method below
|
||||||
|
err = new Error("terminated")
|
||||||
|
err.terminated = true
|
||||||
|
return callback(err)
|
||||||
|
else if code is 1 # exit status from chktex
|
||||||
|
err = new Error("exited")
|
||||||
|
err.code = code
|
||||||
|
return callback(err)
|
||||||
|
else
|
||||||
|
callback()
|
||||||
|
|
||||||
|
return proc.pid # return process id to allow job to be killed if necessary
|
||||||
|
|
||||||
|
kill: (pid, callback = (error) ->) ->
|
||||||
|
try
|
||||||
|
process.kill -pid # kill all processes in group
|
||||||
|
catch err
|
||||||
|
return callback(err)
|
||||||
|
callback()
|
||||||
|
|||||||
@@ -15,7 +15,11 @@ module.exports = CompileController =
|
|||||||
ProjectPersistenceManager.markProjectAsJustAccessed request.project_id, (error) ->
|
ProjectPersistenceManager.markProjectAsJustAccessed request.project_id, (error) ->
|
||||||
return next(error) if error?
|
return next(error) if error?
|
||||||
CompileManager.doCompile request, (error, outputFiles = []) ->
|
CompileManager.doCompile request, (error, outputFiles = []) ->
|
||||||
if error?
|
if error?.terminated
|
||||||
|
status = "terminated"
|
||||||
|
else if error?.validate
|
||||||
|
status = "validation-#{error.validate}"
|
||||||
|
else if error?
|
||||||
logger.error err: error, project_id: request.project_id, "error running compile"
|
logger.error err: error, project_id: request.project_id, "error running compile"
|
||||||
if error.timedout
|
if error.timedout
|
||||||
status = "timedout"
|
status = "timedout"
|
||||||
@@ -44,6 +48,12 @@ module.exports = CompileController =
|
|||||||
build: file.build
|
build: file.build
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stopCompile: (req, res, next) ->
|
||||||
|
{project_id, user_id} = req.params
|
||||||
|
CompileManager.stopCompile project_id, user_id, (error) ->
|
||||||
|
return next(error) if error?
|
||||||
|
res.sendStatus(204)
|
||||||
|
|
||||||
clearCache: (req, res, next = (error) ->) ->
|
clearCache: (req, res, next = (error) ->) ->
|
||||||
ProjectPersistenceManager.clearProject req.params.project_id, req.params.user_id, (error) ->
|
ProjectPersistenceManager.clearProject req.params.project_id, req.params.user_id, (error) ->
|
||||||
return next(error) if error?
|
return next(error) if error?
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ module.exports = CompileManager =
|
|||||||
compileDir = getCompileDir(request.project_id, request.user_id)
|
compileDir = getCompileDir(request.project_id, request.user_id)
|
||||||
|
|
||||||
timer = new Metrics.Timer("write-to-disk")
|
timer = new Metrics.Timer("write-to-disk")
|
||||||
logger.log project_id: request.project_id, user_id: request.user_id, "starting compile"
|
logger.log project_id: request.project_id, user_id: request.user_id, "syncing resources to disk"
|
||||||
ResourceWriter.syncResourcesToDisk request.project_id, request.resources, compileDir, (error) ->
|
ResourceWriter.syncResourcesToDisk request.project_id, request.resources, compileDir, (error) ->
|
||||||
if error?
|
if error?
|
||||||
logger.err err:error, project_id: request.project_id, user_id: request.user_id, "error writing resources to disk"
|
logger.err err:error, project_id: request.project_id, user_id: request.user_id, "error writing resources to disk"
|
||||||
@@ -42,6 +42,15 @@ module.exports = CompileManager =
|
|||||||
else
|
else
|
||||||
callback()
|
callback()
|
||||||
|
|
||||||
|
# set up environment variables for chktex
|
||||||
|
env = {}
|
||||||
|
if request.check?
|
||||||
|
env['CHKTEX_OPTIONS'] = '-nall -e9 -e10 -w15 -w16'
|
||||||
|
if request.check is 'error'
|
||||||
|
env['CHKTEX_EXIT_ON_ERROR'] = 1
|
||||||
|
if request.check is 'validate'
|
||||||
|
env['CHKTEX_VALIDATE'] = 1
|
||||||
|
|
||||||
injectDraftModeIfRequired (error) ->
|
injectDraftModeIfRequired (error) ->
|
||||||
return callback(error) if error?
|
return callback(error) if error?
|
||||||
timer = new Metrics.Timer("run-compile")
|
timer = new Metrics.Timer("run-compile")
|
||||||
@@ -57,7 +66,24 @@ module.exports = CompileManager =
|
|||||||
compiler: request.compiler
|
compiler: request.compiler
|
||||||
timeout: request.timeout
|
timeout: request.timeout
|
||||||
image: request.imageName
|
image: request.imageName
|
||||||
|
environment: env
|
||||||
}, (error, output, stats, timings) ->
|
}, (error, output, stats, timings) ->
|
||||||
|
# request was for validation only
|
||||||
|
if request.check is "validate"
|
||||||
|
result = if error?.code then "fail" else "pass"
|
||||||
|
error = new Error("validation")
|
||||||
|
error.validate = result
|
||||||
|
# request was for compile, and failed on validation
|
||||||
|
if request.check is "error" and error?.message is 'exited'
|
||||||
|
error = new Error("compilation")
|
||||||
|
error.validate = "fail"
|
||||||
|
# compile was killed by user, was a validation, or a compile which failed validation
|
||||||
|
if error?.terminated or error?.validate
|
||||||
|
OutputFileFinder.findOutputFiles request.resources, compileDir, (err, outputFiles) ->
|
||||||
|
return callback(err) if err?
|
||||||
|
callback(error, outputFiles) # return output files so user can check logs
|
||||||
|
return
|
||||||
|
# compile completed normally
|
||||||
return callback(error) if error?
|
return callback(error) if error?
|
||||||
Metrics.inc("compiles-succeeded")
|
Metrics.inc("compiles-succeeded")
|
||||||
for metric_key, metric_value of stats or {}
|
for metric_key, metric_value of stats or {}
|
||||||
@@ -78,6 +104,10 @@ module.exports = CompileManager =
|
|||||||
OutputCacheManager.saveOutputFiles outputFiles, compileDir, (error, newOutputFiles) ->
|
OutputCacheManager.saveOutputFiles outputFiles, compileDir, (error, newOutputFiles) ->
|
||||||
callback null, newOutputFiles
|
callback null, newOutputFiles
|
||||||
|
|
||||||
|
stopCompile: (project_id, user_id, callback = (error) ->) ->
|
||||||
|
compileName = getCompileName(project_id, user_id)
|
||||||
|
LatexRunner.killLatex compileName, callback
|
||||||
|
|
||||||
clearProject: (project_id, user_id, _callback = (error) ->) ->
|
clearProject: (project_id, user_id, _callback = (error) ->) ->
|
||||||
callback = (error) ->
|
callback = (error) ->
|
||||||
_callback(error)
|
_callback(error)
|
||||||
@@ -163,6 +193,8 @@ module.exports = CompileManager =
|
|||||||
_runSynctex: (args, callback = (error, stdout) ->) ->
|
_runSynctex: (args, callback = (error, stdout) ->) ->
|
||||||
bin_path = Path.resolve(__dirname + "/../../bin/synctex")
|
bin_path = Path.resolve(__dirname + "/../../bin/synctex")
|
||||||
seconds = 1000
|
seconds = 1000
|
||||||
|
if Settings.clsi?.synctexCommandWrapper?
|
||||||
|
[bin_path, args] = Settings.clsi?.synctexCommandWrapper bin_path, args
|
||||||
child_process.execFile bin_path, args, timeout: 10 * seconds, (error, stdout, stderr) ->
|
child_process.execFile bin_path, args, timeout: 10 * seconds, (error, stdout, stderr) ->
|
||||||
if error?
|
if error?
|
||||||
logger.err err:error, args:args, "error running synctex"
|
logger.err err:error, args:args, "error running synctex"
|
||||||
@@ -199,19 +231,20 @@ module.exports = CompileManager =
|
|||||||
wordcount: (project_id, user_id, file_name, image, callback = (error, pdfPositions) ->) ->
|
wordcount: (project_id, user_id, file_name, image, callback = (error, pdfPositions) ->) ->
|
||||||
logger.log project_id:project_id, user_id:user_id, file_name:file_name, image:image, "running wordcount"
|
logger.log project_id:project_id, user_id:user_id, file_name:file_name, image:image, "running wordcount"
|
||||||
file_path = "$COMPILE_DIR/" + file_name
|
file_path = "$COMPILE_DIR/" + file_name
|
||||||
command = [ "texcount", '-inc', file_path, "-out=" + file_path + ".wc"]
|
command = [ "texcount", '-nocol', '-inc', file_path, "-out=" + file_path + ".wc"]
|
||||||
directory = getCompileDir(project_id, user_id)
|
directory = getCompileDir(project_id, user_id)
|
||||||
timeout = 10 * 1000
|
timeout = 10 * 1000
|
||||||
compileName = getCompileName(project_id, user_id)
|
compileName = getCompileName(project_id, user_id)
|
||||||
|
|
||||||
CommandRunner.run compileName, command, directory, image, timeout, (error) ->
|
CommandRunner.run compileName, command, directory, image, timeout, {}, (error) ->
|
||||||
return callback(error) if error?
|
return callback(error) if error?
|
||||||
try
|
fs.readFile directory + "/" + file_name + ".wc", "utf-8", (err, stdout) ->
|
||||||
stdout = fs.readFileSync(directory + "/" + file_name + ".wc", "utf-8")
|
if err?
|
||||||
catch err
|
logger.err err:err, command:command, directory:directory, project_id:project_id, user_id:user_id, "error reading word count output"
|
||||||
logger.err err:err, command:command, directory:directory, project_id:project_id, user_id:user_id, "error reading word count output"
|
return callback(err)
|
||||||
return callback(err)
|
results = CompileManager._parseWordcountFromOutput(stdout)
|
||||||
callback null, CompileManager._parseWordcountFromOutput(stdout)
|
logger.log project_id:project_id, user_id:user_id, wordcount: results, "word count results"
|
||||||
|
callback null, results
|
||||||
|
|
||||||
_parseWordcountFromOutput: (output) ->
|
_parseWordcountFromOutput: (output) ->
|
||||||
results = {
|
results = {
|
||||||
@@ -223,6 +256,8 @@ module.exports = CompileManager =
|
|||||||
elements: 0
|
elements: 0
|
||||||
mathInline: 0
|
mathInline: 0
|
||||||
mathDisplay: 0
|
mathDisplay: 0
|
||||||
|
errors: 0
|
||||||
|
messages: ""
|
||||||
}
|
}
|
||||||
for line in output.split("\n")
|
for line in output.split("\n")
|
||||||
[data, info] = line.split(":")
|
[data, info] = line.split(":")
|
||||||
@@ -242,4 +277,8 @@ module.exports = CompileManager =
|
|||||||
results['mathInline'] = parseInt(info, 10)
|
results['mathInline'] = parseInt(info, 10)
|
||||||
if data.indexOf("Number of math displayed") > -1
|
if data.indexOf("Number of math displayed") > -1
|
||||||
results['mathDisplay'] = parseInt(info, 10)
|
results['mathDisplay'] = parseInt(info, 10)
|
||||||
|
if data is "(errors" # errors reported as (errors:123)
|
||||||
|
results['errors'] = parseInt(info, 10)
|
||||||
|
if line.indexOf("!!! ") > -1 # errors logged as !!! message !!!
|
||||||
|
results['messages'] += line + "\n"
|
||||||
return results
|
return results
|
||||||
|
|||||||
@@ -4,13 +4,15 @@ logger = require "logger-sharelatex"
|
|||||||
Metrics = require "./Metrics"
|
Metrics = require "./Metrics"
|
||||||
CommandRunner = require(Settings.clsi?.commandRunner or "./CommandRunner")
|
CommandRunner = require(Settings.clsi?.commandRunner or "./CommandRunner")
|
||||||
|
|
||||||
|
ProcessTable = {} # table of currently running jobs (pids or docker container names)
|
||||||
|
|
||||||
module.exports = LatexRunner =
|
module.exports = LatexRunner =
|
||||||
runLatex: (project_id, options, callback = (error) ->) ->
|
runLatex: (project_id, options, callback = (error) ->) ->
|
||||||
{directory, mainFile, compiler, timeout, image} = options
|
{directory, mainFile, compiler, timeout, image, environment} = options
|
||||||
compiler ||= "pdflatex"
|
compiler ||= "pdflatex"
|
||||||
timeout ||= 60000 # milliseconds
|
timeout ||= 60000 # milliseconds
|
||||||
|
|
||||||
logger.log directory: directory, compiler: compiler, timeout: timeout, mainFile: mainFile, "starting compile"
|
logger.log directory: directory, compiler: compiler, timeout: timeout, mainFile: mainFile, environment: environment, "starting compile"
|
||||||
|
|
||||||
# We want to run latexmk on the tex file which we will automatically
|
# We want to run latexmk on the tex file which we will automatically
|
||||||
# generate from the Rtex/Rmd/md file.
|
# generate from the Rtex/Rmd/md file.
|
||||||
@@ -30,7 +32,10 @@ module.exports = LatexRunner =
|
|||||||
if Settings.clsi?.strace
|
if Settings.clsi?.strace
|
||||||
command = ["strace", "-o", "strace", "-ff"].concat(command)
|
command = ["strace", "-o", "strace", "-ff"].concat(command)
|
||||||
|
|
||||||
CommandRunner.run project_id, command, directory, image, timeout, (error, output) ->
|
id = "#{project_id}" # record running project under this id
|
||||||
|
|
||||||
|
ProcessTable[id] = CommandRunner.run project_id, command, directory, image, timeout, environment, (error, output) ->
|
||||||
|
delete ProcessTable[id]
|
||||||
return callback(error) if error?
|
return callback(error) if error?
|
||||||
runs = output?.stderr?.match(/^Run number \d+ of .*latex/mg)?.length or 0
|
runs = output?.stderr?.match(/^Run number \d+ of .*latex/mg)?.length or 0
|
||||||
failed = if output?.stdout?.match(/^Latexmk: Errors/m)? then 1 else 0
|
failed = if output?.stdout?.match(/^Latexmk: Errors/m)? then 1 else 0
|
||||||
@@ -49,7 +54,17 @@ module.exports = LatexRunner =
|
|||||||
timings["sys-time"] = stderr?.match(/System time.*: (\d+.\d+)/m)?[1] or 0
|
timings["sys-time"] = stderr?.match(/System time.*: (\d+.\d+)/m)?[1] or 0
|
||||||
callback error, output, stats, timings
|
callback error, output, stats, timings
|
||||||
|
|
||||||
_latexmkBaseCommand: ["/usr/bin/time", "-v", "latexmk", "-cd", "-f", "-jobname=output", "-auxdir=$COMPILE_DIR", "-outdir=$COMPILE_DIR"]
|
killLatex: (project_id, callback = (error) ->) ->
|
||||||
|
id = "#{project_id}"
|
||||||
|
logger.log {id:id}, "killing running compile"
|
||||||
|
if not ProcessTable[id]?
|
||||||
|
return callback new Error("no such project to kill")
|
||||||
|
else
|
||||||
|
CommandRunner.kill ProcessTable[id], callback
|
||||||
|
|
||||||
|
_latexmkBaseCommand: (Settings?.clsi?.latexmkCommandPrefix || []).concat(
|
||||||
|
["latexmk", "-cd", "-f", "-jobname=output", "-auxdir=$COMPILE_DIR", "-outdir=$COMPILE_DIR"]
|
||||||
|
)
|
||||||
|
|
||||||
_pdflatexCommand: (mainFile) ->
|
_pdflatexCommand: (mainFile) ->
|
||||||
LatexRunner._latexmkBaseCommand.concat [
|
LatexRunner._latexmkBaseCommand.concat [
|
||||||
|
|||||||
@@ -45,9 +45,8 @@ module.exports = OutputCacheManager =
|
|||||||
cacheRoot = Path.join(compileDir, OutputCacheManager.CACHE_SUBDIR)
|
cacheRoot = Path.join(compileDir, OutputCacheManager.CACHE_SUBDIR)
|
||||||
# Put the files into a new cache subdirectory
|
# Put the files into a new cache subdirectory
|
||||||
cacheDir = Path.join(compileDir, OutputCacheManager.CACHE_SUBDIR, buildId)
|
cacheDir = Path.join(compileDir, OutputCacheManager.CACHE_SUBDIR, buildId)
|
||||||
|
# Is it a per-user compile? check if compile directory is PROJECTID-USERID
|
||||||
# let file expiry run in the background
|
perUser = Path.basename(compileDir).match(/^[0-9a-f]{24}-[0-9a-f]{24}$/)
|
||||||
OutputCacheManager.expireOutputFiles cacheRoot, {keep: buildId}
|
|
||||||
|
|
||||||
# Archive logs in background
|
# Archive logs in background
|
||||||
if Settings.clsi?.archive_logs or Settings.clsi?.strace
|
if Settings.clsi?.archive_logs or Settings.clsi?.strace
|
||||||
@@ -83,9 +82,15 @@ module.exports = OutputCacheManager =
|
|||||||
if err?
|
if err?
|
||||||
# pass back the original files if we encountered *any* error
|
# pass back the original files if we encountered *any* error
|
||||||
callback(err, outputFiles)
|
callback(err, outputFiles)
|
||||||
|
# clean up the directory we just created
|
||||||
|
fse.remove cacheDir, (err) ->
|
||||||
|
if err?
|
||||||
|
logger.error err: err, dir: dir, "error removing cache dir after failure"
|
||||||
else
|
else
|
||||||
# pass back the list of new files in the cache
|
# pass back the list of new files in the cache
|
||||||
callback(err, results)
|
callback(err, results)
|
||||||
|
# let file expiry run in the background, expire all previous files if per-user
|
||||||
|
OutputCacheManager.expireOutputFiles cacheRoot, {keep: buildId, limit: if perUser then 1 else null}
|
||||||
|
|
||||||
archiveLogs: (outputFiles, compileDir, buildId, callback = (error) ->) ->
|
archiveLogs: (outputFiles, compileDir, buildId, callback = (error) ->) ->
|
||||||
archiveDir = Path.join(compileDir, OutputCacheManager.ARCHIVE_SUBDIR, buildId)
|
archiveDir = Path.join(compileDir, OutputCacheManager.ARCHIVE_SUBDIR, buildId)
|
||||||
@@ -116,6 +121,8 @@ module.exports = OutputCacheManager =
|
|||||||
|
|
||||||
isExpired = (dir, index) ->
|
isExpired = (dir, index) ->
|
||||||
return false if options?.keep == dir
|
return false if options?.keep == dir
|
||||||
|
# remove any directories over the requested (non-null) limit
|
||||||
|
return true if options?.limit? and index > options.limit
|
||||||
# remove any directories over the hard limit
|
# remove any directories over the hard limit
|
||||||
return true if index > OutputCacheManager.CACHE_LIMIT
|
return true if index > OutputCacheManager.CACHE_LIMIT
|
||||||
# we can get the build time from the first part of the directory name DDDD-RRRR
|
# we can get the build time from the first part of the directory name DDDD-RRRR
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ module.exports = RequestParser =
|
|||||||
compile.options.draft,
|
compile.options.draft,
|
||||||
default: false,
|
default: false,
|
||||||
type: "boolean"
|
type: "boolean"
|
||||||
|
response.check = @_parseAttribute "check",
|
||||||
|
compile.options.check,
|
||||||
|
type: "string"
|
||||||
|
|
||||||
if response.timeout > RequestParser.MAX_TIMEOUT
|
if response.timeout > RequestParser.MAX_TIMEOUT
|
||||||
response.timeout = RequestParser.MAX_TIMEOUT
|
response.timeout = RequestParser.MAX_TIMEOUT
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ module.exports =
|
|||||||
# modem:
|
# modem:
|
||||||
# socketPath: false
|
# socketPath: false
|
||||||
# user: "tex"
|
# user: "tex"
|
||||||
|
# latexmkCommandPrefix: []
|
||||||
|
# # latexmkCommandPrefix: ["/usr/bin/time", "-v"] # on Linux
|
||||||
|
# # latexmkCommandPrefix: ["/usr/local/bin/gtime", "-v"] # on Mac OSX, installed with `brew install gnu-time`
|
||||||
|
|
||||||
internal:
|
internal:
|
||||||
clsi:
|
clsi:
|
||||||
@@ -41,5 +44,5 @@ module.exports =
|
|||||||
url: "http://localhost:3013"
|
url: "http://localhost:3013"
|
||||||
|
|
||||||
smokeTest: false
|
smokeTest: false
|
||||||
project_cache_length_ms: 60 * 60 * 24
|
project_cache_length_ms: 1000 * 60 * 60 * 24
|
||||||
parallelFileDownloads:1
|
parallelFileDownloads:1
|
||||||
@@ -47,6 +47,7 @@ describe "CompileManager", ->
|
|||||||
compiler: @compiler = "pdflatex"
|
compiler: @compiler = "pdflatex"
|
||||||
timeout: @timeout = 42000
|
timeout: @timeout = 42000
|
||||||
imageName: @image = "example.com/image"
|
imageName: @image = "example.com/image"
|
||||||
|
@env = {}
|
||||||
@Settings.compileDir = "compiles"
|
@Settings.compileDir = "compiles"
|
||||||
@compileDir = "#{@Settings.path.compilesDir}/#{@project_id}-#{@user_id}"
|
@compileDir = "#{@Settings.path.compilesDir}/#{@project_id}-#{@user_id}"
|
||||||
@ResourceWriter.syncResourcesToDisk = sinon.stub().callsArg(3)
|
@ResourceWriter.syncResourcesToDisk = sinon.stub().callsArg(3)
|
||||||
@@ -72,6 +73,7 @@ describe "CompileManager", ->
|
|||||||
compiler: @compiler
|
compiler: @compiler
|
||||||
timeout: @timeout
|
timeout: @timeout
|
||||||
image: @image
|
image: @image
|
||||||
|
environment: @env
|
||||||
})
|
})
|
||||||
.should.equal true
|
.should.equal true
|
||||||
|
|
||||||
@@ -200,8 +202,8 @@ describe "CompileManager", ->
|
|||||||
|
|
||||||
describe "wordcount", ->
|
describe "wordcount", ->
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
@CommandRunner.run = sinon.stub().callsArg(5)
|
@CommandRunner.run = sinon.stub().callsArg(6)
|
||||||
@fs.readFileSync = sinon.stub().returns @stdout = "Encoding: ascii\nWords in text: 2"
|
@fs.readFile = sinon.stub().callsArgWith(2, null, @stdout = "Encoding: ascii\nWords in text: 2")
|
||||||
@callback = sinon.stub()
|
@callback = sinon.stub()
|
||||||
|
|
||||||
@project_id = "project-id-123"
|
@project_id = "project-id-123"
|
||||||
@@ -215,10 +217,10 @@ describe "CompileManager", ->
|
|||||||
it "should run the texcount command", ->
|
it "should run the texcount command", ->
|
||||||
@directory = "#{@Settings.path.compilesDir}/#{@project_id}-#{@user_id}"
|
@directory = "#{@Settings.path.compilesDir}/#{@project_id}-#{@user_id}"
|
||||||
@file_path = "$COMPILE_DIR/#{@file_name}"
|
@file_path = "$COMPILE_DIR/#{@file_name}"
|
||||||
@command =[ "texcount", "-inc", @file_path, "-out=" + @file_path + ".wc"]
|
@command =[ "texcount", "-nocol", "-inc", @file_path, "-out=" + @file_path + ".wc"]
|
||||||
|
|
||||||
@CommandRunner.run
|
@CommandRunner.run
|
||||||
.calledWith("#{@project_id}-#{@user_id}", @command, @directory, @image, @timeout)
|
.calledWith("#{@project_id}-#{@user_id}", @command, @directory, @image, @timeout, {})
|
||||||
.should.equal true
|
.should.equal true
|
||||||
|
|
||||||
it "should call the callback with the parsed output", ->
|
it "should call the callback with the parsed output", ->
|
||||||
@@ -232,5 +234,7 @@ describe "CompileManager", ->
|
|||||||
elements: 0
|
elements: 0
|
||||||
mathInline: 0
|
mathInline: 0
|
||||||
mathDisplay: 0
|
mathDisplay: 0
|
||||||
|
errors: 0
|
||||||
|
messages: ""
|
||||||
})
|
})
|
||||||
.should.equal true
|
.should.equal true
|
||||||
|
|||||||
@@ -22,10 +22,11 @@ describe "LatexRunner", ->
|
|||||||
@image = "example.com/image"
|
@image = "example.com/image"
|
||||||
@callback = sinon.stub()
|
@callback = sinon.stub()
|
||||||
@project_id = "project-id-123"
|
@project_id = "project-id-123"
|
||||||
|
@env = {'foo': '123'}
|
||||||
|
|
||||||
describe "runLatex", ->
|
describe "runLatex", ->
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
@CommandRunner.run = sinon.stub().callsArg(5)
|
@CommandRunner.run = sinon.stub().callsArg(6)
|
||||||
|
|
||||||
describe "normally", ->
|
describe "normally", ->
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
@@ -35,11 +36,12 @@ describe "LatexRunner", ->
|
|||||||
compiler: @compiler
|
compiler: @compiler
|
||||||
timeout: @timeout = 42000
|
timeout: @timeout = 42000
|
||||||
image: @image
|
image: @image
|
||||||
|
environment: @env
|
||||||
@callback
|
@callback
|
||||||
|
|
||||||
it "should run the latex command", ->
|
it "should run the latex command", ->
|
||||||
@CommandRunner.run
|
@CommandRunner.run
|
||||||
.calledWith(@project_id, sinon.match.any, @directory, @image, @timeout)
|
.calledWith(@project_id, sinon.match.any, @directory, @image, @timeout, @env)
|
||||||
.should.equal true
|
.should.equal true
|
||||||
|
|
||||||
describe "with an .Rtex main file", ->
|
describe "with an .Rtex main file", ->
|
||||||
|
|||||||
Reference in New Issue
Block a user