| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- const archiver = require('archiver')
- const OutputCacheManager = require('./OutputCacheManager')
- const OutputFileFinder = require('./OutputFileFinder')
- const Settings = require('@overleaf/settings')
- const { open } = require('node:fs/promises')
- const { NotFoundError } = require('./Errors')
- const logger = require('@overleaf/logger')
- // NOTE: Updating this list requires a corresponding change in
- // * services/web/frontend/js/features/pdf-preview/util/file-list.ts
- const ignoreFiles = ['output.fls', 'output.fdb_latexmk']
- function getContentDir(projectId, userId) {
- let subDir
- if (userId != null) {
- subDir = `${projectId}-${userId}`
- } else {
- subDir = projectId
- }
- return `${Settings.path.outputDir}/${subDir}/`
- }
- module.exports = {
- async archiveFilesForBuild(projectId, userId, build) {
- logger.debug({ projectId, userId, build }, 'Will create zip file')
- const contentDir = getContentDir(projectId, userId)
- const outputFiles = await this._getAllOutputFiles(
- contentDir,
- projectId,
- userId,
- build
- )
- const archive = archiver('zip')
- archive.on('error', err => {
- logger.warn(
- { err, projectId, userId, build },
- 'error emitted when creating output files archive'
- )
- })
- archive.on('warning', err => {
- logger.warn(
- { err, projectId, userId, build },
- 'warning emitted when creating output files archive'
- )
- })
- const missingFiles = []
- for (const { path } of outputFiles) {
- let fileHandle
- try {
- fileHandle = await open(
- `${contentDir}${OutputCacheManager.path(build, path)}`
- )
- } catch (error) {
- logger.warn(
- { path, error, projectId, userId, build },
- 'error opening file to add to output files archive'
- )
- missingFiles.push(path)
- continue
- }
- const fileStream = fileHandle.createReadStream()
- archive.append(fileStream, { name: path })
- }
- if (missingFiles.length > 0) {
- archive.append(missingFiles.join('\n'), {
- name: 'missing_files.txt',
- })
- }
- archive.finalize().catch(error => {
- logger.error(
- { error, projectId, userId, build },
- 'error finalizing output files archive'
- )
- })
- return archive
- },
- async _getAllOutputFiles(contentDir, projectId, userId, build) {
- try {
- const { outputFiles } = await OutputFileFinder.promises.findOutputFiles(
- [],
- `${contentDir}${OutputCacheManager.path(build, '.')}`
- )
- return outputFiles.filter(
- // Ignore the pdf and also ignore the files ignored by the frontend.
- ({ path }) => path !== 'output.pdf' && !ignoreFiles.includes(path)
- )
- } catch (error) {
- if (
- error.code === 'ENOENT' ||
- error.code === 'ENOTDIR' ||
- error.code === 'EACCES'
- ) {
- throw new NotFoundError('Output files not found')
- }
- throw error
- }
- },
- }
|