2019-12-16 05:24:37 -05:00
|
|
|
/* eslint-disable
|
|
|
|
handle-callback-err,
|
|
|
|
no-unreachable,
|
|
|
|
node/no-deprecated-api,
|
|
|
|
*/
|
|
|
|
// TODO: This file was created by bulk-decaffeinate.
|
|
|
|
// Fix any style issues and re-enable lint.
|
2019-12-16 05:24:35 -05:00
|
|
|
/*
|
|
|
|
* decaffeinate suggestions:
|
|
|
|
* 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
|
|
|
|
*/
|
2019-12-16 05:42:31 -05:00
|
|
|
const logger = require('logger-sharelatex')
|
|
|
|
const fs = require('fs')
|
|
|
|
const path = require('path')
|
|
|
|
const LocalFileWriter = require('./LocalFileWriter')
|
|
|
|
const Errors = require('./Errors')
|
|
|
|
const rimraf = require('rimraf')
|
|
|
|
const _ = require('underscore')
|
2015-08-31 11:47:16 -04:00
|
|
|
|
2019-12-16 05:42:31 -05:00
|
|
|
const filterName = key => key.replace(/\//g, '_')
|
2014-02-26 10:10:55 -05:00
|
|
|
|
2019-12-16 05:24:35 -05:00
|
|
|
module.exports = {
|
2019-12-16 05:42:31 -05:00
|
|
|
sendFile(location, target, source, callback) {
|
|
|
|
if (callback == null) {
|
|
|
|
callback = function(err) {}
|
|
|
|
}
|
|
|
|
const filteredTarget = filterName(target)
|
|
|
|
logger.log({ location, target: filteredTarget, source }, 'sending file')
|
2019-12-16 05:24:35 -05:00
|
|
|
const done = _.once(function(err) {
|
|
|
|
if (err != null) {
|
2019-12-16 05:42:31 -05:00
|
|
|
logger.err(
|
|
|
|
{ err, location, target: filteredTarget, source },
|
|
|
|
'Error on put of file'
|
|
|
|
)
|
2019-12-16 05:24:35 -05:00
|
|
|
}
|
2019-12-16 05:42:31 -05:00
|
|
|
return callback(err)
|
|
|
|
})
|
2019-12-16 05:24:35 -05:00
|
|
|
// actually copy the file (instead of moving it) to maintain consistent behaviour
|
|
|
|
// between the different implementations
|
2019-12-16 05:42:31 -05:00
|
|
|
const sourceStream = fs.createReadStream(source)
|
|
|
|
sourceStream.on('error', done)
|
|
|
|
const targetStream = fs.createWriteStream(`${location}/${filteredTarget}`)
|
|
|
|
targetStream.on('error', done)
|
|
|
|
targetStream.on('finish', () => done())
|
|
|
|
return sourceStream.pipe(targetStream)
|
2019-12-16 05:24:35 -05:00
|
|
|
},
|
2014-02-26 10:10:55 -05:00
|
|
|
|
2019-12-16 05:42:31 -05:00
|
|
|
sendStream(location, target, sourceStream, callback) {
|
|
|
|
if (callback == null) {
|
|
|
|
callback = function(err) {}
|
|
|
|
}
|
|
|
|
logger.log({ location, target }, 'sending file stream')
|
|
|
|
sourceStream.on('error', err =>
|
|
|
|
logger.err({ location, target, err: err('error on stream to send') })
|
|
|
|
)
|
|
|
|
return LocalFileWriter.writeStream(sourceStream, null, (err, fsPath) => {
|
2019-12-16 05:24:35 -05:00
|
|
|
if (err != null) {
|
2019-12-16 05:42:31 -05:00
|
|
|
logger.err(
|
|
|
|
{ location, target, fsPath, err },
|
|
|
|
'something went wrong writing stream to disk'
|
|
|
|
)
|
|
|
|
return callback(err)
|
2019-12-16 05:24:35 -05:00
|
|
|
}
|
2019-12-16 05:42:31 -05:00
|
|
|
return this.sendFile(location, target, fsPath, (
|
|
|
|
err // delete the temporary file created above and return the original error
|
|
|
|
) => LocalFileWriter.deleteFile(fsPath, () => callback(err)))
|
|
|
|
})
|
2019-12-16 05:24:35 -05:00
|
|
|
},
|
2014-02-26 10:10:55 -05:00
|
|
|
|
2019-12-16 05:24:35 -05:00
|
|
|
// opts may be {start: Number, end: Number}
|
|
|
|
getFileStream(location, name, opts, callback) {
|
2019-12-16 05:42:31 -05:00
|
|
|
if (callback == null) {
|
|
|
|
callback = function(err, res) {}
|
|
|
|
}
|
|
|
|
const filteredName = filterName(name)
|
|
|
|
logger.log({ location, filteredName }, 'getting file')
|
2019-12-16 05:24:35 -05:00
|
|
|
return fs.open(`${location}/${filteredName}`, 'r', function(err, fd) {
|
|
|
|
if (err != null) {
|
2019-12-16 05:42:31 -05:00
|
|
|
logger.err(
|
|
|
|
{ err, location, filteredName: name },
|
|
|
|
'Error reading from file'
|
|
|
|
)
|
2019-12-16 06:16:37 -05:00
|
|
|
if (err.code === 'ENOENT') {
|
|
|
|
return callback(new Errors.NotFoundError(err.message), null)
|
|
|
|
} else {
|
|
|
|
return callback(err, null)
|
|
|
|
}
|
2019-12-16 05:24:35 -05:00
|
|
|
}
|
2019-12-16 05:42:31 -05:00
|
|
|
opts.fd = fd
|
|
|
|
const sourceStream = fs.createReadStream(null, opts)
|
|
|
|
return callback(null, sourceStream)
|
|
|
|
})
|
2019-12-16 05:24:35 -05:00
|
|
|
},
|
2014-05-23 08:57:18 -04:00
|
|
|
|
2019-12-16 05:24:35 -05:00
|
|
|
getFileSize(location, filename, callback) {
|
2019-12-16 05:42:31 -05:00
|
|
|
const fullPath = path.join(location, filterName(filename))
|
2019-12-16 05:24:35 -05:00
|
|
|
return fs.stat(fullPath, function(err, stats) {
|
|
|
|
if (err != null) {
|
|
|
|
if (err.code === 'ENOENT') {
|
2019-12-16 05:42:31 -05:00
|
|
|
logger.log({ location, filename }, 'file not found')
|
|
|
|
callback(new Errors.NotFoundError(err.message))
|
2019-12-16 05:24:35 -05:00
|
|
|
} else {
|
2019-12-16 05:42:31 -05:00
|
|
|
logger.err({ err, location, filename }, 'failed to stat file')
|
|
|
|
callback(err)
|
2019-12-16 05:24:35 -05:00
|
|
|
}
|
2019-12-16 05:42:31 -05:00
|
|
|
return
|
2019-12-16 05:24:35 -05:00
|
|
|
}
|
2019-12-16 05:42:31 -05:00
|
|
|
return callback(null, stats.size)
|
|
|
|
})
|
2019-12-16 05:24:35 -05:00
|
|
|
},
|
2014-02-26 10:10:55 -05:00
|
|
|
|
2019-12-16 05:42:31 -05:00
|
|
|
copyFile(location, fromName, toName, callback) {
|
|
|
|
if (callback == null) {
|
|
|
|
callback = function(err) {}
|
|
|
|
}
|
|
|
|
const filteredFromName = filterName(fromName)
|
|
|
|
const filteredToName = filterName(toName)
|
|
|
|
logger.log(
|
|
|
|
{ location, fromName: filteredFromName, toName: filteredToName },
|
|
|
|
'copying file'
|
|
|
|
)
|
|
|
|
const sourceStream = fs.createReadStream(`${location}/${filteredFromName}`)
|
2019-12-16 05:24:35 -05:00
|
|
|
sourceStream.on('error', function(err) {
|
2019-12-16 05:42:31 -05:00
|
|
|
logger.err(
|
|
|
|
{ err, location, key: filteredFromName },
|
|
|
|
'Error reading from file'
|
|
|
|
)
|
|
|
|
return callback(err)
|
|
|
|
})
|
|
|
|
const targetStream = fs.createWriteStream(`${location}/${filteredToName}`)
|
2019-12-16 05:24:35 -05:00
|
|
|
targetStream.on('error', function(err) {
|
2019-12-16 05:42:31 -05:00
|
|
|
logger.err(
|
|
|
|
{ err, location, key: filteredToName },
|
|
|
|
'Error writing to file'
|
|
|
|
)
|
|
|
|
return callback(err)
|
|
|
|
})
|
|
|
|
targetStream.on('finish', () => callback(null))
|
|
|
|
return sourceStream.pipe(targetStream)
|
2019-12-16 05:24:35 -05:00
|
|
|
},
|
2014-02-26 10:10:55 -05:00
|
|
|
|
2019-12-16 05:42:31 -05:00
|
|
|
deleteFile(location, name, callback) {
|
|
|
|
const filteredName = filterName(name)
|
|
|
|
logger.log({ location, filteredName }, 'delete file')
|
2019-12-16 05:24:35 -05:00
|
|
|
return fs.unlink(`${location}/${filteredName}`, function(err) {
|
|
|
|
if (err != null) {
|
2019-12-16 05:42:31 -05:00
|
|
|
logger.err({ err, location, filteredName }, 'Error on delete.')
|
|
|
|
return callback(err)
|
2019-12-16 05:24:35 -05:00
|
|
|
} else {
|
2019-12-16 05:42:31 -05:00
|
|
|
return callback()
|
2019-12-16 05:24:35 -05:00
|
|
|
}
|
2019-12-16 05:42:31 -05:00
|
|
|
})
|
2019-12-16 05:24:35 -05:00
|
|
|
},
|
2014-02-26 10:10:55 -05:00
|
|
|
|
2019-12-16 05:42:31 -05:00
|
|
|
deleteDirectory(location, name, callback) {
|
|
|
|
if (callback == null) {
|
|
|
|
callback = function(err) {}
|
|
|
|
}
|
|
|
|
const filteredName = filterName(name.replace(/\/$/, ''))
|
2019-12-16 05:24:35 -05:00
|
|
|
return rimraf(`${location}/${filteredName}`, function(err) {
|
|
|
|
if (err != null) {
|
2019-12-16 05:42:31 -05:00
|
|
|
logger.err({ err, location, filteredName }, 'Error on rimraf rmdir.')
|
|
|
|
return callback(err)
|
2019-12-16 05:24:35 -05:00
|
|
|
} else {
|
2019-12-16 05:42:31 -05:00
|
|
|
return callback()
|
2019-12-16 05:24:35 -05:00
|
|
|
}
|
2019-12-16 05:42:31 -05:00
|
|
|
})
|
2019-12-16 05:24:35 -05:00
|
|
|
},
|
2014-02-26 10:10:55 -05:00
|
|
|
|
2019-12-16 05:42:31 -05:00
|
|
|
checkIfFileExists(location, name, callback) {
|
|
|
|
if (callback == null) {
|
|
|
|
callback = function(err, exists) {}
|
|
|
|
}
|
|
|
|
const filteredName = filterName(name)
|
|
|
|
logger.log({ location, filteredName }, 'checking if file exists')
|
2019-12-16 05:24:35 -05:00
|
|
|
return fs.exists(`${location}/${filteredName}`, function(exists) {
|
2019-12-16 05:42:31 -05:00
|
|
|
logger.log({ location, filteredName, exists }, 'checked if file exists')
|
|
|
|
return callback(null, exists)
|
|
|
|
})
|
2019-12-16 05:24:35 -05:00
|
|
|
},
|
2016-03-12 02:35:49 -05:00
|
|
|
|
2019-12-16 05:42:31 -05:00
|
|
|
directorySize(location, name, callback) {
|
|
|
|
const filteredName = filterName(name.replace(/\/$/, ''))
|
|
|
|
logger.log({ location, filteredName }, 'get project size in file system')
|
2019-12-16 05:24:35 -05:00
|
|
|
return fs.readdir(`${location}/${filteredName}`, function(err, files) {
|
|
|
|
if (err != null) {
|
2019-12-16 05:42:31 -05:00
|
|
|
logger.err(
|
|
|
|
{ err, location, filteredName },
|
|
|
|
'something went wrong listing prefix in aws'
|
|
|
|
)
|
|
|
|
return callback(err)
|
2019-12-16 05:24:35 -05:00
|
|
|
}
|
2019-12-16 05:42:31 -05:00
|
|
|
let totalSize = 0
|
|
|
|
_.each(files, function(entry) {
|
|
|
|
const fd = fs.openSync(`${location}/${filteredName}/${entry}`, 'r')
|
|
|
|
const fileStats = fs.fstatSync(fd)
|
|
|
|
totalSize += fileStats.size
|
|
|
|
return fs.closeSync(fd)
|
|
|
|
})
|
|
|
|
logger.log({ totalSize }, 'total size', { files })
|
|
|
|
return callback(null, totalSize)
|
|
|
|
})
|
2019-12-16 05:24:35 -05:00
|
|
|
}
|
2019-12-16 05:42:31 -05:00
|
|
|
}
|