2019-05-29 05:21:06 -04:00
|
|
|
/* eslint-disable
|
2020-12-15 05:23:54 -05:00
|
|
|
node/handle-callback-err,
|
2019-05-29 05:21:06 -04:00
|
|
|
max-len,
|
|
|
|
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
|
|
|
|
* DS205: Consider reworking code to avoid use of IIFEs
|
|
|
|
* DS207: Consider shorter variations of null checks
|
|
|
|
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
|
|
|
*/
|
|
|
|
let ClsiStateManager
|
2021-07-07 05:38:56 -04:00
|
|
|
const Settings = require('@overleaf/settings')
|
2019-05-29 05:21:06 -04:00
|
|
|
const logger = require('logger-sharelatex')
|
|
|
|
const crypto = require('crypto')
|
|
|
|
const ProjectEntityHandler = require('../Project/ProjectEntityHandler')
|
|
|
|
|
|
|
|
// The "state" of a project is a hash of the relevant attributes in the
|
|
|
|
// project object in this case we only need the rootFolder.
|
|
|
|
//
|
|
|
|
// The idea is that it will change if any doc or file is
|
|
|
|
// created/renamed/deleted, and also if the content of any file (not
|
|
|
|
// doc) changes.
|
|
|
|
//
|
|
|
|
// When the hash changes the full set of files on the CLSI will need to
|
|
|
|
// be updated. If it doesn't change then we can overwrite changed docs
|
|
|
|
// in place on the clsi, getting them from the docupdater.
|
|
|
|
//
|
|
|
|
// The docupdater is responsible for setting the key in redis, and
|
|
|
|
// unsetting it if it removes any documents from the doc updater.
|
|
|
|
|
|
|
|
const buildState = s =>
|
2021-04-14 09:17:21 -04:00
|
|
|
crypto.createHash('sha1').update(s, 'utf8').digest('hex')
|
2019-05-29 05:21:06 -04:00
|
|
|
|
|
|
|
module.exports = ClsiStateManager = {
|
|
|
|
computeHash(project, options, callback) {
|
|
|
|
if (callback == null) {
|
2021-10-27 05:49:18 -04:00
|
|
|
callback = function () {}
|
2019-05-29 05:21:06 -04:00
|
|
|
}
|
2021-04-14 09:17:21 -04:00
|
|
|
return ProjectEntityHandler.getAllEntitiesFromProject(
|
|
|
|
project,
|
|
|
|
function (err, docs, files) {
|
|
|
|
const fileList = Array.from(files || []).map(
|
|
|
|
f => `${f.file._id}:${f.file.rev}:${f.file.created}:${f.path}`
|
|
|
|
)
|
|
|
|
const docList = Array.from(docs || []).map(
|
|
|
|
d => `${d.doc._id}:${d.path}`
|
|
|
|
)
|
|
|
|
const sortedEntityList = [
|
|
|
|
...Array.from(docList),
|
2021-04-27 03:52:58 -04:00
|
|
|
...Array.from(fileList),
|
2021-04-14 09:17:21 -04:00
|
|
|
].sort()
|
|
|
|
// ignore the isAutoCompile options as it doesn't affect the
|
|
|
|
// output, but include all other options e.g. draft
|
|
|
|
const optionsList = (() => {
|
|
|
|
const result = []
|
|
|
|
const object = options || {}
|
2021-05-05 09:05:04 -04:00
|
|
|
for (const key in object) {
|
2021-04-14 09:17:21 -04:00
|
|
|
const value = object[key]
|
|
|
|
if (!['isAutoCompile'].includes(key)) {
|
|
|
|
result.push(`option ${key}:${value}`)
|
|
|
|
}
|
2019-05-29 05:21:06 -04:00
|
|
|
}
|
2021-04-14 09:17:21 -04:00
|
|
|
return result
|
|
|
|
})()
|
|
|
|
const sortedOptionsList = optionsList.sort()
|
|
|
|
const hash = buildState(
|
|
|
|
[
|
|
|
|
...Array.from(sortedEntityList),
|
2021-04-27 03:52:58 -04:00
|
|
|
...Array.from(sortedOptionsList),
|
2021-04-14 09:17:21 -04:00
|
|
|
].join('\n')
|
|
|
|
)
|
|
|
|
return callback(null, hash)
|
|
|
|
}
|
|
|
|
)
|
2021-04-27 03:52:58 -04:00
|
|
|
},
|
2019-05-29 05:21:06 -04:00
|
|
|
}
|