|
@@ -1,10 +1,27 @@
|
|
|
|
|
+/* eslint-disable
|
|
|
|
|
+ handle-callback-err,
|
|
|
|
|
+ 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
|
|
|
|
|
+ * DS103: Rewrite code to no longer use __guard__
|
|
|
|
|
+ * DS201: Simplify complex destructure assignments
|
|
|
|
|
+ * DS207: Consider shorter variations of null checks
|
|
|
|
|
+ * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
|
|
|
|
+ */
|
|
|
|
|
+let ResourceStateManager
|
|
|
const Path = require('path')
|
|
const Path = require('path')
|
|
|
const fs = require('fs')
|
|
const fs = require('fs')
|
|
|
const logger = require('logger-sharelatex')
|
|
const logger = require('logger-sharelatex')
|
|
|
|
|
+const settings = require('settings-sharelatex')
|
|
|
const Errors = require('./Errors')
|
|
const Errors = require('./Errors')
|
|
|
const SafeReader = require('./SafeReader')
|
|
const SafeReader = require('./SafeReader')
|
|
|
|
|
|
|
|
-module.exports = {
|
|
|
|
|
|
|
+module.exports = ResourceStateManager = {
|
|
|
// The sync state is an identifier which must match for an
|
|
// The sync state is an identifier which must match for an
|
|
|
// incremental update to be allowed.
|
|
// incremental update to be allowed.
|
|
|
//
|
|
//
|
|
@@ -23,12 +40,15 @@ module.exports = {
|
|
|
SYNC_STATE_MAX_SIZE: 128 * 1024,
|
|
SYNC_STATE_MAX_SIZE: 128 * 1024,
|
|
|
|
|
|
|
|
saveProjectState(state, resources, basePath, callback) {
|
|
saveProjectState(state, resources, basePath, callback) {
|
|
|
|
|
+ if (callback == null) {
|
|
|
|
|
+ callback = function (error) {}
|
|
|
|
|
+ }
|
|
|
const stateFile = Path.join(basePath, this.SYNC_STATE_FILE)
|
|
const stateFile = Path.join(basePath, this.SYNC_STATE_FILE)
|
|
|
if (state == null) {
|
|
if (state == null) {
|
|
|
// remove the file if no state passed in
|
|
// remove the file if no state passed in
|
|
|
logger.log({ state, basePath }, 'clearing sync state')
|
|
logger.log({ state, basePath }, 'clearing sync state')
|
|
|
- fs.unlink(stateFile, function (err) {
|
|
|
|
|
- if (err && err.code !== 'ENOENT') {
|
|
|
|
|
|
|
+ return fs.unlink(stateFile, function (err) {
|
|
|
|
|
+ if (err != null && err.code !== 'ENOENT') {
|
|
|
return callback(err)
|
|
return callback(err)
|
|
|
} else {
|
|
} else {
|
|
|
return callback()
|
|
return callback()
|
|
@@ -36,24 +56,29 @@ module.exports = {
|
|
|
})
|
|
})
|
|
|
} else {
|
|
} else {
|
|
|
logger.log({ state, basePath }, 'writing sync state')
|
|
logger.log({ state, basePath }, 'writing sync state')
|
|
|
- const resourceList = resources.map((resource) => resource.path)
|
|
|
|
|
- fs.writeFile(
|
|
|
|
|
|
|
+ const resourceList = Array.from(resources).map(
|
|
|
|
|
+ (resource) => resource.path
|
|
|
|
|
+ )
|
|
|
|
|
+ return fs.writeFile(
|
|
|
stateFile,
|
|
stateFile,
|
|
|
- [...resourceList, `stateHash:${state}`].join('\n'),
|
|
|
|
|
|
|
+ [...Array.from(resourceList), `stateHash:${state}`].join('\n'),
|
|
|
callback
|
|
callback
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
checkProjectStateMatches(state, basePath, callback) {
|
|
checkProjectStateMatches(state, basePath, callback) {
|
|
|
|
|
+ if (callback == null) {
|
|
|
|
|
+ callback = function (error, resources) {}
|
|
|
|
|
+ }
|
|
|
const stateFile = Path.join(basePath, this.SYNC_STATE_FILE)
|
|
const stateFile = Path.join(basePath, this.SYNC_STATE_FILE)
|
|
|
const size = this.SYNC_STATE_MAX_SIZE
|
|
const size = this.SYNC_STATE_MAX_SIZE
|
|
|
- SafeReader.readFile(stateFile, size, 'utf8', function (
|
|
|
|
|
|
|
+ return SafeReader.readFile(stateFile, size, 'utf8', function (
|
|
|
err,
|
|
err,
|
|
|
result,
|
|
result,
|
|
|
bytesRead
|
|
bytesRead
|
|
|
) {
|
|
) {
|
|
|
- if (err) {
|
|
|
|
|
|
|
+ if (err != null) {
|
|
|
return callback(err)
|
|
return callback(err)
|
|
|
}
|
|
}
|
|
|
if (bytesRead === size) {
|
|
if (bytesRead === size) {
|
|
@@ -62,7 +87,10 @@ module.exports = {
|
|
|
'project state file truncated'
|
|
'project state file truncated'
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
|
- const array = result.toString().split('\n')
|
|
|
|
|
|
|
+ const array =
|
|
|
|
|
+ __guard__(result != null ? result.toString() : undefined, (x) =>
|
|
|
|
|
+ x.split('\n')
|
|
|
|
|
+ ) || []
|
|
|
const adjustedLength = Math.max(array.length, 1)
|
|
const adjustedLength = Math.max(array.length, 1)
|
|
|
const resourceList = array.slice(0, adjustedLength - 1)
|
|
const resourceList = array.slice(0, adjustedLength - 1)
|
|
|
const oldState = array[adjustedLength - 1]
|
|
const oldState = array[adjustedLength - 1]
|
|
@@ -76,27 +104,36 @@ module.exports = {
|
|
|
new Errors.FilesOutOfSyncError('invalid state for incremental update')
|
|
new Errors.FilesOutOfSyncError('invalid state for incremental update')
|
|
|
)
|
|
)
|
|
|
} else {
|
|
} else {
|
|
|
- const resources = resourceList.map((path) => ({ path }))
|
|
|
|
|
- callback(null, resources)
|
|
|
|
|
|
|
+ const resources = Array.from(resourceList).map((path) => ({ path }))
|
|
|
|
|
+ return callback(null, resources)
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
checkResourceFiles(resources, allFiles, basePath, callback) {
|
|
checkResourceFiles(resources, allFiles, basePath, callback) {
|
|
|
// check the paths are all relative to current directory
|
|
// check the paths are all relative to current directory
|
|
|
- const containsRelativePath = (resource) => {
|
|
|
|
|
- const dirs = resource.path.split('/')
|
|
|
|
|
- return dirs.indexOf('..') !== -1
|
|
|
|
|
|
|
+ let file
|
|
|
|
|
+ if (callback == null) {
|
|
|
|
|
+ callback = function (error) {}
|
|
|
}
|
|
}
|
|
|
- if (resources.some(containsRelativePath)) {
|
|
|
|
|
- return callback(new Error('relative path in resource file list'))
|
|
|
|
|
|
|
+ for (file of Array.from(resources || [])) {
|
|
|
|
|
+ for (const dir of Array.from(
|
|
|
|
|
+ __guard__(file != null ? file.path : undefined, (x) => x.split('/'))
|
|
|
|
|
+ )) {
|
|
|
|
|
+ if (dir === '..') {
|
|
|
|
|
+ return callback(new Error('relative path in resource file list'))
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
// check if any of the input files are not present in list of files
|
|
// check if any of the input files are not present in list of files
|
|
|
- const seenFiles = new Set(allFiles)
|
|
|
|
|
- const missingFiles = resources
|
|
|
|
|
|
|
+ const seenFile = {}
|
|
|
|
|
+ for (file of Array.from(allFiles)) {
|
|
|
|
|
+ seenFile[file] = true
|
|
|
|
|
+ }
|
|
|
|
|
+ const missingFiles = Array.from(resources)
|
|
|
|
|
+ .filter((resource) => !seenFile[resource.path])
|
|
|
.map((resource) => resource.path)
|
|
.map((resource) => resource.path)
|
|
|
- .filter((path) => !seenFiles.has(path))
|
|
|
|
|
- if (missingFiles.length > 0) {
|
|
|
|
|
|
|
+ if ((missingFiles != null ? missingFiles.length : undefined) > 0) {
|
|
|
logger.err(
|
|
logger.err(
|
|
|
{ missingFiles, basePath, allFiles, resources },
|
|
{ missingFiles, basePath, allFiles, resources },
|
|
|
'missing input files for project'
|
|
'missing input files for project'
|
|
@@ -107,7 +144,13 @@ module.exports = {
|
|
|
)
|
|
)
|
|
|
)
|
|
)
|
|
|
} else {
|
|
} else {
|
|
|
- callback()
|
|
|
|
|
|
|
+ return callback()
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+function __guard__(value, transform) {
|
|
|
|
|
+ return typeof value !== 'undefined' && value !== null
|
|
|
|
|
+ ? transform(value)
|
|
|
|
|
+ : undefined
|
|
|
|
|
+}
|