Compare commits
58 Commits
bg-create-
...
csh-issue-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3ce68b44d2 | ||
|
|
c30e6a9d4f | ||
|
|
b1ca08fd0c | ||
|
|
d98745431b | ||
|
|
6b69e26de3 | ||
|
|
a8286e7742 | ||
|
|
58c6fe7c35 | ||
|
|
74a11c7be3 | ||
|
|
1f3217f598 | ||
|
|
52f4bfe9e2 | ||
|
|
a88000281f | ||
|
|
b33734bab6 | ||
|
|
6c7019ccb7 | ||
|
|
bad3850fcc | ||
|
|
9b92793b89 | ||
|
|
6569da0242 | ||
|
|
33d6462875 | ||
|
|
19690e7847 | ||
|
|
5aa90abc2d | ||
|
|
ba7de90a50 | ||
|
|
7ceadc8599 | ||
|
|
f077c337ec | ||
|
|
eb603f9f31 | ||
|
|
385cdd6f0c | ||
|
|
303fb03f1f | ||
|
|
3e3e4503eb | ||
|
|
70363a9109 | ||
|
|
59310cbb09 | ||
|
|
d88136c569 | ||
|
|
0d44fb704b | ||
|
|
bf2430f1fc | ||
|
|
2211ebcefb | ||
|
|
440ec5553e | ||
|
|
17c14b1192 | ||
|
|
8c60406bb5 | ||
|
|
9db18c95a5 | ||
|
|
985bbf27c9 | ||
|
|
f8cb5e36af | ||
|
|
1bcb370ca1 | ||
|
|
e3c278e708 | ||
|
|
54896fb157 | ||
|
|
fec359afac | ||
|
|
97f5691c87 | ||
|
|
9807b51519 | ||
|
|
b8125e396a | ||
|
|
73afa1a8d7 | ||
|
|
942678de38 | ||
|
|
3834c37013 | ||
|
|
a425412bdd | ||
|
|
c004d299c1 | ||
|
|
5ab45c1031 | ||
|
|
0bd99a3edc | ||
|
|
3592ffda52 | ||
|
|
5b5fd2f5df | ||
|
|
2b2fcca39c | ||
|
|
9e82ab0890 | ||
|
|
e3da458b37 | ||
|
|
8fa4232148 |
@@ -2,7 +2,7 @@
|
|||||||
# Instead run bin/update_build_scripts from
|
# Instead run bin/update_build_scripts from
|
||||||
# https://github.com/sharelatex/sharelatex-dev-environment
|
# https://github.com/sharelatex/sharelatex-dev-environment
|
||||||
|
|
||||||
FROM node:10.19.0 as base
|
FROM node:10.21.0 as base
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY install_deps.sh /app
|
COPY install_deps.sh /app
|
||||||
|
|||||||
128
app.js
128
app.js
@@ -5,7 +5,7 @@
|
|||||||
* DS207: Consider shorter variations of null checks
|
* DS207: Consider shorter variations of null checks
|
||||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||||
*/
|
*/
|
||||||
let tenMinutes
|
const tenMinutes = 10 * 60 * 1000
|
||||||
const Metrics = require('metrics-sharelatex')
|
const Metrics = require('metrics-sharelatex')
|
||||||
Metrics.initialize('clsi')
|
Metrics.initialize('clsi')
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ if ((Settings.sentry != null ? Settings.sentry.dsn : undefined) != null) {
|
|||||||
logger.initializeErrorReporting(Settings.sentry.dsn)
|
logger.initializeErrorReporting(Settings.sentry.dsn)
|
||||||
}
|
}
|
||||||
|
|
||||||
const smokeTest = require('smoke-test-sharelatex')
|
const smokeTest = require('./test/smoke/js/SmokeTests')
|
||||||
const ContentTypeMapper = require('./app/js/ContentTypeMapper')
|
const ContentTypeMapper = require('./app/js/ContentTypeMapper')
|
||||||
const Errors = require('./app/js/Errors')
|
const Errors = require('./app/js/Errors')
|
||||||
|
|
||||||
@@ -49,31 +49,29 @@ app.use(function(req, res, next) {
|
|||||||
return next()
|
return next()
|
||||||
})
|
})
|
||||||
|
|
||||||
app.param('project_id', function(req, res, next, project_id) {
|
app.param('project_id', function(req, res, next, projectId) {
|
||||||
if (project_id != null ? project_id.match(/^[a-zA-Z0-9_-]+$/) : undefined) {
|
if (projectId != null ? projectId.match(/^[a-zA-Z0-9_-]+$/) : undefined) {
|
||||||
return next()
|
return next()
|
||||||
} else {
|
} else {
|
||||||
return next(new Error('invalid project id'))
|
return next(new Error('invalid project id'))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
app.param('user_id', function(req, res, next, user_id) {
|
app.param('user_id', function(req, res, next, userId) {
|
||||||
if (user_id != null ? user_id.match(/^[0-9a-f]{24}$/) : undefined) {
|
if (userId != null ? userId.match(/^[0-9a-f]{24}$/) : undefined) {
|
||||||
return next()
|
return next()
|
||||||
} else {
|
} else {
|
||||||
return next(new Error('invalid user id'))
|
return next(new Error('invalid user id'))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
app.param('build_id', function(req, res, next, build_id) {
|
app.param('build_id', function(req, res, next, buildId) {
|
||||||
if (
|
if (
|
||||||
build_id != null
|
buildId != null ? buildId.match(OutputCacheManager.BUILD_REGEX) : undefined
|
||||||
? build_id.match(OutputCacheManager.BUILD_REGEX)
|
|
||||||
: undefined
|
|
||||||
) {
|
) {
|
||||||
return next()
|
return next()
|
||||||
} else {
|
} else {
|
||||||
return next(new Error(`invalid build id ${build_id}`))
|
return next(new Error(`invalid build id ${buildId}`))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -192,69 +190,49 @@ app.get('/oops', function(req, res, next) {
|
|||||||
|
|
||||||
app.get('/status', (req, res, next) => res.send('CLSI is alive\n'))
|
app.get('/status', (req, res, next) => res.send('CLSI is alive\n'))
|
||||||
|
|
||||||
const resCacher = {
|
Settings.processTooOld = false
|
||||||
contentType(setContentType) {
|
|
||||||
this.setContentType = setContentType
|
|
||||||
},
|
|
||||||
send(code, body) {
|
|
||||||
this.code = code
|
|
||||||
this.body = body
|
|
||||||
},
|
|
||||||
|
|
||||||
// default the server to be down
|
|
||||||
code: 500,
|
|
||||||
body: {},
|
|
||||||
setContentType: 'application/json'
|
|
||||||
}
|
|
||||||
|
|
||||||
let shutdownTime
|
|
||||||
if (Settings.processLifespanLimitMs) {
|
if (Settings.processLifespanLimitMs) {
|
||||||
Settings.processLifespanLimitMs +=
|
Settings.processLifespanLimitMs +=
|
||||||
Settings.processLifespanLimitMs * (Math.random() / 10)
|
Settings.processLifespanLimitMs * (Math.random() / 10)
|
||||||
shutdownTime = Date.now() + Settings.processLifespanLimitMs
|
logger.info(
|
||||||
logger.info('Lifespan limited to ', shutdownTime)
|
'Lifespan limited to ',
|
||||||
}
|
Date.now() + Settings.processLifespanLimitMs
|
||||||
|
)
|
||||||
|
|
||||||
const checkIfProcessIsTooOld = function(cont) {
|
setTimeout(() => {
|
||||||
if (shutdownTime && shutdownTime < Date.now()) {
|
|
||||||
logger.log('shutting down, process is too old')
|
logger.log('shutting down, process is too old')
|
||||||
resCacher.send = function() {}
|
Settings.processTooOld = true
|
||||||
resCacher.code = 500
|
}, Settings.processLifespanLimitMs)
|
||||||
resCacher.body = { processToOld: true }
|
|
||||||
} else {
|
|
||||||
cont()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function runSmokeTest() {
|
||||||
|
if (Settings.processTooOld) return
|
||||||
|
logger.log('running smoke tests')
|
||||||
|
smokeTest.triggerRun(err => {
|
||||||
|
if (err) logger.error({ err }, 'smoke tests failed')
|
||||||
|
setTimeout(runSmokeTest, 30 * 1000)
|
||||||
|
})
|
||||||
|
}
|
||||||
if (Settings.smokeTest) {
|
if (Settings.smokeTest) {
|
||||||
const runSmokeTest = function() {
|
|
||||||
checkIfProcessIsTooOld(function() {
|
|
||||||
logger.log('running smoke tests')
|
|
||||||
smokeTest.run(
|
|
||||||
require.resolve(__dirname + '/test/smoke/js/SmokeTests.js')
|
|
||||||
)({}, resCacher)
|
|
||||||
return setTimeout(runSmokeTest, 30 * 1000)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
runSmokeTest()
|
runSmokeTest()
|
||||||
}
|
}
|
||||||
|
|
||||||
app.get('/health_check', function(req, res) {
|
app.get('/health_check', function(req, res) {
|
||||||
res.contentType(resCacher.setContentType)
|
if (Settings.processTooOld) {
|
||||||
return res.status(resCacher.code).send(resCacher.body)
|
return res.status(500).json({ processTooOld: true })
|
||||||
|
}
|
||||||
|
smokeTest.sendLastResult(res)
|
||||||
})
|
})
|
||||||
|
|
||||||
app.get('/smoke_test_force', (req, res) =>
|
app.get('/smoke_test_force', (req, res) => smokeTest.sendNewResult(res))
|
||||||
smokeTest.run(require.resolve(__dirname + '/test/smoke/js/SmokeTests.js'))(
|
|
||||||
req,
|
|
||||||
res
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
app.use(function(error, req, res, next) {
|
app.use(function(error, req, res, next) {
|
||||||
if (error instanceof Errors.NotFoundError) {
|
if (error instanceof Errors.NotFoundError) {
|
||||||
logger.warn({ err: error, url: req.url }, 'not found error')
|
logger.log({ err: error, url: req.url }, 'not found error')
|
||||||
return res.sendStatus(404)
|
return res.sendStatus(404)
|
||||||
|
} else if (error.code === 'EPIPE') {
|
||||||
|
// inspect container returns EPIPE when shutting down
|
||||||
|
return res.sendStatus(503) // send 503 Unavailable response
|
||||||
} else {
|
} else {
|
||||||
logger.error({ err: error, url: req.url }, 'server error')
|
logger.error({ err: error, url: req.url }, 'server error')
|
||||||
return res.sendStatus((error != null ? error.statusCode : undefined) || 500)
|
return res.sendStatus((error != null ? error.statusCode : undefined) || 500)
|
||||||
@@ -331,38 +309,40 @@ const host =
|
|||||||
x1 => x1.host
|
x1 => x1.host
|
||||||
) || 'localhost'
|
) || 'localhost'
|
||||||
|
|
||||||
const load_tcp_port = Settings.internal.load_balancer_agent.load_port
|
const loadTcpPort = Settings.internal.load_balancer_agent.load_port
|
||||||
const load_http_port = Settings.internal.load_balancer_agent.local_port
|
const loadHttpPort = Settings.internal.load_balancer_agent.local_port
|
||||||
|
|
||||||
if (!module.parent) {
|
if (!module.parent) {
|
||||||
// Called directly
|
// Called directly
|
||||||
app.listen(port, host, error =>
|
app.listen(port, host, error => {
|
||||||
logger.info(`CLSI starting up, listening on ${host}:${port}`)
|
if (error) {
|
||||||
)
|
logger.fatal({ error }, `Error starting CLSI on ${host}:${port}`)
|
||||||
|
} else {
|
||||||
loadTcpServer.listen(load_tcp_port, host, function(error) {
|
logger.info(`CLSI starting up, listening on ${host}:${port}`)
|
||||||
if (error != null) {
|
|
||||||
throw error
|
|
||||||
}
|
}
|
||||||
return logger.info(`Load tcp agent listening on load port ${load_tcp_port}`)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
loadHttpServer.listen(load_http_port, host, function(error) {
|
loadTcpServer.listen(loadTcpPort, host, function(error) {
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
return logger.info(
|
return logger.info(`Load tcp agent listening on load port ${loadTcpPort}`)
|
||||||
`Load http agent listening on load port ${load_http_port}`
|
})
|
||||||
)
|
|
||||||
|
loadHttpServer.listen(loadHttpPort, host, function(error) {
|
||||||
|
if (error != null) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
return logger.info(`Load http agent listening on load port ${loadHttpPort}`)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = app
|
module.exports = app
|
||||||
|
|
||||||
setInterval(
|
setInterval(() => {
|
||||||
() => ProjectPersistenceManager.clearExpiredProjects(),
|
ProjectPersistenceManager.refreshExpiryTimeout()
|
||||||
(tenMinutes = 10 * 60 * 1000)
|
ProjectPersistenceManager.clearExpiredProjects()
|
||||||
)
|
}, tenMinutes)
|
||||||
|
|
||||||
function __guard__(value, transform) {
|
function __guard__(value, transform) {
|
||||||
return typeof value !== 'undefined' && value !== null
|
return typeof value !== 'undefined' && value !== null
|
||||||
|
|||||||
@@ -55,6 +55,10 @@ module.exports = CompileController = {
|
|||||||
} else if (error instanceof Errors.FilesOutOfSyncError) {
|
} else if (error instanceof Errors.FilesOutOfSyncError) {
|
||||||
code = 409 // Http 409 Conflict
|
code = 409 // Http 409 Conflict
|
||||||
status = 'retry'
|
status = 'retry'
|
||||||
|
} else if (error && error.code === 'EPIPE') {
|
||||||
|
// docker returns EPIPE when shutting down
|
||||||
|
code = 503 // send 503 Unavailable response
|
||||||
|
status = 'unavailable'
|
||||||
} else if (error != null ? error.terminated : undefined) {
|
} else if (error != null ? error.terminated : undefined) {
|
||||||
status = 'terminated'
|
status = 'terminated'
|
||||||
} else if (error != null ? error.validate : undefined) {
|
} else if (error != null ? error.validate : undefined) {
|
||||||
|
|||||||
@@ -142,6 +142,10 @@ module.exports = CompileManager = {
|
|||||||
)
|
)
|
||||||
// set up environment variables for chktex
|
// set up environment variables for chktex
|
||||||
const env = {}
|
const env = {}
|
||||||
|
if (Settings.texliveOpenoutAny && Settings.texliveOpenoutAny !== '') {
|
||||||
|
// override default texlive openout_any environment variable
|
||||||
|
env.openout_any = Settings.texliveOpenoutAny
|
||||||
|
}
|
||||||
// only run chktex on LaTeX files (not knitr .Rtex files or any others)
|
// only run chktex on LaTeX files (not knitr .Rtex files or any others)
|
||||||
const isLaTeXFile =
|
const isLaTeXFile =
|
||||||
request.rootResourcePath != null
|
request.rootResourcePath != null
|
||||||
@@ -195,7 +199,8 @@ module.exports = CompileManager = {
|
|||||||
timeout: request.timeout,
|
timeout: request.timeout,
|
||||||
image: request.imageName,
|
image: request.imageName,
|
||||||
flags: request.flags,
|
flags: request.flags,
|
||||||
environment: env
|
environment: env,
|
||||||
|
compileGroup: request.compileGroup
|
||||||
},
|
},
|
||||||
function(error, output, stats, timings) {
|
function(error, output, stats, timings) {
|
||||||
// request was for validation only
|
// request was for validation only
|
||||||
@@ -334,7 +339,7 @@ module.exports = CompileManager = {
|
|||||||
proc.on('error', callback)
|
proc.on('error', callback)
|
||||||
|
|
||||||
let stderr = ''
|
let stderr = ''
|
||||||
proc.stderr.on('data', chunk => (stderr += chunk.toString()))
|
proc.stderr.setEncoding('utf8').on('data', chunk => (stderr += chunk))
|
||||||
|
|
||||||
return proc.on('close', function(code) {
|
return proc.on('close', function(code) {
|
||||||
if (code === 0) {
|
if (code === 0) {
|
||||||
@@ -426,30 +431,18 @@ module.exports = CompileManager = {
|
|||||||
const compileDir = getCompileDir(project_id, user_id)
|
const compileDir = getCompileDir(project_id, user_id)
|
||||||
const synctex_path = `${base_dir}/output.pdf`
|
const synctex_path = `${base_dir}/output.pdf`
|
||||||
const command = ['code', synctex_path, file_path, line, column]
|
const command = ['code', synctex_path, file_path, line, column]
|
||||||
return fse.ensureDir(compileDir, function(error) {
|
CompileManager._runSynctex(project_id, user_id, command, function(
|
||||||
|
error,
|
||||||
|
stdout
|
||||||
|
) {
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
logger.err(
|
|
||||||
{ error, project_id, user_id, file_name },
|
|
||||||
'error ensuring dir for sync from code'
|
|
||||||
)
|
|
||||||
return callback(error)
|
return callback(error)
|
||||||
}
|
}
|
||||||
return CompileManager._runSynctex(project_id, user_id, command, function(
|
logger.log(
|
||||||
error,
|
{ project_id, user_id, file_name, line, column, command, stdout },
|
||||||
stdout
|
'synctex code output'
|
||||||
) {
|
)
|
||||||
if (error != null) {
|
return callback(null, CompileManager._parseSynctexFromCodeOutput(stdout))
|
||||||
return callback(error)
|
|
||||||
}
|
|
||||||
logger.log(
|
|
||||||
{ project_id, user_id, file_name, line, column, command, stdout },
|
|
||||||
'synctex code output'
|
|
||||||
)
|
|
||||||
return callback(
|
|
||||||
null,
|
|
||||||
CompileManager._parseSynctexFromCodeOutput(stdout)
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -462,53 +455,39 @@ module.exports = CompileManager = {
|
|||||||
const base_dir = Settings.path.synctexBaseDir(compileName)
|
const base_dir = Settings.path.synctexBaseDir(compileName)
|
||||||
const synctex_path = `${base_dir}/output.pdf`
|
const synctex_path = `${base_dir}/output.pdf`
|
||||||
const command = ['pdf', synctex_path, page, h, v]
|
const command = ['pdf', synctex_path, page, h, v]
|
||||||
return fse.ensureDir(compileDir, function(error) {
|
CompileManager._runSynctex(project_id, user_id, command, function(
|
||||||
|
error,
|
||||||
|
stdout
|
||||||
|
) {
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
logger.err(
|
|
||||||
{ error, project_id, user_id, file_name },
|
|
||||||
'error ensuring dir for sync to code'
|
|
||||||
)
|
|
||||||
return callback(error)
|
return callback(error)
|
||||||
}
|
}
|
||||||
return CompileManager._runSynctex(project_id, user_id, command, function(
|
logger.log(
|
||||||
error,
|
{ project_id, user_id, page, h, v, stdout },
|
||||||
stdout
|
'synctex pdf output'
|
||||||
) {
|
)
|
||||||
if (error != null) {
|
return callback(
|
||||||
return callback(error)
|
null,
|
||||||
}
|
CompileManager._parseSynctexFromPdfOutput(stdout, base_dir)
|
||||||
logger.log(
|
)
|
||||||
{ project_id, user_id, page, h, v, stdout },
|
|
||||||
'synctex pdf output'
|
|
||||||
)
|
|
||||||
return callback(
|
|
||||||
null,
|
|
||||||
CompileManager._parseSynctexFromPdfOutput(stdout, base_dir)
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
_checkFileExists(path, callback) {
|
_checkFileExists(dir, filename, callback) {
|
||||||
if (callback == null) {
|
if (callback == null) {
|
||||||
callback = function(error) {}
|
callback = function(error) {}
|
||||||
}
|
}
|
||||||
const synctexDir = Path.dirname(path)
|
const file = Path.join(dir, filename)
|
||||||
const synctexFile = Path.join(synctexDir, 'output.synctex.gz')
|
return fs.stat(dir, function(error, stats) {
|
||||||
return fs.stat(synctexDir, function(error, stats) {
|
|
||||||
if ((error != null ? error.code : undefined) === 'ENOENT') {
|
if ((error != null ? error.code : undefined) === 'ENOENT') {
|
||||||
return callback(
|
return callback(new Errors.NotFoundError('no output directory'))
|
||||||
new Errors.NotFoundError('called synctex with no output directory')
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
return callback(error)
|
return callback(error)
|
||||||
}
|
}
|
||||||
return fs.stat(synctexFile, function(error, stats) {
|
return fs.stat(file, function(error, stats) {
|
||||||
if ((error != null ? error.code : undefined) === 'ENOENT') {
|
if ((error != null ? error.code : undefined) === 'ENOENT') {
|
||||||
return callback(
|
return callback(new Errors.NotFoundError('no output file'))
|
||||||
new Errors.NotFoundError('called synctex with no output file')
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
return callback(error)
|
return callback(error)
|
||||||
@@ -532,24 +511,31 @@ module.exports = CompileManager = {
|
|||||||
const directory = getCompileDir(project_id, user_id)
|
const directory = getCompileDir(project_id, user_id)
|
||||||
const timeout = 60 * 1000 // increased to allow for large projects
|
const timeout = 60 * 1000 // increased to allow for large projects
|
||||||
const compileName = getCompileName(project_id, user_id)
|
const compileName = getCompileName(project_id, user_id)
|
||||||
return CommandRunner.run(
|
const compileGroup = 'synctex'
|
||||||
compileName,
|
CompileManager._checkFileExists(directory, 'output.synctex.gz', error => {
|
||||||
command,
|
if (error) {
|
||||||
directory,
|
return callback(error)
|
||||||
Settings.clsi != null ? Settings.clsi.docker.image : undefined,
|
|
||||||
timeout,
|
|
||||||
{},
|
|
||||||
function(error, output) {
|
|
||||||
if (error != null) {
|
|
||||||
logger.err(
|
|
||||||
{ err: error, command, project_id, user_id },
|
|
||||||
'error running synctex'
|
|
||||||
)
|
|
||||||
return callback(error)
|
|
||||||
}
|
|
||||||
return callback(null, output.stdout)
|
|
||||||
}
|
}
|
||||||
)
|
return CommandRunner.run(
|
||||||
|
compileName,
|
||||||
|
command,
|
||||||
|
directory,
|
||||||
|
Settings.clsi != null ? Settings.clsi.docker.image : undefined,
|
||||||
|
timeout,
|
||||||
|
{},
|
||||||
|
compileGroup,
|
||||||
|
function(error, output) {
|
||||||
|
if (error != null) {
|
||||||
|
logger.err(
|
||||||
|
{ err: error, command, project_id, user_id },
|
||||||
|
'error running synctex'
|
||||||
|
)
|
||||||
|
return callback(error)
|
||||||
|
}
|
||||||
|
return callback(null, output.stdout)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
_parseSynctexFromCodeOutput(output) {
|
_parseSynctexFromCodeOutput(output) {
|
||||||
@@ -602,6 +588,7 @@ module.exports = CompileManager = {
|
|||||||
const compileDir = getCompileDir(project_id, user_id)
|
const compileDir = getCompileDir(project_id, user_id)
|
||||||
const timeout = 60 * 1000
|
const timeout = 60 * 1000
|
||||||
const compileName = getCompileName(project_id, user_id)
|
const compileName = getCompileName(project_id, user_id)
|
||||||
|
const compileGroup = 'wordcount'
|
||||||
return fse.ensureDir(compileDir, function(error) {
|
return fse.ensureDir(compileDir, function(error) {
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
logger.err(
|
logger.err(
|
||||||
@@ -617,6 +604,7 @@ module.exports = CompileManager = {
|
|||||||
image,
|
image,
|
||||||
timeout,
|
timeout,
|
||||||
{},
|
{},
|
||||||
|
compileGroup,
|
||||||
function(error) {
|
function(error) {
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
return callback(error)
|
return callback(error)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ const async = require('async')
|
|||||||
const LockManager = require('./DockerLockManager')
|
const LockManager = require('./DockerLockManager')
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const Path = require('path')
|
const Path = require('path')
|
||||||
const _ = require('underscore')
|
const _ = require('lodash')
|
||||||
|
|
||||||
logger.info('using docker runner')
|
logger.info('using docker runner')
|
||||||
|
|
||||||
@@ -44,7 +44,16 @@ module.exports = DockerRunner = {
|
|||||||
ERR_EXITED: new Error('exited'),
|
ERR_EXITED: new Error('exited'),
|
||||||
ERR_TIMED_OUT: new Error('container timed out'),
|
ERR_TIMED_OUT: new Error('container timed out'),
|
||||||
|
|
||||||
run(project_id, command, directory, image, timeout, environment, callback) {
|
run(
|
||||||
|
project_id,
|
||||||
|
command,
|
||||||
|
directory,
|
||||||
|
image,
|
||||||
|
timeout,
|
||||||
|
environment,
|
||||||
|
compileGroup,
|
||||||
|
callback
|
||||||
|
) {
|
||||||
let name
|
let name
|
||||||
if (callback == null) {
|
if (callback == null) {
|
||||||
callback = function(error, output) {}
|
callback = function(error, output) {}
|
||||||
@@ -87,7 +96,8 @@ module.exports = DockerRunner = {
|
|||||||
image,
|
image,
|
||||||
volumes,
|
volumes,
|
||||||
timeout,
|
timeout,
|
||||||
environment
|
environment,
|
||||||
|
compileGroup
|
||||||
)
|
)
|
||||||
const fingerprint = DockerRunner._fingerprintContainer(options)
|
const fingerprint = DockerRunner._fingerprintContainer(options)
|
||||||
options.name = name = `project-${project_id}-${fingerprint}`
|
options.name = name = `project-${project_id}-${fingerprint}`
|
||||||
@@ -223,7 +233,14 @@ module.exports = DockerRunner = {
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
_getContainerOptions(command, image, volumes, timeout, environment) {
|
_getContainerOptions(
|
||||||
|
command,
|
||||||
|
image,
|
||||||
|
volumes,
|
||||||
|
timeout,
|
||||||
|
environment,
|
||||||
|
compileGroup
|
||||||
|
) {
|
||||||
let m, year
|
let m, year
|
||||||
let key, value, hostVol, dockerVol
|
let key, value, hostVol, dockerVol
|
||||||
const timeoutInSeconds = timeout / 1000
|
const timeoutInSeconds = timeout / 1000
|
||||||
@@ -310,6 +327,23 @@ module.exports = DockerRunner = {
|
|||||||
options.HostConfig.Runtime = Settings.clsi.docker.runtime
|
options.HostConfig.Runtime = Settings.clsi.docker.runtime
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Settings.clsi.docker.Readonly) {
|
||||||
|
options.HostConfig.ReadonlyRootfs = true
|
||||||
|
options.HostConfig.Tmpfs = { '/tmp': 'rw,noexec,nosuid,size=65536k' }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow per-compile group overriding of individual settings
|
||||||
|
if (
|
||||||
|
Settings.clsi.docker.compileGroupConfig &&
|
||||||
|
Settings.clsi.docker.compileGroupConfig[compileGroup]
|
||||||
|
) {
|
||||||
|
const override = Settings.clsi.docker.compileGroupConfig[compileGroup]
|
||||||
|
let key
|
||||||
|
for (key in override) {
|
||||||
|
_.set(options, key, override[key])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return options
|
return options
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -632,6 +666,9 @@ module.exports = DockerRunner = {
|
|||||||
ttl
|
ttl
|
||||||
) {
|
) {
|
||||||
if (name.slice(0, 9) === '/project-' && ttl <= 0) {
|
if (name.slice(0, 9) === '/project-' && ttl <= 0) {
|
||||||
|
// strip the / prefix
|
||||||
|
// the LockManager uses the plain container name
|
||||||
|
name = name.slice(1)
|
||||||
return jobs.push(cb =>
|
return jobs.push(cb =>
|
||||||
DockerRunner.destroyContainer(name, id, false, () => cb())
|
DockerRunner.destroyContainer(name, id, false, () => cb())
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ const Settings = require('settings-sharelatex')
|
|||||||
const logger = require('logger-sharelatex')
|
const logger = require('logger-sharelatex')
|
||||||
const Metrics = require('./Metrics')
|
const Metrics = require('./Metrics')
|
||||||
const CommandRunner = require('./CommandRunner')
|
const CommandRunner = require('./CommandRunner')
|
||||||
|
const fs = require('fs')
|
||||||
|
|
||||||
const ProcessTable = {} // table of currently running jobs (pids or docker container names)
|
const ProcessTable = {} // table of currently running jobs (pids or docker container names)
|
||||||
|
|
||||||
@@ -35,7 +36,8 @@ module.exports = LatexRunner = {
|
|||||||
timeout,
|
timeout,
|
||||||
image,
|
image,
|
||||||
environment,
|
environment,
|
||||||
flags
|
flags,
|
||||||
|
compileGroup
|
||||||
} = options
|
} = options
|
||||||
if (!compiler) {
|
if (!compiler) {
|
||||||
compiler = 'pdflatex'
|
compiler = 'pdflatex'
|
||||||
@@ -45,7 +47,15 @@ module.exports = LatexRunner = {
|
|||||||
} // milliseconds
|
} // milliseconds
|
||||||
|
|
||||||
logger.log(
|
logger.log(
|
||||||
{ directory, compiler, timeout, mainFile, environment, flags },
|
{
|
||||||
|
directory,
|
||||||
|
compiler,
|
||||||
|
timeout,
|
||||||
|
mainFile,
|
||||||
|
environment,
|
||||||
|
flags,
|
||||||
|
compileGroup
|
||||||
|
},
|
||||||
'starting compile'
|
'starting compile'
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -78,6 +88,7 @@ module.exports = LatexRunner = {
|
|||||||
image,
|
image,
|
||||||
timeout,
|
timeout,
|
||||||
environment,
|
environment,
|
||||||
|
compileGroup,
|
||||||
function(error, output) {
|
function(error, output) {
|
||||||
delete ProcessTable[id]
|
delete ProcessTable[id]
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
@@ -127,11 +138,39 @@ module.exports = LatexRunner = {
|
|||||||
: undefined,
|
: undefined,
|
||||||
x5 => x5[1]
|
x5 => x5[1]
|
||||||
) || 0
|
) || 0
|
||||||
return callback(error, output, stats, timings)
|
// record output files
|
||||||
|
LatexRunner.writeLogOutput(project_id, directory, output, () => {
|
||||||
|
return callback(error, output, stats, timings)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
},
|
},
|
||||||
|
|
||||||
|
writeLogOutput(project_id, directory, output, callback) {
|
||||||
|
if (!output) {
|
||||||
|
return callback()
|
||||||
|
}
|
||||||
|
// internal method for writing non-empty log files
|
||||||
|
function _writeFile(file, content, cb) {
|
||||||
|
if (content && content.length > 0) {
|
||||||
|
fs.writeFile(file, content, err => {
|
||||||
|
if (err) {
|
||||||
|
logger.error({ project_id, file }, 'error writing log file') // don't fail on error
|
||||||
|
}
|
||||||
|
cb()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
cb()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// write stdout and stderr, ignoring errors
|
||||||
|
_writeFile(Path.join(directory, 'output.stdout'), output.stdout, () => {
|
||||||
|
_writeFile(Path.join(directory, 'output.stderr'), output.stderr, () => {
|
||||||
|
callback()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
killLatex(project_id, callback) {
|
killLatex(project_id, callback) {
|
||||||
if (callback == null) {
|
if (callback == null) {
|
||||||
callback = function(error) {}
|
callback = function(error) {}
|
||||||
|
|||||||
@@ -20,7 +20,16 @@ const 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, environment, callback) {
|
run(
|
||||||
|
project_id,
|
||||||
|
command,
|
||||||
|
directory,
|
||||||
|
image,
|
||||||
|
timeout,
|
||||||
|
environment,
|
||||||
|
compileGroup,
|
||||||
|
callback
|
||||||
|
) {
|
||||||
let key, value
|
let key, value
|
||||||
if (callback == null) {
|
if (callback == null) {
|
||||||
callback = function(error) {}
|
callback = function(error) {}
|
||||||
@@ -46,7 +55,7 @@ module.exports = CommandRunner = {
|
|||||||
const proc = spawn(command[0], command.slice(1), { cwd: directory, env })
|
const proc = spawn(command[0], command.slice(1), { cwd: directory, env })
|
||||||
|
|
||||||
let stdout = ''
|
let stdout = ''
|
||||||
proc.stdout.on('data', data => (stdout += data))
|
proc.stdout.setEncoding('utf8').on('data', data => (stdout += data))
|
||||||
|
|
||||||
proc.on('error', function(err) {
|
proc.on('error', function(err) {
|
||||||
logger.err(
|
logger.err(
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ const fs = require('fs')
|
|||||||
const fse = require('fs-extra')
|
const fse = require('fs-extra')
|
||||||
const Path = require('path')
|
const Path = require('path')
|
||||||
const logger = require('logger-sharelatex')
|
const logger = require('logger-sharelatex')
|
||||||
const _ = require('underscore')
|
const _ = require('lodash')
|
||||||
const Settings = require('settings-sharelatex')
|
const Settings = require('settings-sharelatex')
|
||||||
const crypto = require('crypto')
|
const crypto = require('crypto')
|
||||||
|
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ module.exports = OutputFileFinder = {
|
|||||||
|
|
||||||
const proc = spawn('find', args)
|
const proc = spawn('find', args)
|
||||||
let stdout = ''
|
let stdout = ''
|
||||||
proc.stdout.on('data', chunk => (stdout += chunk.toString()))
|
proc.stdout.setEncoding('utf8').on('data', chunk => (stdout += chunk))
|
||||||
proc.on('error', callback)
|
proc.on('error', callback)
|
||||||
return proc.on('close', function(code) {
|
return proc.on('close', function(code) {
|
||||||
if (code !== 0) {
|
if (code !== 0) {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ const Path = require('path')
|
|||||||
const { spawn } = require('child_process')
|
const { spawn } = require('child_process')
|
||||||
const logger = require('logger-sharelatex')
|
const logger = require('logger-sharelatex')
|
||||||
const Metrics = require('./Metrics')
|
const Metrics = require('./Metrics')
|
||||||
const _ = require('underscore')
|
const _ = require('lodash')
|
||||||
|
|
||||||
module.exports = OutputFileOptimiser = {
|
module.exports = OutputFileOptimiser = {
|
||||||
optimiseFile(src, dst, callback) {
|
optimiseFile(src, dst, callback) {
|
||||||
@@ -45,8 +45,7 @@ module.exports = OutputFileOptimiser = {
|
|||||||
|
|
||||||
checkIfPDFIsOptimised(file, callback) {
|
checkIfPDFIsOptimised(file, callback) {
|
||||||
const SIZE = 16 * 1024 // check the header of the pdf
|
const SIZE = 16 * 1024 // check the header of the pdf
|
||||||
const result = new Buffer(SIZE)
|
const result = Buffer.alloc(SIZE) // fills with zeroes by default
|
||||||
result.fill(0) // prevent leakage of uninitialised buffer
|
|
||||||
return fs.open(file, 'r', function(err, fd) {
|
return fs.open(file, 'r', function(err, fd) {
|
||||||
if (err != null) {
|
if (err != null) {
|
||||||
return callback(err)
|
return callback(err)
|
||||||
@@ -78,7 +77,7 @@ module.exports = OutputFileOptimiser = {
|
|||||||
const timer = new Metrics.Timer('qpdf')
|
const timer = new Metrics.Timer('qpdf')
|
||||||
const proc = spawn('qpdf', args)
|
const proc = spawn('qpdf', args)
|
||||||
let stdout = ''
|
let stdout = ''
|
||||||
proc.stdout.on('data', chunk => (stdout += chunk.toString()))
|
proc.stdout.setEncoding('utf8').on('data', chunk => (stdout += chunk))
|
||||||
callback = _.once(callback) // avoid double call back for error and close event
|
callback = _.once(callback) // avoid double call back for error and close event
|
||||||
proc.on('error', function(err) {
|
proc.on('error', function(err) {
|
||||||
logger.warn({ err, args }, 'qpdf failed')
|
logger.warn({ err, args }, 'qpdf failed')
|
||||||
|
|||||||
@@ -20,10 +20,32 @@ const async = require('async')
|
|||||||
const logger = require('logger-sharelatex')
|
const logger = require('logger-sharelatex')
|
||||||
const oneDay = 24 * 60 * 60 * 1000
|
const oneDay = 24 * 60 * 60 * 1000
|
||||||
const Settings = require('settings-sharelatex')
|
const Settings = require('settings-sharelatex')
|
||||||
|
const diskusage = require('diskusage')
|
||||||
|
|
||||||
module.exports = ProjectPersistenceManager = {
|
module.exports = ProjectPersistenceManager = {
|
||||||
EXPIRY_TIMEOUT: Settings.project_cache_length_ms || oneDay * 2.5,
|
EXPIRY_TIMEOUT: Settings.project_cache_length_ms || oneDay * 2.5,
|
||||||
|
|
||||||
|
refreshExpiryTimeout(callback) {
|
||||||
|
if (callback == null) {
|
||||||
|
callback = function(error) {}
|
||||||
|
}
|
||||||
|
diskusage.check('/', function(err, stats) {
|
||||||
|
if (err) {
|
||||||
|
logger.err({ err: err }, 'error getting disk usage')
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
const lowDisk = stats.available / stats.total < 0.1
|
||||||
|
const lowerExpiry = ProjectPersistenceManager.EXPIRY_TIMEOUT * 0.9
|
||||||
|
if (lowDisk && Settings.project_cache_length_ms / 2 < lowerExpiry) {
|
||||||
|
logger.warn(
|
||||||
|
{ stats: stats },
|
||||||
|
'disk running low on space, modifying EXPIRY_TIMEOUT'
|
||||||
|
)
|
||||||
|
ProjectPersistenceManager.EXPIRY_TIMEOUT = lowerExpiry
|
||||||
|
}
|
||||||
|
callback()
|
||||||
|
})
|
||||||
|
},
|
||||||
markProjectAsJustAccessed(project_id, callback) {
|
markProjectAsJustAccessed(project_id, callback) {
|
||||||
if (callback == null) {
|
if (callback == null) {
|
||||||
callback = function(error) {}
|
callback = function(error) {}
|
||||||
|
|||||||
@@ -74,7 +74,17 @@ module.exports = RequestParser = {
|
|||||||
default: [],
|
default: [],
|
||||||
type: 'object'
|
type: 'object'
|
||||||
})
|
})
|
||||||
|
if (settings.allowedCompileGroups) {
|
||||||
|
response.compileGroup = this._parseAttribute(
|
||||||
|
'compileGroup',
|
||||||
|
compile.options.compileGroup,
|
||||||
|
{
|
||||||
|
validValues: settings.allowedCompileGroups,
|
||||||
|
default: '',
|
||||||
|
type: 'string'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
// The syncType specifies whether the request contains all
|
// The syncType specifies whether the request contains all
|
||||||
// resources (full) or only those resources to be updated
|
// resources (full) or only those resources to be updated
|
||||||
// in-place (incremental).
|
// in-place (incremental).
|
||||||
|
|||||||
@@ -231,7 +231,9 @@ module.exports = ResourceWriter = {
|
|||||||
path === 'output.pdf' ||
|
path === 'output.pdf' ||
|
||||||
path === 'output.dvi' ||
|
path === 'output.dvi' ||
|
||||||
path === 'output.log' ||
|
path === 'output.log' ||
|
||||||
path === 'output.xdv'
|
path === 'output.xdv' ||
|
||||||
|
path === 'output.stdout' ||
|
||||||
|
path === 'output.stderr'
|
||||||
) {
|
) {
|
||||||
should_delete = true
|
should_delete = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ module.exports = SafeReader = {
|
|||||||
}
|
}
|
||||||
return callback(null, ...Array.from(result))
|
return callback(null, ...Array.from(result))
|
||||||
})
|
})
|
||||||
const buff = new Buffer(size, 0) // fill with zeros
|
const buff = Buffer.alloc(size) // fills with zeroes by default
|
||||||
return fs.read(fd, buff, 0, buff.length, 0, function(
|
return fs.read(fd, buff, 0, buff.length, 0, function(
|
||||||
err,
|
err,
|
||||||
bytesRead,
|
bytesRead,
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ module.exports = UrlCache = {
|
|||||||
}
|
}
|
||||||
if (needsDownloading) {
|
if (needsDownloading) {
|
||||||
logger.log({ url, lastModified }, 'downloading URL')
|
logger.log({ url, lastModified }, 'downloading URL')
|
||||||
return UrlFetcher.pipeUrlToFile(
|
return UrlFetcher.pipeUrlToFileWithRetry(
|
||||||
url,
|
url,
|
||||||
UrlCache._cacheFilePathForUrl(project_id, url),
|
UrlCache._cacheFilePathForUrl(project_id, url),
|
||||||
error => {
|
error => {
|
||||||
|
|||||||
@@ -18,10 +18,18 @@ const fs = require('fs')
|
|||||||
const logger = require('logger-sharelatex')
|
const logger = require('logger-sharelatex')
|
||||||
const settings = require('settings-sharelatex')
|
const settings = require('settings-sharelatex')
|
||||||
const URL = require('url')
|
const URL = require('url')
|
||||||
|
const async = require('async')
|
||||||
|
|
||||||
const oneMinute = 60 * 1000
|
const oneMinute = 60 * 1000
|
||||||
|
|
||||||
module.exports = UrlFetcher = {
|
module.exports = UrlFetcher = {
|
||||||
|
pipeUrlToFileWithRetry(url, filePath, callback) {
|
||||||
|
const doDownload = function(cb) {
|
||||||
|
UrlFetcher.pipeUrlToFile(url, filePath, cb)
|
||||||
|
}
|
||||||
|
async.retry(3, doDownload, callback)
|
||||||
|
},
|
||||||
|
|
||||||
pipeUrlToFile(url, filePath, _callback) {
|
pipeUrlToFile(url, filePath, _callback) {
|
||||||
if (_callback == null) {
|
if (_callback == null) {
|
||||||
_callback = function(error) {}
|
_callback = function(error) {}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
*/
|
*/
|
||||||
const Sequelize = require('sequelize')
|
const Sequelize = require('sequelize')
|
||||||
const Settings = require('settings-sharelatex')
|
const Settings = require('settings-sharelatex')
|
||||||
const _ = require('underscore')
|
const _ = require('lodash')
|
||||||
const logger = require('logger-sharelatex')
|
const logger = require('logger-sharelatex')
|
||||||
|
|
||||||
const options = _.extend({ logging: false }, Settings.mysql.clsi)
|
const options = _.extend({ logging: false }, Settings.mysql.clsi)
|
||||||
|
|||||||
@@ -6,6 +6,6 @@ clsi
|
|||||||
--env-add=
|
--env-add=
|
||||||
--env-pass-through=TEXLIVE_IMAGE
|
--env-pass-through=TEXLIVE_IMAGE
|
||||||
--language=es
|
--language=es
|
||||||
--node-version=10.19.0
|
--node-version=10.21.0
|
||||||
--public-repo=True
|
--public-repo=True
|
||||||
--script-version=2.1.0
|
--script-version=2.1.0
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ module.exports = {
|
|||||||
username: 'clsi',
|
username: 'clsi',
|
||||||
dialect: 'sqlite',
|
dialect: 'sqlite',
|
||||||
storage:
|
storage:
|
||||||
process.env.SQLITE_PATH || Path.resolve(__dirname + '/../db/db.sqlite'),
|
process.env.SQLITE_PATH || Path.resolve(__dirname, '../db/db.sqlite'),
|
||||||
pool: {
|
pool: {
|
||||||
max: 1,
|
max: 1,
|
||||||
min: 1
|
min: 1
|
||||||
@@ -26,10 +26,10 @@ module.exports = {
|
|||||||
parseInt(process.env.PROCESS_LIFE_SPAN_LIMIT_MS) || 60 * 60 * 24 * 1000 * 2,
|
parseInt(process.env.PROCESS_LIFE_SPAN_LIMIT_MS) || 60 * 60 * 24 * 1000 * 2,
|
||||||
|
|
||||||
path: {
|
path: {
|
||||||
compilesDir: Path.resolve(__dirname + '/../compiles'),
|
compilesDir: Path.resolve(__dirname, '../compiles'),
|
||||||
clsiCacheDir: Path.resolve(__dirname + '/../cache'),
|
clsiCacheDir: Path.resolve(__dirname, '../cache'),
|
||||||
synctexBaseDir(project_id) {
|
synctexBaseDir(projectId) {
|
||||||
return Path.join(this.compilesDir, project_id)
|
return Path.join(this.compilesDir, projectId)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -57,13 +57,25 @@ module.exports = {
|
|||||||
parallelSqlQueryLimit: process.env.FILESTORE_PARALLEL_SQL_QUERY_LIMIT || 1,
|
parallelSqlQueryLimit: process.env.FILESTORE_PARALLEL_SQL_QUERY_LIMIT || 1,
|
||||||
filestoreDomainOveride: process.env.FILESTORE_DOMAIN_OVERRIDE,
|
filestoreDomainOveride: process.env.FILESTORE_DOMAIN_OVERRIDE,
|
||||||
texliveImageNameOveride: process.env.TEX_LIVE_IMAGE_NAME_OVERRIDE,
|
texliveImageNameOveride: process.env.TEX_LIVE_IMAGE_NAME_OVERRIDE,
|
||||||
|
texliveOpenoutAny: process.env.TEXLIVE_OPENOUT_ANY,
|
||||||
sentry: {
|
sentry: {
|
||||||
dsn: process.env.SENTRY_DSN
|
dsn: process.env.SENTRY_DSN
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (process.env.ALLOWED_COMPILE_GROUPS) {
|
||||||
|
try {
|
||||||
|
module.exports.allowedCompileGroups = process.env.ALLOWED_COMPILE_GROUPS.split(
|
||||||
|
' '
|
||||||
|
)
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error, 'could not apply allowed compile group setting')
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (process.env.DOCKER_RUNNER) {
|
if (process.env.DOCKER_RUNNER) {
|
||||||
let seccomp_profile_path
|
let seccompProfilePath
|
||||||
module.exports.clsi = {
|
module.exports.clsi = {
|
||||||
dockerRunner: process.env.DOCKER_RUNNER === 'true',
|
dockerRunner: process.env.DOCKER_RUNNER === 'true',
|
||||||
docker: {
|
docker: {
|
||||||
@@ -76,22 +88,45 @@ if (process.env.DOCKER_RUNNER) {
|
|||||||
socketPath: '/var/run/docker.sock',
|
socketPath: '/var/run/docker.sock',
|
||||||
user: process.env.TEXLIVE_IMAGE_USER || 'tex'
|
user: process.env.TEXLIVE_IMAGE_USER || 'tex'
|
||||||
},
|
},
|
||||||
|
optimiseInDocker: true,
|
||||||
expireProjectAfterIdleMs: 24 * 60 * 60 * 1000,
|
expireProjectAfterIdleMs: 24 * 60 * 60 * 1000,
|
||||||
checkProjectsIntervalMs: 10 * 60 * 1000
|
checkProjectsIntervalMs: 10 * 60 * 1000
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
seccomp_profile_path = Path.resolve(
|
// Override individual docker settings using path-based keys, e.g.:
|
||||||
__dirname + '/../seccomp/clsi-profile.json'
|
// compileGroupDockerConfigs = {
|
||||||
|
// priority: { 'HostConfig.CpuShares': 100 }
|
||||||
|
// beta: { 'dotted.path.here', 'value'}
|
||||||
|
// }
|
||||||
|
const compileGroupConfig = JSON.parse(
|
||||||
|
process.env.COMPILE_GROUP_DOCKER_CONFIGS || '{}'
|
||||||
)
|
)
|
||||||
module.exports.clsi.docker.seccomp_profile = JSON.stringify(
|
// Automatically clean up wordcount and synctex containers
|
||||||
JSON.parse(require('fs').readFileSync(seccomp_profile_path))
|
const defaultCompileGroupConfig = {
|
||||||
|
wordcount: { 'HostConfig.AutoRemove': true },
|
||||||
|
synctex: { 'HostConfig.AutoRemove': true }
|
||||||
|
}
|
||||||
|
module.exports.clsi.docker.compileGroupConfig = Object.assign(
|
||||||
|
defaultCompileGroupConfig,
|
||||||
|
compileGroupConfig
|
||||||
)
|
)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(
|
console.error(error, 'could not apply compile group docker configs')
|
||||||
error,
|
process.exit(1)
|
||||||
`could not load seccom profile from ${seccomp_profile_path}`
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
seccompProfilePath = Path.resolve(__dirname, '../seccomp/clsi-profile.json')
|
||||||
|
module.exports.clsi.docker.seccomp_profile = JSON.stringify(
|
||||||
|
JSON.parse(require('fs').readFileSync(seccompProfilePath))
|
||||||
)
|
)
|
||||||
|
} catch (error) {
|
||||||
|
console.error(
|
||||||
|
error,
|
||||||
|
`could not load seccomp profile from ${seccompProfilePath}`
|
||||||
|
)
|
||||||
|
process.exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.path.synctexBaseDir = () => '/compile'
|
module.exports.path.synctexBaseDir = () => '/compile'
|
||||||
|
|||||||
562
package-lock.json
generated
562
package-lock.json
generated
@@ -163,9 +163,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@google-cloud/common": {
|
"@google-cloud/common": {
|
||||||
"version": "2.2.3",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-2.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-2.4.0.tgz",
|
||||||
"integrity": "sha512-lvw54mGKn8VqVIy2NzAk0l5fntBFX4UwQhHk6HaqkyCQ7WBl5oz4XhzKMtMilozF/3ObPcDogqwuyEWyZ6rnQQ==",
|
"integrity": "sha512-zWFjBS35eI9leAHhjfeOYlK5Plcuj/77EzstnrJIZbKgF/nkqjcQuGiMCpzCwOfPyUbz8ZaEOYgbHa759AKbjg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@google-cloud/projectify": "^1.0.0",
|
"@google-cloud/projectify": "^1.0.0",
|
||||||
"@google-cloud/promisify": "^1.0.0",
|
"@google-cloud/promisify": "^1.0.0",
|
||||||
@@ -175,7 +175,7 @@
|
|||||||
"extend": "^3.0.2",
|
"extend": "^3.0.2",
|
||||||
"google-auth-library": "^5.5.0",
|
"google-auth-library": "^5.5.0",
|
||||||
"retry-request": "^4.0.0",
|
"retry-request": "^4.0.0",
|
||||||
"teeny-request": "^5.2.1"
|
"teeny-request": "^6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@google-cloud/debug-agent": {
|
"@google-cloud/debug-agent": {
|
||||||
@@ -346,44 +346,51 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@google-cloud/logging": {
|
"@google-cloud/logging": {
|
||||||
"version": "5.5.3",
|
"version": "7.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@google-cloud/logging/-/logging-5.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/@google-cloud/logging/-/logging-7.3.0.tgz",
|
||||||
"integrity": "sha512-TZ/DzHod4icaC7wEEBm0PHYfbhvg0CbCVzKLsdAwj11xSD/egGNOsG5optEQcbAQEPrO1B5xBXfsE0wIBBYjpQ==",
|
"integrity": "sha512-xTW1V4MKpYC0mjSugyuiyUoZ9g6A42IhrrO3z7Tt3SmAb2IRj2Gf4RLoguKKncs340ooZFXrrVN/++t2Aj5zgg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@google-cloud/common": "^2.2.2",
|
"@google-cloud/common": "^2.2.2",
|
||||||
"@google-cloud/paginator": "^2.0.0",
|
"@google-cloud/paginator": "^2.0.0",
|
||||||
"@google-cloud/projectify": "^1.0.0",
|
"@google-cloud/projectify": "^1.0.0",
|
||||||
"@google-cloud/promisify": "^1.0.0",
|
"@google-cloud/promisify": "^1.0.0",
|
||||||
"@opencensus/propagation-stackdriver": "0.0.18",
|
"@opencensus/propagation-stackdriver": "0.0.20",
|
||||||
"arrify": "^2.0.0",
|
"arrify": "^2.0.0",
|
||||||
"dot-prop": "^5.1.0",
|
"dot-prop": "^5.1.0",
|
||||||
"eventid": "^0.1.2",
|
"eventid": "^1.0.0",
|
||||||
"extend": "^3.0.2",
|
"extend": "^3.0.2",
|
||||||
"gcp-metadata": "^3.1.0",
|
"gcp-metadata": "^3.1.0",
|
||||||
"google-gax": "^1.7.5",
|
"google-auth-library": "^5.2.2",
|
||||||
|
"google-gax": "^1.11.0",
|
||||||
"is": "^3.3.0",
|
"is": "^3.3.0",
|
||||||
"on-finished": "^2.3.0",
|
"on-finished": "^2.3.0",
|
||||||
"protobufjs": "^6.8.8",
|
|
||||||
"pumpify": "^2.0.0",
|
"pumpify": "^2.0.0",
|
||||||
"snakecase-keys": "^3.0.0",
|
"snakecase-keys": "^3.0.0",
|
||||||
"stream-events": "^1.0.4",
|
"stream-events": "^1.0.4",
|
||||||
"through2": "^3.0.0",
|
"through2": "^3.0.0",
|
||||||
"type-fest": "^0.8.0"
|
"type-fest": "^0.12.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"type-fest": {
|
||||||
|
"version": "0.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.12.0.tgz",
|
||||||
|
"integrity": "sha512-53RyidyjvkGpnWPMF9bQgFtWp+Sl8O2Rp13VavmJgfAP9WWG6q6TkrKU8iyJdnwnfgHI6k2hTlgqH4aSdjoTbg=="
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@google-cloud/logging-bunyan": {
|
"@google-cloud/logging-bunyan": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@google-cloud/logging-bunyan/-/logging-bunyan-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@google-cloud/logging-bunyan/-/logging-bunyan-2.0.3.tgz",
|
||||||
"integrity": "sha512-9W9B8GQNMlBdQSV+c0492+sMMknn4/428EdSO1xv5Hn07P32N/e4T25y4Gnl9jlrItuZHIXRwYPVSHqUyGb1Zg==",
|
"integrity": "sha512-8n9MwsCRd4v8WZg17+d3m7qInud7lYTm5rpwXHY0/lzWEJYjeiztT09BiCYh56EEhHr+ynymJnzUDZKazkywlg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@google-cloud/logging": "^5.5.2",
|
"@google-cloud/logging": "^7.0.0",
|
||||||
"google-auth-library": "^5.0.0"
|
"google-auth-library": "^5.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@google-cloud/paginator": {
|
"@google-cloud/paginator": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-2.0.3.tgz",
|
||||||
"integrity": "sha512-HZ6UTGY/gHGNriD7OCikYWL/Eu0sTEur2qqse2w6OVsz+57se3nTkqH14JIPxtf0vlEJ8IJN5w3BdZ22pjCB8g==",
|
"integrity": "sha512-kp/pkb2p/p0d8/SKUu4mOq8+HGwF8NPzHWkj+VKrIPQPyMRw8deZtrO/OcSiy9C/7bpfU5Txah5ltUNfPkgEXg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"arrify": "^2.0.0",
|
"arrify": "^2.0.0",
|
||||||
"extend": "^3.0.2"
|
"extend": "^3.0.2"
|
||||||
@@ -557,14 +564,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@google-cloud/projectify": {
|
"@google-cloud/projectify": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-1.0.4.tgz",
|
||||||
"integrity": "sha512-xknDOmsMgOYHksKc1GPbwDLsdej8aRNIA17SlSZgQdyrcC0lx0OGo4VZgYfwoEU1YS8oUxF9Y+6EzDOb0eB7Xg=="
|
"integrity": "sha512-ZdzQUN02eRsmTKfBj9FDL0KNDIFNjBn/d6tHQmA/+FImH5DO6ZV8E7FzxMgAUiVAUq41RFAkb25p1oHOZ8psfg=="
|
||||||
},
|
},
|
||||||
"@google-cloud/promisify": {
|
"@google-cloud/promisify": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-1.0.4.tgz",
|
||||||
"integrity": "sha512-7WfV4R/3YV5T30WRZW0lqmvZy9hE2/p9MvpI34WuKa2Wz62mLu5XplGTFEMK6uTbJCLWUxTcZ4J4IyClKucE5g=="
|
"integrity": "sha512-VccZDcOql77obTnFh0TbNED/6ZbbmHDf8UMNnzO1d5g9V0Htfm4k5cllY8P1tJsRKC3zWYGRLaViiupcgVjBoQ=="
|
||||||
},
|
},
|
||||||
"@google-cloud/trace-agent": {
|
"@google-cloud/trace-agent": {
|
||||||
"version": "3.6.1",
|
"version": "3.6.1",
|
||||||
@@ -728,9 +735,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@grpc/grpc-js": {
|
"@grpc/grpc-js": {
|
||||||
"version": "0.6.9",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-0.6.9.tgz",
|
"resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.0.5.tgz",
|
||||||
"integrity": "sha512-r1nDOEEiYmAsVYBaS4DPPqdwPOXPw7YhVOnnpPdWhlNtKbYzPash6DqWTTza9gBiYMA5d2Wiq6HzrPqsRaP4yA==",
|
"integrity": "sha512-Hm+xOiqAhcpT9RYM8lc15dbQD7aQurM7ZU8ulmulepiPlN7iwBXXwP3vSBUimoFoApRqz7pSIisXU8pZaCB4og==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"semver": "^6.2.0"
|
"semver": "^6.2.0"
|
||||||
},
|
},
|
||||||
@@ -743,18 +750,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@grpc/proto-loader": {
|
"@grpc/proto-loader": {
|
||||||
"version": "0.5.2",
|
"version": "0.5.4",
|
||||||
"resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.5.4.tgz",
|
||||||
"integrity": "sha512-eBKD/FPxQoY1x6QONW2nBd54QUEyzcFP9FenujmoeDPy1rutVSHki1s/wR68F6O1QfCNDx+ayBH1O2CVNMzyyw==",
|
"integrity": "sha512-HTM4QpI9B2XFkPz7pjwMyMgZchJ93TVkL3kWPW8GDMDKYxsMnmf4w2TNMJK7+KNiYHS5cJrCEAFlF+AwtXWVPA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"lodash.camelcase": "^4.3.0",
|
"lodash.camelcase": "^4.3.0",
|
||||||
"protobufjs": "^6.8.6"
|
"protobufjs": "^6.8.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@opencensus/core": {
|
"@opencensus/core": {
|
||||||
"version": "0.0.18",
|
"version": "0.0.20",
|
||||||
"resolved": "https://registry.npmjs.org/@opencensus/core/-/core-0.0.18.tgz",
|
"resolved": "https://registry.npmjs.org/@opencensus/core/-/core-0.0.20.tgz",
|
||||||
"integrity": "sha512-PgRQXLyb3bLi8Z6pQct9erYFRdnYAZNQXAEVPf6Xq6IMkZaH20wiOTNNPxEckjI31mq5utgstAbwOn4gJiPjBQ==",
|
"integrity": "sha512-vqOuTd2yuMpKohp8TNNGUAPjWEGjlnGfB9Rh5e3DKqeyR94YgierNs4LbMqxKtsnwB8Dm2yoEtRuUgoe5vD9DA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"continuation-local-storage": "^3.2.1",
|
"continuation-local-storage": "^3.2.1",
|
||||||
"log-driver": "^1.2.7",
|
"log-driver": "^1.2.7",
|
||||||
@@ -771,19 +778,19 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@opencensus/propagation-stackdriver": {
|
"@opencensus/propagation-stackdriver": {
|
||||||
"version": "0.0.18",
|
"version": "0.0.20",
|
||||||
"resolved": "https://registry.npmjs.org/@opencensus/propagation-stackdriver/-/propagation-stackdriver-0.0.18.tgz",
|
"resolved": "https://registry.npmjs.org/@opencensus/propagation-stackdriver/-/propagation-stackdriver-0.0.20.tgz",
|
||||||
"integrity": "sha512-BLwfszIGAfqN2mqGf/atfEu84cWeoLM/YuXGfXDO1iDN2k5GXz4QFyhS8sz5l63HtsYuQqFuV+Ze7ZM0NvJp2A==",
|
"integrity": "sha512-P8yuHSLtce+yb+2EZjtTVqG7DQ48laC+IuOWi3X9q78s1Gni5F9+hmbmyP6Nb61jb5BEvXQX1s2rtRI6bayUWA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@opencensus/core": "^0.0.18",
|
"@opencensus/core": "^0.0.20",
|
||||||
"hex2dec": "^1.0.1",
|
"hex2dec": "^1.0.1",
|
||||||
"uuid": "^3.2.1"
|
"uuid": "^3.2.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@overleaf/o-error": {
|
"@overleaf/o-error": {
|
||||||
"version": "2.1.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@overleaf/o-error/-/o-error-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@overleaf/o-error/-/o-error-3.0.0.tgz",
|
||||||
"integrity": "sha512-Zd9sks9LrLw8ErHt/cXeWIkyxWAqNAvNGn7wIjLQJH6TTEEW835PWOhpch+hQwwWsTxWIx/JDj+IpZ3ouw925g=="
|
"integrity": "sha512-LsM2s6Iy9G97ktPo0ys4VxtI/m3ahc1ZHwjo5XnhXtjeIkkkVAehsrcRRoV/yWepPjymB0oZonhcfojpjYR/tg=="
|
||||||
},
|
},
|
||||||
"@protobufjs/aspromise": {
|
"@protobufjs/aspromise": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
@@ -905,6 +912,11 @@
|
|||||||
"integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==",
|
"integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@tootallnate/once": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw=="
|
||||||
|
},
|
||||||
"@types/caseless": {
|
"@types/caseless": {
|
||||||
"version": "0.12.2",
|
"version": "0.12.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz",
|
||||||
@@ -935,6 +947,14 @@
|
|||||||
"integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==",
|
"integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/fs-extra": {
|
||||||
|
"version": "8.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.1.tgz",
|
||||||
|
"integrity": "sha512-TcUlBem321DFQzBNuz8p0CLLKp0VvF/XH9E4KHNmgwyp4E3AfgI5cjiIVZWlbfThBop2qxFIh4+LeY6hVWWZ2w==",
|
||||||
|
"requires": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/json-schema": {
|
"@types/json-schema": {
|
||||||
"version": "7.0.4",
|
"version": "7.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz",
|
||||||
@@ -1216,7 +1236,7 @@
|
|||||||
"asn1": {
|
"asn1": {
|
||||||
"version": "0.2.4",
|
"version": "0.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
|
||||||
"integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
|
"integrity": "sha1-jSR136tVO7M+d7VOWeiAu4ziMTY=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"safer-buffer": "~2.1.0"
|
"safer-buffer": "~2.1.0"
|
||||||
}
|
}
|
||||||
@@ -1434,7 +1454,7 @@
|
|||||||
"buffer-from": {
|
"buffer-from": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
|
||||||
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
|
"integrity": "sha1-MnE7wCj3XAL9txDXx7zsHyxgcO8="
|
||||||
},
|
},
|
||||||
"builtin-modules": {
|
"builtin-modules": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
@@ -1445,7 +1465,6 @@
|
|||||||
"version": "1.8.12",
|
"version": "1.8.12",
|
||||||
"resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.12.tgz",
|
"resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.12.tgz",
|
||||||
"integrity": "sha1-8VDw9nSKvdcq6uhPBEA74u8RN5c=",
|
"integrity": "sha1-8VDw9nSKvdcq6uhPBEA74u8RN5c=",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"dtrace-provider": "~0.8",
|
"dtrace-provider": "~0.8",
|
||||||
"moment": "^2.10.6",
|
"moment": "^2.10.6",
|
||||||
@@ -1669,11 +1688,6 @@
|
|||||||
"delayed-stream": "~1.0.0"
|
"delayed-stream": "~1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"commander": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "http://registry.npmjs.org/commander/-/commander-2.0.0.tgz",
|
|
||||||
"integrity": "sha1-0bhvkB+LZL2UG96tr5JFMDk76Sg="
|
|
||||||
},
|
|
||||||
"common-tags": {
|
"common-tags": {
|
||||||
"version": "1.8.0",
|
"version": "1.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz",
|
||||||
@@ -1735,7 +1749,7 @@
|
|||||||
"content-type": {
|
"content-type": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
|
||||||
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
|
"integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js="
|
||||||
},
|
},
|
||||||
"continuation-local-storage": {
|
"continuation-local-storage": {
|
||||||
"version": "3.2.1",
|
"version": "3.2.1",
|
||||||
@@ -1878,10 +1892,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
|
||||||
"integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups="
|
"integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups="
|
||||||
},
|
},
|
||||||
"diff": {
|
"diskusage": {
|
||||||
"version": "1.0.7",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/diff/-/diff-1.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/diskusage/-/diskusage-1.1.3.tgz",
|
||||||
"integrity": "sha1-JLuwAcSn1VIhaefKvbLCgU7ZHPQ="
|
"integrity": "sha512-EAyaxl8hy4Ph07kzlzGTfpbZMNAAAHXSZtNEMwdlnSd1noHzvA6HsgKt4fEMSvaEXQYLSphe5rPMxN4WOj0hcQ==",
|
||||||
|
"requires": {
|
||||||
|
"es6-promise": "^4.2.5",
|
||||||
|
"nan": "^2.14.0"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"dlv": {
|
"dlv": {
|
||||||
"version": "1.1.3",
|
"version": "1.1.3",
|
||||||
@@ -1945,9 +1963,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dot-prop": {
|
"dot-prop": {
|
||||||
"version": "5.1.1",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz",
|
||||||
"integrity": "sha512-QCHI6Lkf+9fJMpwfAFsTvbiSh6ujoPmhCLiDvD/n4dGtLvHfhuBwPdN6z2x4YSOwwtTcLoO/LP70xELWGF/JVA==",
|
"integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"is-obj": "^2.0.0"
|
"is-obj": "^2.0.0"
|
||||||
}
|
}
|
||||||
@@ -1961,7 +1979,6 @@
|
|||||||
"version": "0.8.8",
|
"version": "0.8.8",
|
||||||
"resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.8.tgz",
|
"resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.8.tgz",
|
||||||
"integrity": "sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg==",
|
"integrity": "sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg==",
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"nan": "^2.14.0"
|
"nan": "^2.14.0"
|
||||||
@@ -1971,7 +1988,6 @@
|
|||||||
"version": "2.14.0",
|
"version": "2.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
|
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
|
||||||
"integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==",
|
"integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==",
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
"optional": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2614,9 +2630,9 @@
|
|||||||
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="
|
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="
|
||||||
},
|
},
|
||||||
"eventid": {
|
"eventid": {
|
||||||
"version": "0.1.2",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/eventid/-/eventid-0.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/eventid/-/eventid-1.0.0.tgz",
|
||||||
"integrity": "sha1-CyMtPiROpbHVKJhBQOpprH7IkhU=",
|
"integrity": "sha512-4upSDsvpxhWPsmw4fsJCp0zj8S7I0qh1lCDTmZXP8V3TtryQKDI8CgQPN+e5JakbWwzaAX3lrdp2b3KSoMSUpw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"d64": "^1.0.0",
|
"d64": "^1.0.0",
|
||||||
"uuid": "^3.0.1"
|
"uuid": "^3.0.1"
|
||||||
@@ -2848,7 +2864,7 @@
|
|||||||
"form-data": {
|
"form-data": {
|
||||||
"version": "2.3.3",
|
"version": "2.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
|
||||||
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
|
"integrity": "sha1-3M5SwF9kTymManq5Nr1yTO/786Y=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"asynckit": "^0.4.0",
|
"asynckit": "^0.4.0",
|
||||||
"combined-stream": "^1.0.6",
|
"combined-stream": "^1.0.6",
|
||||||
@@ -2868,7 +2884,7 @@
|
|||||||
"fs-constants": {
|
"fs-constants": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||||
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
|
"integrity": "sha1-a+Dem+mYzhavivwkSXue6bfM2a0="
|
||||||
},
|
},
|
||||||
"fs-extra": {
|
"fs-extra": {
|
||||||
"version": "8.1.0",
|
"version": "8.1.0",
|
||||||
@@ -2928,23 +2944,23 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"gaxios": {
|
"gaxios": {
|
||||||
"version": "2.1.0",
|
"version": "2.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/gaxios/-/gaxios-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/gaxios/-/gaxios-2.3.4.tgz",
|
||||||
"integrity": "sha512-Gtpb5sdQmb82sgVkT2GnS2n+Kx4dlFwbeMYcDlD395aEvsLCSQXJJcHt7oJ2LrGxDEAeiOkK79Zv2A8Pzt6CFg==",
|
"integrity": "sha512-US8UMj8C5pRnao3Zykc4AAVr+cffoNKRTg9Rsf2GiuZCW69vgJj38VK2PzlPuQU73FZ/nTk9/Av6/JGcE1N9vA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"abort-controller": "^3.0.0",
|
"abort-controller": "^3.0.0",
|
||||||
"extend": "^3.0.2",
|
"extend": "^3.0.2",
|
||||||
"https-proxy-agent": "^3.0.0",
|
"https-proxy-agent": "^5.0.0",
|
||||||
"is-stream": "^2.0.0",
|
"is-stream": "^2.0.0",
|
||||||
"node-fetch": "^2.3.0"
|
"node-fetch": "^2.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"gcp-metadata": {
|
"gcp-metadata": {
|
||||||
"version": "3.2.0",
|
"version": "3.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-3.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-3.5.0.tgz",
|
||||||
"integrity": "sha512-ympv+yQ6k5QuWCuwQqnGEvFGS7MBKdcQdj1i188v3bW9QLFIchTGaBCEZxSQapT0jffdn1vdt8oJhB5VBWQO1Q==",
|
"integrity": "sha512-ZQf+DLZ5aKcRpLzYUyBS3yo3N0JSa82lNDO8rj3nMSlovLcz2riKFBsYgDzeXcv75oo5eqB2lx+B14UvPoCRnA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"gaxios": "^2.0.1",
|
"gaxios": "^2.1.0",
|
||||||
"json-bigint": "^0.3.0"
|
"json-bigint": "^0.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3003,27 +3019,51 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"google-auth-library": {
|
"google-auth-library": {
|
||||||
"version": "5.5.1",
|
"version": "5.10.1",
|
||||||
"resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-5.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-5.10.1.tgz",
|
||||||
"integrity": "sha512-zCtjQccWS/EHYyFdXRbfeSGM/gW+d7uMAcVnvXRnjBXON5ijo6s0nsObP0ifqileIDSbZjTlLtgo+UoN8IFJcg==",
|
"integrity": "sha512-rOlaok5vlpV9rSiUu5EpR0vVpc+PhN62oF4RyX/6++DG1VsaulAFEMlDYBLjJDDPI6OcNOCGAKy9UVB/3NIDXg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"arrify": "^2.0.0",
|
"arrify": "^2.0.0",
|
||||||
"base64-js": "^1.3.0",
|
"base64-js": "^1.3.0",
|
||||||
|
"ecdsa-sig-formatter": "^1.0.11",
|
||||||
"fast-text-encoding": "^1.0.0",
|
"fast-text-encoding": "^1.0.0",
|
||||||
"gaxios": "^2.1.0",
|
"gaxios": "^2.1.0",
|
||||||
"gcp-metadata": "^3.2.0",
|
"gcp-metadata": "^3.4.0",
|
||||||
"gtoken": "^4.1.0",
|
"gtoken": "^4.1.0",
|
||||||
"jws": "^3.1.5",
|
"jws": "^4.0.0",
|
||||||
"lru-cache": "^5.0.0"
|
"lru-cache": "^5.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"jwa": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==",
|
||||||
|
"requires": {
|
||||||
|
"buffer-equal-constant-time": "1.0.1",
|
||||||
|
"ecdsa-sig-formatter": "1.0.11",
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"jws": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==",
|
||||||
|
"requires": {
|
||||||
|
"jwa": "^2.0.0",
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"google-gax": {
|
"google-gax": {
|
||||||
"version": "1.7.5",
|
"version": "1.15.3",
|
||||||
"resolved": "https://registry.npmjs.org/google-gax/-/google-gax-1.7.5.tgz",
|
"resolved": "https://registry.npmjs.org/google-gax/-/google-gax-1.15.3.tgz",
|
||||||
"integrity": "sha512-Tz2DFs8umzDcCBTi2W1cY4vEgAKaYRj70g6Hh/MiiZaJizrly7PgyxsIYUGi7sOpEuAbARQymYKvy5mNi8hEbg==",
|
"integrity": "sha512-3JKJCRumNm3x2EksUTw4P1Rad43FTpqrtW9jzpf3xSMYXx+ogaqTM1vGo7VixHB4xkAyATXVIa3OcNSh8H9zsQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@grpc/grpc-js": "0.6.9",
|
"@grpc/grpc-js": "~1.0.3",
|
||||||
"@grpc/proto-loader": "^0.5.1",
|
"@grpc/proto-loader": "^0.5.1",
|
||||||
|
"@types/fs-extra": "^8.0.1",
|
||||||
|
"@types/long": "^4.0.0",
|
||||||
"abort-controller": "^3.0.0",
|
"abort-controller": "^3.0.0",
|
||||||
"duplexify": "^3.6.0",
|
"duplexify": "^3.6.0",
|
||||||
"google-auth-library": "^5.0.0",
|
"google-auth-library": "^5.0.0",
|
||||||
@@ -3031,12 +3071,44 @@
|
|||||||
"lodash.at": "^4.6.0",
|
"lodash.at": "^4.6.0",
|
||||||
"lodash.has": "^4.5.2",
|
"lodash.has": "^4.5.2",
|
||||||
"node-fetch": "^2.6.0",
|
"node-fetch": "^2.6.0",
|
||||||
"protobufjs": "^6.8.8",
|
"protobufjs": "^6.8.9",
|
||||||
"retry-request": "^4.0.0",
|
"retry-request": "^4.0.0",
|
||||||
"semver": "^6.0.0",
|
"semver": "^6.0.0",
|
||||||
"walkdir": "^0.4.0"
|
"walkdir": "^0.4.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/node": {
|
||||||
|
"version": "13.13.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.12.tgz",
|
||||||
|
"integrity": "sha512-zWz/8NEPxoXNT9YyF2osqyA9WjssZukYpgI4UYZpOjcyqwIUqWGkcCionaEb9Ki+FULyPyvNFpg/329Kd2/pbw=="
|
||||||
|
},
|
||||||
|
"protobufjs": {
|
||||||
|
"version": "6.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.9.0.tgz",
|
||||||
|
"integrity": "sha512-LlGVfEWDXoI/STstRDdZZKb/qusoAWUnmLg9R8OLSO473mBLWHowx8clbX5/+mKDEI+v7GzjoK9tRPZMMcoTrg==",
|
||||||
|
"requires": {
|
||||||
|
"@protobufjs/aspromise": "^1.1.2",
|
||||||
|
"@protobufjs/base64": "^1.1.2",
|
||||||
|
"@protobufjs/codegen": "^2.0.4",
|
||||||
|
"@protobufjs/eventemitter": "^1.1.0",
|
||||||
|
"@protobufjs/fetch": "^1.1.0",
|
||||||
|
"@protobufjs/float": "^1.0.2",
|
||||||
|
"@protobufjs/inquire": "^1.1.0",
|
||||||
|
"@protobufjs/path": "^1.1.2",
|
||||||
|
"@protobufjs/pool": "^1.1.0",
|
||||||
|
"@protobufjs/utf8": "^1.1.0",
|
||||||
|
"@types/long": "^4.0.1",
|
||||||
|
"@types/node": "^13.7.0",
|
||||||
|
"long": "^4.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/long": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "6.3.0",
|
"version": "6.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||||
@@ -3045,9 +3117,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"google-p12-pem": {
|
"google-p12-pem": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-2.0.4.tgz",
|
||||||
"integrity": "sha512-UfnEARfJKI6pbmC1hfFFm+UAcZxeIwTiEcHfqKe/drMsXD/ilnVjF7zgOGpHXyhuvX6jNJK3S8A0hOQjwtFxEw==",
|
"integrity": "sha512-S4blHBQWZRnEW44OcR7TL9WR+QCqByRvhNDZ/uuQfpxywfupikf/miba8js1jZi6ZOGv5slgSuoshCWh6EMDzg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"node-forge": "^0.9.0"
|
"node-forge": "^0.9.0"
|
||||||
}
|
}
|
||||||
@@ -3057,26 +3129,40 @@
|
|||||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
|
||||||
"integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ=="
|
"integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ=="
|
||||||
},
|
},
|
||||||
"growl": {
|
|
||||||
"version": "1.7.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/growl/-/growl-1.7.0.tgz",
|
|
||||||
"integrity": "sha1-3i1mE20ALhErpw8/EMMc98NQsto="
|
|
||||||
},
|
|
||||||
"gtoken": {
|
"gtoken": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/gtoken/-/gtoken-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/gtoken/-/gtoken-4.1.4.tgz",
|
||||||
"integrity": "sha512-wqyn2gf5buzEZN4QNmmiiW2i2JkEdZnL7Z/9p44RtZqgt4077m4khRgAYNuu8cBwHWCc6MsP6eDUn/KkF6jFIw==",
|
"integrity": "sha512-VxirzD0SWoFUo5p8RDP8Jt2AGyOmyYcT/pOUgDKJCK+iSw0TMqwrVfY37RXTNmoKwrzmDHSk0GMT9FsgVmnVSA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"gaxios": "^2.0.0",
|
"gaxios": "^2.1.0",
|
||||||
"google-p12-pem": "^2.0.0",
|
"google-p12-pem": "^2.0.0",
|
||||||
"jws": "^3.1.5",
|
"jws": "^4.0.0",
|
||||||
"mime": "^2.2.0"
|
"mime": "^2.2.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"jwa": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==",
|
||||||
|
"requires": {
|
||||||
|
"buffer-equal-constant-time": "1.0.1",
|
||||||
|
"ecdsa-sig-formatter": "1.0.11",
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"jws": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==",
|
||||||
|
"requires": {
|
||||||
|
"jwa": "^2.0.0",
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"mime": {
|
"mime": {
|
||||||
"version": "2.4.4",
|
"version": "2.4.6",
|
||||||
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
|
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz",
|
||||||
"integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA=="
|
"integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3088,7 +3174,7 @@
|
|||||||
"har-validator": {
|
"har-validator": {
|
||||||
"version": "5.1.3",
|
"version": "5.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
|
||||||
"integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
|
"integrity": "sha1-HvievT5JllV2de7ZiTEQ3DUPoIA=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"ajv": "^6.5.5",
|
"ajv": "^6.5.5",
|
||||||
"har-schema": "^2.0.0"
|
"har-schema": "^2.0.0"
|
||||||
@@ -3174,21 +3260,35 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"http-proxy-agent": {
|
"http-proxy-agent": {
|
||||||
"version": "2.1.0",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
|
||||||
"integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==",
|
"integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"agent-base": "4",
|
"@tootallnate/once": "1",
|
||||||
"debug": "3.1.0"
|
"agent-base": "6",
|
||||||
|
"debug": "4"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"debug": {
|
"agent-base": {
|
||||||
"version": "3.1.0",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.0.tgz",
|
||||||
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
"integrity": "sha512-j1Q7cSCqN+AwrmDd+pzgqc0/NpC655x2bUf5ZjRIO77DcNBFmh+OgRNzF6OKdCC9RSCb19fGd99+bhXFdkRNqw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"ms": "2.0.0"
|
"debug": "4"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"debug": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
|
||||||
|
"requires": {
|
||||||
|
"ms": "^2.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ms": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3203,18 +3303,26 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"https-proxy-agent": {
|
"https-proxy-agent": {
|
||||||
"version": "3.0.1",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
|
||||||
"integrity": "sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==",
|
"integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"agent-base": "^4.3.0",
|
"agent-base": "6",
|
||||||
"debug": "^3.1.0"
|
"debug": "4"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"agent-base": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-j1Q7cSCqN+AwrmDd+pzgqc0/NpC655x2bUf5ZjRIO77DcNBFmh+OgRNzF6OKdCC9RSCb19fGd99+bhXFdkRNqw==",
|
||||||
|
"requires": {
|
||||||
|
"debug": "4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "3.2.6",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
|
||||||
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
|
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"ms": "^2.1.1"
|
"ms": "^2.1.1"
|
||||||
}
|
}
|
||||||
@@ -3567,27 +3675,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
|
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
|
||||||
},
|
},
|
||||||
"jade": {
|
|
||||||
"version": "0.26.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz",
|
|
||||||
"integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=",
|
|
||||||
"requires": {
|
|
||||||
"commander": "0.6.1",
|
|
||||||
"mkdirp": "0.3.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"commander": {
|
|
||||||
"version": "0.6.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz",
|
|
||||||
"integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY="
|
|
||||||
},
|
|
||||||
"mkdirp": {
|
|
||||||
"version": "0.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz",
|
|
||||||
"integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"js-tokens": {
|
"js-tokens": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||||
@@ -3816,76 +3903,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"logger-sharelatex": {
|
"logger-sharelatex": {
|
||||||
"version": "1.9.1",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/logger-sharelatex/-/logger-sharelatex-1.9.1.tgz",
|
"resolved": "https://registry.npmjs.org/logger-sharelatex/-/logger-sharelatex-2.1.0.tgz",
|
||||||
"integrity": "sha512-9s6JQnH/PN+Js2CmI8+J3MQCTNlRzP2Dh4pcekXrV6Jm5J4HzyPi+6d3zfBskZ4NBmaUVw9hC4p5dmdaRmh4mQ==",
|
"integrity": "sha512-WgAABqnBMOv0VAwQJyw+fY4rpqKX+nPJNRydGEYZTo+6lKtJI2TttmZ+Coryg1LEzAjNagxoU78XOHKQvhg7qg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@google-cloud/logging-bunyan": "^2.0.0",
|
"@google-cloud/logging-bunyan": "^2.0.0",
|
||||||
"@overleaf/o-error": "^2.0.0",
|
"@overleaf/o-error": "^3.0.0",
|
||||||
"bunyan": "1.8.12",
|
"bunyan": "1.8.12",
|
||||||
"raven": "1.1.3",
|
"raven": "1.1.3",
|
||||||
"request": "2.88.0",
|
|
||||||
"yn": "^3.1.1"
|
"yn": "^3.1.1"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"bunyan": {
|
|
||||||
"version": "1.8.12",
|
|
||||||
"resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.12.tgz",
|
|
||||||
"integrity": "sha1-8VDw9nSKvdcq6uhPBEA74u8RN5c=",
|
|
||||||
"requires": {
|
|
||||||
"dtrace-provider": "~0.8",
|
|
||||||
"moment": "^2.10.6",
|
|
||||||
"mv": "~2",
|
|
||||||
"safe-json-stringify": "~1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"dtrace-provider": {
|
|
||||||
"version": "0.8.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.8.tgz",
|
|
||||||
"integrity": "sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg==",
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"nan": "^2.14.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nan": {
|
|
||||||
"version": "2.14.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
|
|
||||||
"integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==",
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"qs": {
|
|
||||||
"version": "6.5.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
|
|
||||||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
|
|
||||||
},
|
|
||||||
"request": {
|
|
||||||
"version": "2.88.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
|
|
||||||
"integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
|
|
||||||
"requires": {
|
|
||||||
"aws-sign2": "~0.7.0",
|
|
||||||
"aws4": "^1.8.0",
|
|
||||||
"caseless": "~0.12.0",
|
|
||||||
"combined-stream": "~1.0.6",
|
|
||||||
"extend": "~3.0.2",
|
|
||||||
"forever-agent": "~0.6.1",
|
|
||||||
"form-data": "~2.3.2",
|
|
||||||
"har-validator": "~5.1.0",
|
|
||||||
"http-signature": "~1.2.0",
|
|
||||||
"is-typedarray": "~1.0.0",
|
|
||||||
"isstream": "~0.1.2",
|
|
||||||
"json-stringify-safe": "~5.0.1",
|
|
||||||
"mime-types": "~2.1.19",
|
|
||||||
"oauth-sign": "~0.9.0",
|
|
||||||
"performance-now": "^2.1.0",
|
|
||||||
"qs": "~6.5.2",
|
|
||||||
"safe-buffer": "^5.1.2",
|
|
||||||
"tough-cookie": "~2.4.3",
|
|
||||||
"tunnel-agent": "^0.6.0",
|
|
||||||
"uuid": "^3.3.2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"loglevel": {
|
"loglevel": {
|
||||||
@@ -4502,7 +4528,7 @@
|
|||||||
"oauth-sign": {
|
"oauth-sign": {
|
||||||
"version": "0.9.0",
|
"version": "0.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
|
||||||
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
|
"integrity": "sha1-R6ewFrqmi1+g7PPe4IqFxnmsZFU="
|
||||||
},
|
},
|
||||||
"object-assign": {
|
"object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
@@ -5523,19 +5549,10 @@
|
|||||||
"stream-shift": "^1.0.0"
|
"stream-shift": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pump": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
|
|
||||||
"requires": {
|
|
||||||
"end-of-stream": "^1.1.0",
|
|
||||||
"once": "^1.3.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"readable-stream": {
|
"readable-stream": {
|
||||||
"version": "3.4.0",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||||
"integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==",
|
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"inherits": "^2.0.3",
|
"inherits": "^2.0.3",
|
||||||
"string_decoder": "^1.1.1",
|
"string_decoder": "^1.1.1",
|
||||||
@@ -6053,11 +6070,6 @@
|
|||||||
"object-inspect": "^1.7.0"
|
"object-inspect": "^1.7.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sigmund": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz",
|
|
||||||
"integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA="
|
|
||||||
},
|
|
||||||
"signal-exit": {
|
"signal-exit": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
|
||||||
@@ -6120,69 +6132,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"smoke-test-sharelatex": {
|
|
||||||
"version": "git+https://github.com/sharelatex/smoke-test-sharelatex.git#bc3e93d18ccee219c0d99e8b02c984ccdd842e1c",
|
|
||||||
"from": "git+https://github.com/sharelatex/smoke-test-sharelatex.git#v0.2.0",
|
|
||||||
"requires": {
|
|
||||||
"mocha": "~1.17.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"glob": {
|
|
||||||
"version": "3.2.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-3.2.3.tgz",
|
|
||||||
"integrity": "sha1-4xPusknHr/qlxHUoaw4RW1mDlGc=",
|
|
||||||
"requires": {
|
|
||||||
"graceful-fs": "~2.0.0",
|
|
||||||
"inherits": "2",
|
|
||||||
"minimatch": "~0.2.11"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"graceful-fs": {
|
|
||||||
"version": "2.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz",
|
|
||||||
"integrity": "sha1-fNLNsiiko/Nule+mzBQt59GhNtA="
|
|
||||||
},
|
|
||||||
"lru-cache": {
|
|
||||||
"version": "2.7.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz",
|
|
||||||
"integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI="
|
|
||||||
},
|
|
||||||
"minimatch": {
|
|
||||||
"version": "0.2.14",
|
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz",
|
|
||||||
"integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=",
|
|
||||||
"requires": {
|
|
||||||
"lru-cache": "2",
|
|
||||||
"sigmund": "~1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"mocha": {
|
|
||||||
"version": "1.17.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/mocha/-/mocha-1.17.1.tgz",
|
|
||||||
"integrity": "sha1-f3Zx1oUm0HS3uuZgyQmfh+DqHMs=",
|
|
||||||
"requires": {
|
|
||||||
"commander": "2.0.0",
|
|
||||||
"debug": "*",
|
|
||||||
"diff": "1.0.7",
|
|
||||||
"glob": "3.2.3",
|
|
||||||
"growl": "1.7.x",
|
|
||||||
"jade": "0.26.3",
|
|
||||||
"mkdirp": "0.3.5"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"mkdirp": {
|
|
||||||
"version": "0.3.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz",
|
|
||||||
"integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"snakecase-keys": {
|
"snakecase-keys": {
|
||||||
"version": "3.1.0",
|
"version": "3.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/snakecase-keys/-/snakecase-keys-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/snakecase-keys/-/snakecase-keys-3.2.0.tgz",
|
||||||
"integrity": "sha512-QM038drLbhdOY5HcRQVjO1ZJ1WR7yV5D5TIBzcOB/g3f5HURHhfpYEnvOyzXet8K+MQsgeIUA7O7vn90nAX6EA==",
|
"integrity": "sha512-WTJ0NhCH/37J+PU3fuz0x5b6TvtWQChTcKPOndWoUy0pteKOe0hrHMzSRsJOWSIP48EQkzUEsgQPmrG3W8pFNQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"map-obj": "^4.0.0",
|
"map-obj": "^4.0.0",
|
||||||
"to-snake-case": "^1.0.0"
|
"to-snake-case": "^1.0.0"
|
||||||
@@ -6565,15 +6518,22 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"teeny-request": {
|
"teeny-request": {
|
||||||
"version": "5.3.0",
|
"version": "6.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-5.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-6.0.3.tgz",
|
||||||
"integrity": "sha512-sN9E3JvEBe2CFqB/jpJpw1erWD1C7MxyYCxogHFCQSyZfkHYcdf4wzVQSw7FZxbwcfnS+FP0W9BS0mp6SEOKjg==",
|
"integrity": "sha512-TZG/dfd2r6yeji19es1cUIwAlVD8y+/svB1kAC2Y0bjEyysrfbO8EZvJBRwIE6WkwmUoB7uvWLwTIhJbMXZ1Dw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"http-proxy-agent": "^2.1.0",
|
"http-proxy-agent": "^4.0.0",
|
||||||
"https-proxy-agent": "^3.0.0",
|
"https-proxy-agent": "^5.0.0",
|
||||||
"node-fetch": "^2.2.0",
|
"node-fetch": "^2.2.0",
|
||||||
"stream-events": "^1.0.5",
|
"stream-events": "^1.0.5",
|
||||||
"uuid": "^3.3.2"
|
"uuid": "^7.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"uuid": {
|
||||||
|
"version": "7.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz",
|
||||||
|
"integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg=="
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"text-table": {
|
"text-table": {
|
||||||
@@ -6656,22 +6616,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz",
|
||||||
"integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg="
|
"integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg="
|
||||||
},
|
},
|
||||||
"tough-cookie": {
|
|
||||||
"version": "2.4.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
|
|
||||||
"integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
|
|
||||||
"requires": {
|
|
||||||
"psl": "^1.1.24",
|
|
||||||
"punycode": "^1.4.1"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"punycode": {
|
|
||||||
"version": "1.4.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
|
|
||||||
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"tslib": {
|
"tslib": {
|
||||||
"version": "1.10.0",
|
"version": "1.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
|
||||||
@@ -6709,7 +6653,8 @@
|
|||||||
"type-fest": {
|
"type-fest": {
|
||||||
"version": "0.8.1",
|
"version": "0.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
|
||||||
"integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA=="
|
"integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"type-is": {
|
"type-is": {
|
||||||
"version": "1.6.18",
|
"version": "1.6.18",
|
||||||
@@ -6731,11 +6676,6 @@
|
|||||||
"integrity": "sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw==",
|
"integrity": "sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"underscore": {
|
|
||||||
"version": "1.9.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.2.tgz",
|
|
||||||
"integrity": "sha512-D39qtimx0c1fI3ya1Lnhk3E9nONswSKhnffBI0gME9C99fYOkNi04xs8K6pePLhvl1frbDemkaBQ5ikWllR2HQ=="
|
|
||||||
},
|
|
||||||
"universalify": {
|
"universalify": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
|
||||||
|
|||||||
@@ -21,21 +21,21 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"async": "3.2.0",
|
"async": "3.2.0",
|
||||||
"body-parser": "^1.19.0",
|
"body-parser": "^1.19.0",
|
||||||
|
"diskusage": "^1.1.3",
|
||||||
"dockerode": "^3.1.0",
|
"dockerode": "^3.1.0",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"fs-extra": "^8.1.0",
|
"fs-extra": "^8.1.0",
|
||||||
"heapdump": "^0.3.15",
|
"heapdump": "^0.3.15",
|
||||||
"lockfile": "^1.0.4",
|
"lockfile": "^1.0.4",
|
||||||
"logger-sharelatex": "^1.9.1",
|
"lodash": "^4.17.15",
|
||||||
|
"logger-sharelatex": "^2.1.0",
|
||||||
"lynx": "0.2.0",
|
"lynx": "0.2.0",
|
||||||
"metrics-sharelatex": "^2.6.0",
|
"metrics-sharelatex": "^2.6.0",
|
||||||
"mysql": "^2.18.1",
|
"mysql": "^2.18.1",
|
||||||
"request": "^2.88.2",
|
"request": "^2.88.2",
|
||||||
"sequelize": "^5.21.5",
|
"sequelize": "^5.21.5",
|
||||||
"settings-sharelatex": "git+https://github.com/sharelatex/settings-sharelatex.git#v1.1.0",
|
"settings-sharelatex": "git+https://github.com/sharelatex/settings-sharelatex.git#v1.1.0",
|
||||||
"smoke-test-sharelatex": "git+https://github.com/sharelatex/smoke-test-sharelatex.git#v0.2.0",
|
|
||||||
"sqlite3": "^4.1.1",
|
"sqlite3": "^4.1.1",
|
||||||
"underscore": "^1.9.2",
|
|
||||||
"v8-profiler-node8": "^6.1.1",
|
"v8-profiler-node8": "^6.1.1",
|
||||||
"wrench": "~1.5.9"
|
"wrench": "~1.5.9"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ Hello world
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
return describe('from pdf to code', function() {
|
describe('from pdf to code', function() {
|
||||||
return it('should return the correct location', function(done) {
|
return it('should return the correct location', function(done) {
|
||||||
return Client.syncFromPdf(
|
return Client.syncFromPdf(
|
||||||
this.project_id,
|
this.project_id,
|
||||||
@@ -88,4 +88,104 @@ Hello world
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('when the project directory is not available', function() {
|
||||||
|
before(function() {
|
||||||
|
this.other_project_id = Client.randomId()
|
||||||
|
})
|
||||||
|
describe('from code to pdf', function() {
|
||||||
|
it('should return a 404 response', function(done) {
|
||||||
|
return Client.syncFromCode(
|
||||||
|
this.other_project_id,
|
||||||
|
'main.tex',
|
||||||
|
3,
|
||||||
|
5,
|
||||||
|
(error, body) => {
|
||||||
|
if (error != null) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
expect(body).to.equal('Not Found')
|
||||||
|
return done()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
describe('from pdf to code', function() {
|
||||||
|
it('should return a 404 response', function(done) {
|
||||||
|
return Client.syncFromPdf(
|
||||||
|
this.other_project_id,
|
||||||
|
1,
|
||||||
|
100,
|
||||||
|
200,
|
||||||
|
(error, body) => {
|
||||||
|
if (error != null) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
expect(body).to.equal('Not Found')
|
||||||
|
return done()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('when the synctex file is not available', function() {
|
||||||
|
before(function(done) {
|
||||||
|
this.broken_project_id = Client.randomId()
|
||||||
|
const content = 'this is not valid tex' // not a valid tex file
|
||||||
|
this.request = {
|
||||||
|
resources: [
|
||||||
|
{
|
||||||
|
path: 'main.tex',
|
||||||
|
content
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
Client.compile(
|
||||||
|
this.broken_project_id,
|
||||||
|
this.request,
|
||||||
|
(error, res, body) => {
|
||||||
|
this.error = error
|
||||||
|
this.res = res
|
||||||
|
this.body = body
|
||||||
|
return done()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('from code to pdf', function() {
|
||||||
|
it('should return a 404 response', function(done) {
|
||||||
|
return Client.syncFromCode(
|
||||||
|
this.broken_project_id,
|
||||||
|
'main.tex',
|
||||||
|
3,
|
||||||
|
5,
|
||||||
|
(error, body) => {
|
||||||
|
if (error != null) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
expect(body).to.equal('Not Found')
|
||||||
|
return done()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
describe('from pdf to code', function() {
|
||||||
|
it('should return a 404 response', function(done) {
|
||||||
|
return Client.syncFromPdf(
|
||||||
|
this.broken_project_id,
|
||||||
|
1,
|
||||||
|
100,
|
||||||
|
200,
|
||||||
|
(error, body) => {
|
||||||
|
if (error != null) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
expect(body).to.equal('Not Found')
|
||||||
|
return done()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||||
*/
|
*/
|
||||||
const Client = require('./helpers/Client')
|
const Client = require('./helpers/Client')
|
||||||
const request = require('request')
|
|
||||||
require('chai').should()
|
require('chai').should()
|
||||||
const sinon = require('sinon')
|
const sinon = require('sinon')
|
||||||
const ClsiApp = require('./helpers/ClsiApp')
|
const ClsiApp = require('./helpers/ClsiApp')
|
||||||
|
|||||||
@@ -81,13 +81,14 @@ module.exports = Client = {
|
|||||||
file,
|
file,
|
||||||
line,
|
line,
|
||||||
column
|
column
|
||||||
}
|
},
|
||||||
|
json: true
|
||||||
},
|
},
|
||||||
(error, response, body) => {
|
(error, response, body) => {
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
return callback(error)
|
return callback(error)
|
||||||
}
|
}
|
||||||
return callback(null, JSON.parse(body))
|
return callback(null, body)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@@ -103,13 +104,14 @@ module.exports = Client = {
|
|||||||
page,
|
page,
|
||||||
h,
|
h,
|
||||||
v
|
v
|
||||||
}
|
},
|
||||||
|
json: true
|
||||||
},
|
},
|
||||||
(error, response, body) => {
|
(error, response, body) => {
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
return callback(error)
|
return callback(error)
|
||||||
}
|
}
|
||||||
return callback(null, JSON.parse(body))
|
return callback(null, body)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const request = require('request')
|
|||||||
const Settings = require('settings-sharelatex')
|
const Settings = require('settings-sharelatex')
|
||||||
const async = require('async')
|
const async = require('async')
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const _ = require('underscore')
|
const _ = require('lodash')
|
||||||
const concurentCompiles = 5
|
const concurentCompiles = 5
|
||||||
const totalCompiles = 50
|
const totalCompiles = 50
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,3 @@
|
|||||||
/* eslint-disable
|
|
||||||
no-unused-vars,
|
|
||||||
*/
|
|
||||||
// TODO: This file was created by bulk-decaffeinate.
|
|
||||||
// Fix any style issues and re-enable lint.
|
|
||||||
/*
|
|
||||||
* decaffeinate suggestions:
|
|
||||||
* DS101: Remove unnecessary use of Array.from
|
|
||||||
* DS102: Remove unnecessary code created because of implicit returns
|
|
||||||
* DS207: Consider shorter variations of null checks
|
|
||||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
|
||||||
*/
|
|
||||||
const chai = require('chai')
|
|
||||||
if (Object.prototype.should == null) {
|
|
||||||
chai.should()
|
|
||||||
}
|
|
||||||
const { expect } = chai
|
|
||||||
const request = require('request')
|
const request = require('request')
|
||||||
const Settings = require('settings-sharelatex')
|
const Settings = require('settings-sharelatex')
|
||||||
|
|
||||||
@@ -23,9 +6,35 @@ const buildUrl = path =>
|
|||||||
|
|
||||||
const url = buildUrl(`project/smoketest-${process.pid}/compile`)
|
const url = buildUrl(`project/smoketest-${process.pid}/compile`)
|
||||||
|
|
||||||
describe('Running a compile', function() {
|
module.exports = {
|
||||||
before(function(done) {
|
sendNewResult(res) {
|
||||||
return request.post(
|
this._run(error => this._sendResponse(res, error))
|
||||||
|
},
|
||||||
|
sendLastResult(res) {
|
||||||
|
this._sendResponse(res, this._lastError)
|
||||||
|
},
|
||||||
|
triggerRun(cb) {
|
||||||
|
this._run(error => {
|
||||||
|
this._lastError = error
|
||||||
|
cb(error)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
_lastError: new Error('SmokeTestsPending'),
|
||||||
|
_sendResponse(res, error) {
|
||||||
|
let code, body
|
||||||
|
if (error) {
|
||||||
|
code = 500
|
||||||
|
body = error.message
|
||||||
|
} else {
|
||||||
|
code = 200
|
||||||
|
body = 'OK'
|
||||||
|
}
|
||||||
|
res.contentType('text/plain')
|
||||||
|
res.status(code).send(body)
|
||||||
|
},
|
||||||
|
_run(done) {
|
||||||
|
request.post(
|
||||||
{
|
{
|
||||||
url,
|
url,
|
||||||
json: {
|
json: {
|
||||||
@@ -72,29 +81,22 @@ describe('Running a compile', function() {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
(error, response, body) => {
|
(error, response, body) => {
|
||||||
this.error = error
|
if (error) return done(error)
|
||||||
this.response = response
|
if (!body || !body.compile || !body.compile.outputFiles) {
|
||||||
this.body = body
|
return done(new Error('response payload incomplete'))
|
||||||
return done()
|
}
|
||||||
|
|
||||||
|
let pdfFound = false
|
||||||
|
let logFound = false
|
||||||
|
for (const file of body.compile.outputFiles) {
|
||||||
|
if (file.type === 'pdf') pdfFound = true
|
||||||
|
if (file.type === 'log') logFound = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pdfFound) return done(new Error('no pdf returned'))
|
||||||
|
if (!logFound) return done(new Error('no log returned'))
|
||||||
|
done()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
}
|
||||||
|
}
|
||||||
it('should return the pdf', function() {
|
|
||||||
for (const file of Array.from(this.body.compile.outputFiles)) {
|
|
||||||
if (file.type === 'pdf') {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new Error('no pdf returned')
|
|
||||||
})
|
|
||||||
|
|
||||||
return it('should return the log', function() {
|
|
||||||
for (const file of Array.from(this.body.compile.outputFiles)) {
|
|
||||||
if (file.type === 'log') {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new Error('no log returned')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|||||||
@@ -160,7 +160,8 @@ describe('CompileManager', function() {
|
|||||||
compiler: (this.compiler = 'pdflatex'),
|
compiler: (this.compiler = 'pdflatex'),
|
||||||
timeout: (this.timeout = 42000),
|
timeout: (this.timeout = 42000),
|
||||||
imageName: (this.image = 'example.com/image'),
|
imageName: (this.image = 'example.com/image'),
|
||||||
flags: (this.flags = ['-file-line-error'])
|
flags: (this.flags = ['-file-line-error']),
|
||||||
|
compileGroup: (this.compileGroup = 'compile-group')
|
||||||
}
|
}
|
||||||
this.env = {}
|
this.env = {}
|
||||||
this.Settings.compileDir = 'compiles'
|
this.Settings.compileDir = 'compiles'
|
||||||
@@ -199,7 +200,8 @@ describe('CompileManager', function() {
|
|||||||
timeout: this.timeout,
|
timeout: this.timeout,
|
||||||
image: this.image,
|
image: this.image,
|
||||||
flags: this.flags,
|
flags: this.flags,
|
||||||
environment: this.env
|
environment: this.env,
|
||||||
|
compileGroup: this.compileGroup
|
||||||
})
|
})
|
||||||
.should.equal(true)
|
.should.equal(true)
|
||||||
})
|
})
|
||||||
@@ -253,7 +255,8 @@ describe('CompileManager', function() {
|
|||||||
CHKTEX_OPTIONS: '-nall -e9 -e10 -w15 -w16',
|
CHKTEX_OPTIONS: '-nall -e9 -e10 -w15 -w16',
|
||||||
CHKTEX_EXIT_ON_ERROR: 1,
|
CHKTEX_EXIT_ON_ERROR: 1,
|
||||||
CHKTEX_ULIMIT_OPTIONS: '-t 5 -v 64000'
|
CHKTEX_ULIMIT_OPTIONS: '-t 5 -v 64000'
|
||||||
}
|
},
|
||||||
|
compileGroup: this.compileGroup
|
||||||
})
|
})
|
||||||
.should.equal(true)
|
.should.equal(true)
|
||||||
})
|
})
|
||||||
@@ -275,7 +278,8 @@ describe('CompileManager', function() {
|
|||||||
timeout: this.timeout,
|
timeout: this.timeout,
|
||||||
image: this.image,
|
image: this.image,
|
||||||
flags: this.flags,
|
flags: this.flags,
|
||||||
environment: this.env
|
environment: this.env,
|
||||||
|
compileGroup: this.compileGroup
|
||||||
})
|
})
|
||||||
.should.equal(true)
|
.should.equal(true)
|
||||||
})
|
})
|
||||||
@@ -294,6 +298,7 @@ describe('CompileManager', function() {
|
|||||||
this.proc = new EventEmitter()
|
this.proc = new EventEmitter()
|
||||||
this.proc.stdout = new EventEmitter()
|
this.proc.stdout = new EventEmitter()
|
||||||
this.proc.stderr = new EventEmitter()
|
this.proc.stderr = new EventEmitter()
|
||||||
|
this.proc.stderr.setEncoding = sinon.stub().returns(this.proc.stderr)
|
||||||
this.child_process.spawn = sinon.stub().returns(this.proc)
|
this.child_process.spawn = sinon.stub().returns(this.proc)
|
||||||
this.CompileManager.clearProject(
|
this.CompileManager.clearProject(
|
||||||
this.project_id,
|
this.project_id,
|
||||||
@@ -328,6 +333,7 @@ describe('CompileManager', function() {
|
|||||||
this.proc = new EventEmitter()
|
this.proc = new EventEmitter()
|
||||||
this.proc.stdout = new EventEmitter()
|
this.proc.stdout = new EventEmitter()
|
||||||
this.proc.stderr = new EventEmitter()
|
this.proc.stderr = new EventEmitter()
|
||||||
|
this.proc.stderr.setEncoding = sinon.stub().returns(this.proc.stderr)
|
||||||
this.child_process.spawn = sinon.stub().returns(this.proc)
|
this.child_process.spawn = sinon.stub().returns(this.proc)
|
||||||
this.CompileManager.clearProject(
|
this.CompileManager.clearProject(
|
||||||
this.project_id,
|
this.project_id,
|
||||||
@@ -382,7 +388,7 @@ describe('CompileManager', function() {
|
|||||||
this.stdout = `NODE\t${this.page}\t${this.h}\t${this.v}\t${this.width}\t${this.height}\n`
|
this.stdout = `NODE\t${this.page}\t${this.h}\t${this.v}\t${this.width}\t${this.height}\n`
|
||||||
this.CommandRunner.run = sinon
|
this.CommandRunner.run = sinon
|
||||||
.stub()
|
.stub()
|
||||||
.callsArgWith(6, null, { stdout: this.stdout })
|
.callsArgWith(7, null, { stdout: this.stdout })
|
||||||
return this.CompileManager.syncFromCode(
|
return this.CompileManager.syncFromCode(
|
||||||
this.project_id,
|
this.project_id,
|
||||||
this.user_id,
|
this.user_id,
|
||||||
@@ -441,7 +447,7 @@ describe('CompileManager', function() {
|
|||||||
this.stdout = `NODE\t${this.Settings.path.compilesDir}/${this.project_id}-${this.user_id}/${this.file_name}\t${this.line}\t${this.column}\n`
|
this.stdout = `NODE\t${this.Settings.path.compilesDir}/${this.project_id}-${this.user_id}/${this.file_name}\t${this.line}\t${this.column}\n`
|
||||||
this.CommandRunner.run = sinon
|
this.CommandRunner.run = sinon
|
||||||
.stub()
|
.stub()
|
||||||
.callsArgWith(6, null, { stdout: this.stdout })
|
.callsArgWith(7, null, { stdout: this.stdout })
|
||||||
return this.CompileManager.syncFromPdf(
|
return this.CompileManager.syncFromPdf(
|
||||||
this.project_id,
|
this.project_id,
|
||||||
this.user_id,
|
this.user_id,
|
||||||
@@ -483,7 +489,7 @@ describe('CompileManager', function() {
|
|||||||
|
|
||||||
return describe('wordcount', function() {
|
return describe('wordcount', function() {
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
this.CommandRunner.run = sinon.stub().callsArg(6)
|
this.CommandRunner.run = sinon.stub().callsArg(7)
|
||||||
this.fs.readFile = sinon
|
this.fs.readFile = sinon
|
||||||
.stub()
|
.stub()
|
||||||
.callsArgWith(
|
.callsArgWith(
|
||||||
|
|||||||
@@ -69,7 +69,8 @@ describe('DockerRunner', function() {
|
|||||||
return runner(callback)
|
return runner(callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
globals: { Math } // used by lodash
|
||||||
})
|
})
|
||||||
this.Docker = Docker
|
this.Docker = Docker
|
||||||
this.getContainer = Docker.prototype.getContainer
|
this.getContainer = Docker.prototype.getContainer
|
||||||
@@ -85,6 +86,7 @@ describe('DockerRunner', function() {
|
|||||||
this.project_id = 'project-id-123'
|
this.project_id = 'project-id-123'
|
||||||
this.volumes = { '/local/compile/directory': '/compile' }
|
this.volumes = { '/local/compile/directory': '/compile' }
|
||||||
this.Settings.clsi.docker.image = this.defaultImage = 'default-image'
|
this.Settings.clsi.docker.image = this.defaultImage = 'default-image'
|
||||||
|
this.compileGroup = 'compile-group'
|
||||||
return (this.Settings.clsi.docker.env = { PATH: 'mock-path' })
|
return (this.Settings.clsi.docker.env = { PATH: 'mock-path' })
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -121,6 +123,7 @@ describe('DockerRunner', function() {
|
|||||||
this.image,
|
this.image,
|
||||||
this.timeout,
|
this.timeout,
|
||||||
this.env,
|
this.env,
|
||||||
|
this.compileGroup,
|
||||||
(err, output) => {
|
(err, output) => {
|
||||||
this.callback(err, output)
|
this.callback(err, output)
|
||||||
return done()
|
return done()
|
||||||
@@ -170,6 +173,7 @@ describe('DockerRunner', function() {
|
|||||||
this.image,
|
this.image,
|
||||||
this.timeout,
|
this.timeout,
|
||||||
this.env,
|
this.env,
|
||||||
|
this.compileGroup,
|
||||||
this.callback
|
this.callback
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@@ -218,6 +222,7 @@ describe('DockerRunner', function() {
|
|||||||
this.image,
|
this.image,
|
||||||
this.timeout,
|
this.timeout,
|
||||||
this.env,
|
this.env,
|
||||||
|
this.compileGroup,
|
||||||
this.callback
|
this.callback
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@@ -251,6 +256,7 @@ describe('DockerRunner', function() {
|
|||||||
null,
|
null,
|
||||||
this.timeout,
|
this.timeout,
|
||||||
this.env,
|
this.env,
|
||||||
|
this.compileGroup,
|
||||||
this.callback
|
this.callback
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@@ -280,6 +286,7 @@ describe('DockerRunner', function() {
|
|||||||
this.image,
|
this.image,
|
||||||
this.timeout,
|
this.timeout,
|
||||||
this.env,
|
this.env,
|
||||||
|
this.compileGroup,
|
||||||
this.callback
|
this.callback
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@@ -291,6 +298,64 @@ describe('DockerRunner', function() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('run with _getOptions', function() {
|
||||||
|
beforeEach(function(done) {
|
||||||
|
// this.DockerRunner._getContainerOptions = sinon
|
||||||
|
// .stub()
|
||||||
|
// .returns((this.options = { mockoptions: 'foo' }))
|
||||||
|
this.DockerRunner._fingerprintContainer = sinon
|
||||||
|
.stub()
|
||||||
|
.returns((this.fingerprint = 'fingerprint'))
|
||||||
|
|
||||||
|
this.name = `project-${this.project_id}-${this.fingerprint}`
|
||||||
|
|
||||||
|
this.command = ['mock', 'command', '--outdir=$COMPILE_DIR']
|
||||||
|
this.command_with_dir = ['mock', 'command', '--outdir=/compile']
|
||||||
|
this.timeout = 42000
|
||||||
|
return done()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('when a compile group config is set', function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
this.Settings.clsi.docker.compileGroupConfig = {
|
||||||
|
'compile-group': {
|
||||||
|
'HostConfig.newProperty': 'new-property'
|
||||||
|
},
|
||||||
|
'other-group': { otherProperty: 'other-property' }
|
||||||
|
}
|
||||||
|
this.DockerRunner._runAndWaitForContainer = sinon
|
||||||
|
.stub()
|
||||||
|
.callsArgWith(3, null, (this.output = 'mock-output'))
|
||||||
|
return this.DockerRunner.run(
|
||||||
|
this.project_id,
|
||||||
|
this.command,
|
||||||
|
this.directory,
|
||||||
|
this.image,
|
||||||
|
this.timeout,
|
||||||
|
this.env,
|
||||||
|
this.compileGroup,
|
||||||
|
this.callback
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should set the docker options for the compile group', function() {
|
||||||
|
const options = this.DockerRunner._runAndWaitForContainer.lastCall
|
||||||
|
.args[0]
|
||||||
|
return expect(options.HostConfig).to.deep.include({
|
||||||
|
Binds: ['/local/compile/directory:/compile:rw'],
|
||||||
|
LogConfig: { Type: 'none', Config: {} },
|
||||||
|
CapDrop: 'ALL',
|
||||||
|
SecurityOpt: ['no-new-privileges'],
|
||||||
|
newProperty: 'new-property'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return it('should call the callback', function() {
|
||||||
|
return this.callback.calledWith(null, this.output).should.equal(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('_runAndWaitForContainer', function() {
|
describe('_runAndWaitForContainer', function() {
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
this.options = { mockoptions: 'foo', name: (this.name = 'mock-name') }
|
this.options = { mockoptions: 'foo', name: (this.name = 'mock-name') }
|
||||||
@@ -357,8 +422,8 @@ describe('DockerRunner', function() {
|
|||||||
return this.DockerRunner.startContainer(
|
return this.DockerRunner.startContainer(
|
||||||
this.options,
|
this.options,
|
||||||
this.volumes,
|
this.volumes,
|
||||||
this.callback,
|
() => {},
|
||||||
() => {}
|
this.callback
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -630,19 +695,19 @@ describe('DockerRunner', function() {
|
|||||||
it('should destroy old containers', function() {
|
it('should destroy old containers', function() {
|
||||||
this.DockerRunner.destroyContainer.callCount.should.equal(1)
|
this.DockerRunner.destroyContainer.callCount.should.equal(1)
|
||||||
return this.DockerRunner.destroyContainer
|
return this.DockerRunner.destroyContainer
|
||||||
.calledWith('/project-old-container-name', 'old-container-id')
|
.calledWith('project-old-container-name', 'old-container-id')
|
||||||
.should.equal(true)
|
.should.equal(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not destroy new containers', function() {
|
it('should not destroy new containers', function() {
|
||||||
return this.DockerRunner.destroyContainer
|
return this.DockerRunner.destroyContainer
|
||||||
.calledWith('/project-new-container-name', 'new-container-id')
|
.calledWith('project-new-container-name', 'new-container-id')
|
||||||
.should.equal(false)
|
.should.equal(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not destroy non-project containers', function() {
|
it('should not destroy non-project containers', function() {
|
||||||
return this.DockerRunner.destroyContainer
|
return this.DockerRunner.destroyContainer
|
||||||
.calledWith('/totally-not-a-project-container', 'some-random-id')
|
.calledWith('totally-not-a-project-container', 'some-random-id')
|
||||||
.should.equal(false)
|
.should.equal(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,10 @@ describe('LatexRunner', function() {
|
|||||||
done() {}
|
done() {}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
'./CommandRunner': (this.CommandRunner = {})
|
'./CommandRunner': (this.CommandRunner = {}),
|
||||||
|
fs: (this.fs = {
|
||||||
|
writeFile: sinon.stub().callsArg(2)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -45,6 +48,7 @@ describe('LatexRunner', function() {
|
|||||||
this.mainFile = 'main-file.tex'
|
this.mainFile = 'main-file.tex'
|
||||||
this.compiler = 'pdflatex'
|
this.compiler = 'pdflatex'
|
||||||
this.image = 'example.com/image'
|
this.image = 'example.com/image'
|
||||||
|
this.compileGroup = 'compile-group'
|
||||||
this.callback = sinon.stub()
|
this.callback = sinon.stub()
|
||||||
this.project_id = 'project-id-123'
|
this.project_id = 'project-id-123'
|
||||||
return (this.env = { foo: '123' })
|
return (this.env = { foo: '123' })
|
||||||
@@ -52,7 +56,10 @@ describe('LatexRunner', function() {
|
|||||||
|
|
||||||
return describe('runLatex', function() {
|
return describe('runLatex', function() {
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
return (this.CommandRunner.run = sinon.stub().callsArg(6))
|
return (this.CommandRunner.run = sinon.stub().callsArgWith(7, null, {
|
||||||
|
stdout: 'this is stdout',
|
||||||
|
stderr: 'this is stderr'
|
||||||
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('normally', function() {
|
describe('normally', function() {
|
||||||
@@ -65,13 +72,14 @@ describe('LatexRunner', function() {
|
|||||||
compiler: this.compiler,
|
compiler: this.compiler,
|
||||||
timeout: (this.timeout = 42000),
|
timeout: (this.timeout = 42000),
|
||||||
image: this.image,
|
image: this.image,
|
||||||
environment: this.env
|
environment: this.env,
|
||||||
|
compileGroup: this.compileGroup
|
||||||
},
|
},
|
||||||
this.callback
|
this.callback
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
return it('should run the latex command', function() {
|
it('should run the latex command', function() {
|
||||||
return this.CommandRunner.run
|
return this.CommandRunner.run
|
||||||
.calledWith(
|
.calledWith(
|
||||||
this.project_id,
|
this.project_id,
|
||||||
@@ -79,10 +87,20 @@ describe('LatexRunner', function() {
|
|||||||
this.directory,
|
this.directory,
|
||||||
this.image,
|
this.image,
|
||||||
this.timeout,
|
this.timeout,
|
||||||
this.env
|
this.env,
|
||||||
|
this.compileGroup
|
||||||
)
|
)
|
||||||
.should.equal(true)
|
.should.equal(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should record the stdout and stderr', function() {
|
||||||
|
this.fs.writeFile
|
||||||
|
.calledWith(this.directory + '/' + 'output.stdout', 'this is stdout')
|
||||||
|
.should.equal(true)
|
||||||
|
this.fs.writeFile
|
||||||
|
.calledWith(this.directory + '/' + 'output.stderr', 'this is stderr')
|
||||||
|
.should.equal(true)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('with an .Rtex main file', function() {
|
describe('with an .Rtex main file', function() {
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ describe('OutputFileFinder', function() {
|
|||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
this.proc = new EventEmitter()
|
this.proc = new EventEmitter()
|
||||||
this.proc.stdout = new EventEmitter()
|
this.proc.stdout = new EventEmitter()
|
||||||
|
this.proc.stdout.setEncoding = sinon.stub().returns(this.proc.stdout)
|
||||||
this.spawn.returns(this.proc)
|
this.spawn.returns(this.proc)
|
||||||
this.directory = '/base/dir'
|
this.directory = '/base/dir'
|
||||||
return this.OutputFileFinder._getAllFiles(this.directory, this.callback)
|
return this.OutputFileFinder._getAllFiles(this.directory, this.callback)
|
||||||
|
|||||||
@@ -30,7 +30,8 @@ describe('OutputFileOptimiser', function() {
|
|||||||
child_process: { spawn: (this.spawn = sinon.stub()) },
|
child_process: { spawn: (this.spawn = sinon.stub()) },
|
||||||
'logger-sharelatex': { log: sinon.stub(), warn: sinon.stub() },
|
'logger-sharelatex': { log: sinon.stub(), warn: sinon.stub() },
|
||||||
'./Metrics': {}
|
'./Metrics': {}
|
||||||
}
|
},
|
||||||
|
globals: { Math } // used by lodash
|
||||||
})
|
})
|
||||||
this.directory = '/test/dir'
|
this.directory = '/test/dir'
|
||||||
return (this.callback = sinon.stub())
|
return (this.callback = sinon.stub())
|
||||||
@@ -124,7 +125,7 @@ describe('OutputFileOptimiser', function() {
|
|||||||
this.fs.read = sinon
|
this.fs.read = sinon
|
||||||
.stub()
|
.stub()
|
||||||
.withArgs(this.fd)
|
.withArgs(this.fd)
|
||||||
.yields(null, 100, new Buffer('hello /Linearized 1'))
|
.yields(null, 100, Buffer.from('hello /Linearized 1'))
|
||||||
this.fs.close = sinon
|
this.fs.close = sinon
|
||||||
.stub()
|
.stub()
|
||||||
.withArgs(this.fd)
|
.withArgs(this.fd)
|
||||||
@@ -140,7 +141,7 @@ describe('OutputFileOptimiser', function() {
|
|||||||
this.fs.read = sinon
|
this.fs.read = sinon
|
||||||
.stub()
|
.stub()
|
||||||
.withArgs(this.fd)
|
.withArgs(this.fd)
|
||||||
.yields(null, 100, new Buffer('hello /Linearized 1'))
|
.yields(null, 100, Buffer.from('hello /Linearized 1'))
|
||||||
return this.OutputFileOptimiser.checkIfPDFIsOptimised(
|
return this.OutputFileOptimiser.checkIfPDFIsOptimised(
|
||||||
this.src,
|
this.src,
|
||||||
this.callback
|
this.callback
|
||||||
@@ -169,7 +170,7 @@ describe('OutputFileOptimiser', function() {
|
|||||||
this.fs.read = sinon
|
this.fs.read = sinon
|
||||||
.stub()
|
.stub()
|
||||||
.withArgs(this.fd)
|
.withArgs(this.fd)
|
||||||
.yields(null, 100, new Buffer('hello not linearized 1'))
|
.yields(null, 100, Buffer.from('hello not linearized 1'))
|
||||||
return this.OutputFileOptimiser.checkIfPDFIsOptimised(
|
return this.OutputFileOptimiser.checkIfPDFIsOptimised(
|
||||||
this.src,
|
this.src,
|
||||||
this.callback
|
this.callback
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
const SandboxedModule = require('sandboxed-module')
|
const SandboxedModule = require('sandboxed-module')
|
||||||
const sinon = require('sinon')
|
const sinon = require('sinon')
|
||||||
require('chai').should()
|
require('chai').should()
|
||||||
|
const assert = require('chai').assert
|
||||||
const modulePath = require('path').join(
|
const modulePath = require('path').join(
|
||||||
__dirname,
|
__dirname,
|
||||||
'../../../app/js/ProjectPersistenceManager'
|
'../../../app/js/ProjectPersistenceManager'
|
||||||
@@ -26,7 +27,15 @@ describe('ProjectPersistenceManager', function() {
|
|||||||
requires: {
|
requires: {
|
||||||
'./UrlCache': (this.UrlCache = {}),
|
'./UrlCache': (this.UrlCache = {}),
|
||||||
'./CompileManager': (this.CompileManager = {}),
|
'./CompileManager': (this.CompileManager = {}),
|
||||||
'logger-sharelatex': (this.logger = { log: sinon.stub() }),
|
diskusage: (this.diskusage = { check: sinon.stub() }),
|
||||||
|
'logger-sharelatex': (this.logger = {
|
||||||
|
log: sinon.stub(),
|
||||||
|
warn: sinon.stub(),
|
||||||
|
err: sinon.stub()
|
||||||
|
}),
|
||||||
|
'settings-sharelatex': (this.settings = {
|
||||||
|
project_cache_length_ms: 1000
|
||||||
|
}),
|
||||||
'./db': (this.db = {})
|
'./db': (this.db = {})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -35,6 +44,57 @@ describe('ProjectPersistenceManager', function() {
|
|||||||
return (this.user_id = '1234')
|
return (this.user_id = '1234')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('refreshExpiryTimeout', function() {
|
||||||
|
it('should leave expiry alone if plenty of disk', function(done) {
|
||||||
|
this.diskusage.check.callsArgWith(1, null, {
|
||||||
|
available: 40,
|
||||||
|
total: 100
|
||||||
|
})
|
||||||
|
|
||||||
|
this.ProjectPersistenceManager.refreshExpiryTimeout(() => {
|
||||||
|
this.ProjectPersistenceManager.EXPIRY_TIMEOUT.should.equal(
|
||||||
|
this.settings.project_cache_length_ms
|
||||||
|
)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should drop EXPIRY_TIMEOUT 10% if low disk usage', function(done) {
|
||||||
|
this.diskusage.check.callsArgWith(1, null, {
|
||||||
|
available: 5,
|
||||||
|
total: 100
|
||||||
|
})
|
||||||
|
|
||||||
|
this.ProjectPersistenceManager.refreshExpiryTimeout(() => {
|
||||||
|
this.ProjectPersistenceManager.EXPIRY_TIMEOUT.should.equal(900)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not drop EXPIRY_TIMEOUT to below 50% of project_cache_length_ms', function(done) {
|
||||||
|
this.diskusage.check.callsArgWith(1, null, {
|
||||||
|
available: 5,
|
||||||
|
total: 100
|
||||||
|
})
|
||||||
|
this.ProjectPersistenceManager.EXPIRY_TIMEOUT = 500
|
||||||
|
this.ProjectPersistenceManager.refreshExpiryTimeout(() => {
|
||||||
|
this.ProjectPersistenceManager.EXPIRY_TIMEOUT.should.equal(500)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not modify EXPIRY_TIMEOUT if there is an error getting disk values', function(done) {
|
||||||
|
this.diskusage.check.callsArgWith(1, 'Error', {
|
||||||
|
available: 5,
|
||||||
|
total: 100
|
||||||
|
})
|
||||||
|
this.ProjectPersistenceManager.refreshExpiryTimeout(() => {
|
||||||
|
this.ProjectPersistenceManager.EXPIRY_TIMEOUT.should.equal(1000)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('clearExpiredProjects', function() {
|
describe('clearExpiredProjects', function() {
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
this.project_ids = ['project-id-1', 'project-id-2']
|
this.project_ids = ['project-id-1', 'project-id-2']
|
||||||
|
|||||||
@@ -230,6 +230,12 @@ describe('ResourceWriter', function() {
|
|||||||
{
|
{
|
||||||
path: '_markdown_main/30893013dec5d869a415610079774c2f.md.tex',
|
path: '_markdown_main/30893013dec5d869a415610079774c2f.md.tex',
|
||||||
type: 'tex'
|
type: 'tex'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'output.stdout'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'output.stderr'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
this.resources = 'mock-resources'
|
this.resources = 'mock-resources'
|
||||||
@@ -256,6 +262,18 @@ describe('ResourceWriter', function() {
|
|||||||
.should.equal(true)
|
.should.equal(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should delete the stdout log file', function() {
|
||||||
|
return this.ResourceWriter._deleteFileIfNotDirectory
|
||||||
|
.calledWith(path.join(this.basePath, 'output.stdout'))
|
||||||
|
.should.equal(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should delete the stderr log file', function() {
|
||||||
|
return this.ResourceWriter._deleteFileIfNotDirectory
|
||||||
|
.calledWith(path.join(this.basePath, 'output.stderr'))
|
||||||
|
.should.equal(true)
|
||||||
|
})
|
||||||
|
|
||||||
it('should delete the extra files', function() {
|
it('should delete the extra files', function() {
|
||||||
return this.ResourceWriter._deleteFileIfNotDirectory
|
return this.ResourceWriter._deleteFileIfNotDirectory
|
||||||
.calledWith(path.join(this.basePath, 'extra/file.tex'))
|
.calledWith(path.join(this.basePath, 'extra/file.tex'))
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ describe('UrlCache', function() {
|
|||||||
|
|
||||||
describe('_ensureUrlIsInCache', function() {
|
describe('_ensureUrlIsInCache', function() {
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
this.UrlFetcher.pipeUrlToFile = sinon.stub().callsArg(2)
|
this.UrlFetcher.pipeUrlToFileWithRetry = sinon.stub().callsArg(2)
|
||||||
return (this.UrlCache._updateOrCreateUrlDetails = sinon
|
return (this.UrlCache._updateOrCreateUrlDetails = sinon
|
||||||
.stub()
|
.stub()
|
||||||
.callsArg(3))
|
.callsArg(3))
|
||||||
@@ -190,7 +190,7 @@ describe('UrlCache', function() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should download the URL to the cache file', function() {
|
it('should download the URL to the cache file', function() {
|
||||||
return this.UrlFetcher.pipeUrlToFile
|
return this.UrlFetcher.pipeUrlToFileWithRetry
|
||||||
.calledWith(
|
.calledWith(
|
||||||
this.url,
|
this.url,
|
||||||
this.UrlCache._cacheFilePathForUrl(this.project_id, this.url)
|
this.UrlCache._cacheFilePathForUrl(this.project_id, this.url)
|
||||||
@@ -232,7 +232,7 @@ describe('UrlCache', function() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should not download the URL to the cache file', function() {
|
it('should not download the URL to the cache file', function() {
|
||||||
return this.UrlFetcher.pipeUrlToFile.called.should.equal(false)
|
return this.UrlFetcher.pipeUrlToFileWithRetry.called.should.equal(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
return it('should return the callback with the cache file path', function() {
|
return it('should return the callback with the cache file path', function() {
|
||||||
|
|||||||
@@ -33,72 +33,64 @@ describe('UrlFetcher', function() {
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
describe('pipeUrlToFileWithRetry', function() {
|
||||||
it('should turn off the cookie jar in request', function() {
|
this.beforeEach(function() {
|
||||||
return this.defaults.calledWith({ jar: false }).should.equal(true)
|
this.UrlFetcher.pipeUrlToFile = sinon.stub()
|
||||||
})
|
|
||||||
|
|
||||||
describe('rewrite url domain if filestoreDomainOveride is set', function() {
|
|
||||||
beforeEach(function() {
|
|
||||||
this.path = '/path/to/file/on/disk'
|
|
||||||
this.request.get = sinon
|
|
||||||
.stub()
|
|
||||||
.returns((this.urlStream = new EventEmitter()))
|
|
||||||
this.urlStream.pipe = sinon.stub()
|
|
||||||
this.urlStream.pause = sinon.stub()
|
|
||||||
this.urlStream.resume = sinon.stub()
|
|
||||||
this.fs.createWriteStream = sinon
|
|
||||||
.stub()
|
|
||||||
.returns((this.fileStream = new EventEmitter()))
|
|
||||||
return (this.fs.unlink = (file, callback) => callback())
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should use the normal domain when override not set', function(done) {
|
it('should call pipeUrlToFile', function(done) {
|
||||||
this.UrlFetcher.pipeUrlToFile(this.url, this.path, () => {
|
this.UrlFetcher.pipeUrlToFile.callsArgWith(2)
|
||||||
this.request.get.args[0][0].url.should.equal(this.url)
|
this.UrlFetcher.pipeUrlToFileWithRetry(this.url, this.path, err => {
|
||||||
return done()
|
expect(err).to.equal(undefined)
|
||||||
|
this.UrlFetcher.pipeUrlToFile.called.should.equal(true)
|
||||||
|
done()
|
||||||
})
|
})
|
||||||
this.res = { statusCode: 200 }
|
|
||||||
this.urlStream.emit('response', this.res)
|
|
||||||
this.urlStream.emit('end')
|
|
||||||
return this.fileStream.emit('finish')
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return it('should use override domain when filestoreDomainOveride is set', function(done) {
|
it('should call pipeUrlToFile multiple times on error', function(done) {
|
||||||
this.settings.filestoreDomainOveride = '192.11.11.11'
|
const error = new Error("couldn't download file")
|
||||||
this.UrlFetcher.pipeUrlToFile(this.url, this.path, () => {
|
this.UrlFetcher.pipeUrlToFile.callsArgWith(2, error)
|
||||||
this.request.get.args[0][0].url.should.equal(
|
this.UrlFetcher.pipeUrlToFileWithRetry(this.url, this.path, err => {
|
||||||
'192.11.11.11/file/here?query=string'
|
expect(err).to.equal(error)
|
||||||
)
|
this.UrlFetcher.pipeUrlToFile.callCount.should.equal(3)
|
||||||
return done()
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should call pipeUrlToFile twice if only 1 error', function(done) {
|
||||||
|
this.UrlFetcher.pipeUrlToFile.onCall(0).callsArgWith(2, 'error')
|
||||||
|
this.UrlFetcher.pipeUrlToFile.onCall(1).callsArgWith(2)
|
||||||
|
this.UrlFetcher.pipeUrlToFileWithRetry(this.url, this.path, err => {
|
||||||
|
expect(err).to.equal(undefined)
|
||||||
|
this.UrlFetcher.pipeUrlToFile.callCount.should.equal(2)
|
||||||
|
done()
|
||||||
})
|
})
|
||||||
this.res = { statusCode: 200 }
|
|
||||||
this.urlStream.emit('response', this.res)
|
|
||||||
this.urlStream.emit('end')
|
|
||||||
return this.fileStream.emit('finish')
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
return describe('pipeUrlToFile', function() {
|
describe('pipeUrlToFile', function() {
|
||||||
beforeEach(function(done) {
|
it('should turn off the cookie jar in request', function() {
|
||||||
this.path = '/path/to/file/on/disk'
|
return this.defaults.calledWith({ jar: false }).should.equal(true)
|
||||||
this.request.get = sinon
|
|
||||||
.stub()
|
|
||||||
.returns((this.urlStream = new EventEmitter()))
|
|
||||||
this.urlStream.pipe = sinon.stub()
|
|
||||||
this.urlStream.pause = sinon.stub()
|
|
||||||
this.urlStream.resume = sinon.stub()
|
|
||||||
this.fs.createWriteStream = sinon
|
|
||||||
.stub()
|
|
||||||
.returns((this.fileStream = new EventEmitter()))
|
|
||||||
this.fs.unlink = (file, callback) => callback()
|
|
||||||
return done()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('successfully', function() {
|
describe('rewrite url domain if filestoreDomainOveride is set', function() {
|
||||||
beforeEach(function(done) {
|
beforeEach(function() {
|
||||||
|
this.path = '/path/to/file/on/disk'
|
||||||
|
this.request.get = sinon
|
||||||
|
.stub()
|
||||||
|
.returns((this.urlStream = new EventEmitter()))
|
||||||
|
this.urlStream.pipe = sinon.stub()
|
||||||
|
this.urlStream.pause = sinon.stub()
|
||||||
|
this.urlStream.resume = sinon.stub()
|
||||||
|
this.fs.createWriteStream = sinon
|
||||||
|
.stub()
|
||||||
|
.returns((this.fileStream = new EventEmitter()))
|
||||||
|
return (this.fs.unlink = (file, callback) => callback())
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should use the normal domain when override not set', function(done) {
|
||||||
this.UrlFetcher.pipeUrlToFile(this.url, this.path, () => {
|
this.UrlFetcher.pipeUrlToFile(this.url, this.path, () => {
|
||||||
this.callback()
|
this.request.get.args[0][0].url.should.equal(this.url)
|
||||||
return done()
|
return done()
|
||||||
})
|
})
|
||||||
this.res = { statusCode: 200 }
|
this.res = { statusCode: 200 }
|
||||||
@@ -107,67 +99,113 @@ describe('UrlFetcher', function() {
|
|||||||
return this.fileStream.emit('finish')
|
return this.fileStream.emit('finish')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should request the URL', function() {
|
return it('should use override domain when filestoreDomainOveride is set', function(done) {
|
||||||
return this.request.get
|
this.settings.filestoreDomainOveride = '192.11.11.11'
|
||||||
.calledWith(sinon.match({ url: this.url }))
|
this.UrlFetcher.pipeUrlToFile(this.url, this.path, () => {
|
||||||
.should.equal(true)
|
this.request.get.args[0][0].url.should.equal(
|
||||||
})
|
'192.11.11.11/file/here?query=string'
|
||||||
|
)
|
||||||
it('should open the file for writing', function() {
|
|
||||||
return this.fs.createWriteStream
|
|
||||||
.calledWith(this.path)
|
|
||||||
.should.equal(true)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should pipe the URL to the file', function() {
|
|
||||||
return this.urlStream.pipe
|
|
||||||
.calledWith(this.fileStream)
|
|
||||||
.should.equal(true)
|
|
||||||
})
|
|
||||||
|
|
||||||
return it('should call the callback', function() {
|
|
||||||
return this.callback.called.should.equal(true)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('with non success status code', function() {
|
|
||||||
beforeEach(function(done) {
|
|
||||||
this.UrlFetcher.pipeUrlToFile(this.url, this.path, err => {
|
|
||||||
this.callback(err)
|
|
||||||
return done()
|
return done()
|
||||||
})
|
})
|
||||||
this.res = { statusCode: 404 }
|
this.res = { statusCode: 200 }
|
||||||
this.urlStream.emit('response', this.res)
|
this.urlStream.emit('response', this.res)
|
||||||
return this.urlStream.emit('end')
|
this.urlStream.emit('end')
|
||||||
})
|
return this.fileStream.emit('finish')
|
||||||
|
|
||||||
it('should call the callback with an error', function() {
|
|
||||||
this.callback.calledWith(sinon.match(Error)).should.equal(true)
|
|
||||||
|
|
||||||
const message = this.callback.args[0][0].message
|
|
||||||
expect(message).to.include('URL returned non-success status code: 404')
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
return describe('with error', function() {
|
return describe('pipeUrlToFile', function() {
|
||||||
beforeEach(function(done) {
|
beforeEach(function(done) {
|
||||||
this.UrlFetcher.pipeUrlToFile(this.url, this.path, err => {
|
this.path = '/path/to/file/on/disk'
|
||||||
this.callback(err)
|
this.request.get = sinon
|
||||||
return done()
|
.stub()
|
||||||
|
.returns((this.urlStream = new EventEmitter()))
|
||||||
|
this.urlStream.pipe = sinon.stub()
|
||||||
|
this.urlStream.pause = sinon.stub()
|
||||||
|
this.urlStream.resume = sinon.stub()
|
||||||
|
this.fs.createWriteStream = sinon
|
||||||
|
.stub()
|
||||||
|
.returns((this.fileStream = new EventEmitter()))
|
||||||
|
this.fs.unlink = (file, callback) => callback()
|
||||||
|
return done()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('successfully', function() {
|
||||||
|
beforeEach(function(done) {
|
||||||
|
this.UrlFetcher.pipeUrlToFile(this.url, this.path, () => {
|
||||||
|
this.callback()
|
||||||
|
return done()
|
||||||
|
})
|
||||||
|
this.res = { statusCode: 200 }
|
||||||
|
this.urlStream.emit('response', this.res)
|
||||||
|
this.urlStream.emit('end')
|
||||||
|
return this.fileStream.emit('finish')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should request the URL', function() {
|
||||||
|
return this.request.get
|
||||||
|
.calledWith(sinon.match({ url: this.url }))
|
||||||
|
.should.equal(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should open the file for writing', function() {
|
||||||
|
return this.fs.createWriteStream
|
||||||
|
.calledWith(this.path)
|
||||||
|
.should.equal(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should pipe the URL to the file', function() {
|
||||||
|
return this.urlStream.pipe
|
||||||
|
.calledWith(this.fileStream)
|
||||||
|
.should.equal(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
return it('should call the callback', function() {
|
||||||
|
return this.callback.called.should.equal(true)
|
||||||
})
|
})
|
||||||
return this.urlStream.emit(
|
|
||||||
'error',
|
|
||||||
(this.error = new Error('something went wrong'))
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should call the callback with the error', function() {
|
describe('with non success status code', function() {
|
||||||
return this.callback.calledWith(this.error).should.equal(true)
|
beforeEach(function(done) {
|
||||||
|
this.UrlFetcher.pipeUrlToFile(this.url, this.path, err => {
|
||||||
|
this.callback(err)
|
||||||
|
return done()
|
||||||
|
})
|
||||||
|
this.res = { statusCode: 404 }
|
||||||
|
this.urlStream.emit('response', this.res)
|
||||||
|
return this.urlStream.emit('end')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should call the callback with an error', function() {
|
||||||
|
this.callback.calledWith(sinon.match(Error)).should.equal(true)
|
||||||
|
|
||||||
|
const message = this.callback.args[0][0].message
|
||||||
|
expect(message).to.include(
|
||||||
|
'URL returned non-success status code: 404'
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
return it('should only call the callback once, even if end is called', function() {
|
return describe('with error', function() {
|
||||||
this.urlStream.emit('end')
|
beforeEach(function(done) {
|
||||||
return this.callback.calledOnce.should.equal(true)
|
this.UrlFetcher.pipeUrlToFile(this.url, this.path, err => {
|
||||||
|
this.callback(err)
|
||||||
|
return done()
|
||||||
|
})
|
||||||
|
return this.urlStream.emit(
|
||||||
|
'error',
|
||||||
|
(this.error = new Error('something went wrong'))
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should call the callback with the error', function() {
|
||||||
|
return this.callback.calledWith(this.error).should.equal(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
return it('should only call the callback once, even if end is called', function() {
|
||||||
|
this.urlStream.emit('end')
|
||||||
|
return this.callback.calledOnce.should.equal(true)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user