diff --git a/src/apps.js b/src/apps.js index bcd0a17fd..088543e54 100644 --- a/src/apps.js +++ b/src/apps.js @@ -182,7 +182,6 @@ const appTaskManager = require('./apptaskmanager.js'), services = require('./services.js'), shell = require('./shell.js')('apps'), tasks = require('./tasks.js'), - tgz = require('./backupformat/tgz.js'), TransformStream = require('stream').Transform, users = require('./users.js'), util = require('util'), @@ -2837,7 +2836,7 @@ async function getBackupDownloadStream(app, backupId) { const ps = new PassThrough(); - const stream = await backupTargets.storageApi(backupTarget).download(backupTarget.config, tgz.getBackupFilePath(backupTarget, backup.remotePath)); + const stream = await backupTargets.storageApi(backupTarget).download(backupTarget.config, backupTargets.getBackupFilePath(backupTarget, backup.remotePath)); stream.on('error', function(error) { debug(`getBackupDownloadStream: read stream error: ${error.message}`); ps.emit('error', new BoxError(BoxError.EXTERNAL_ERROR, error)); diff --git a/src/backupcleaner.js b/src/backupcleaner.js index b3203ef24..164fe78ae 100644 --- a/src/backupcleaner.js +++ b/src/backupcleaner.js @@ -11,7 +11,6 @@ exports = module.exports = { const apps = require('./apps.js'), archives = require('./archives.js'), assert = require('assert'), - backupFormat = require('./backupformat.js'), backups = require('./backups.js'), backupTargets = require('./backuptargets.js'), constants = require('./constants.js'), @@ -83,7 +82,7 @@ async function removeBackup(target, backup, progressCallback) { assert.strictEqual(typeof backup, 'object'); assert.strictEqual(typeof progressCallback, 'function'); - const backupFilePath = backupFormat.api(target.format).getBackupFilePath(target, backup.remotePath); + const backupFilePath = backupTargets.getBackupFilePath(target, backup.remotePath); let removeError; if (target.format ==='tgz') { @@ -218,7 +217,7 @@ async function cleanupMissingBackups(target, progressCallback) { for (const backup of result) { if (backup.state !== backups.BACKUP_STATE_NORMAL) continue; // note: errored and incomplete backups are cleaned up by the backup retention logic - let backupFilePath = backupFormat.api(target.format).getBackupFilePath(target, backup.remotePath); + let backupFilePath = backupTargets.getBackupFilePath(target, backup.remotePath); if (target.format === 'rsync') backupFilePath = backupFilePath + '/'; // add trailing slash to indicate directory const [existsError, exists] = await safe(backupTargets.storageApi(target).exists(target.config, backupFilePath)); @@ -255,9 +254,9 @@ async function removeOldAppSnapshots(backupTarget) { if (app !== null) continue; // app is still installed if (snapshotInfo[appId].format ==='tgz') { - await safe(backupTargets.storageApi(backupTarget).remove(backupTarget.config, backupFormat.api(snapshotInfo[appId].format).getBackupFilePath(backupTarget, `snapshot/app_${appId}`)), { debug }); + await safe(backupTargets.storageApi(backupTarget).remove(backupTarget.config, backupTargets.getBackupFilePath(backupTarget, `snapshot/app_${appId}`)), { debug }); } else { - await safe(backupTargets.storageApi(backupTarget).removeDir(backupTarget.config, backupFormat.api(snapshotInfo[appId].format).getBackupFilePath(backupTarget, `snapshot/app_${appId}`), progressCallback), { debug }); + await safe(backupTargets.storageApi(backupTarget).removeDir(backupTarget.config, backupTargets.getBackupFilePath(backupTarget, `snapshot/app_${appId}`), progressCallback), { debug }); } await backupTargets.setSnapshotInfo(backupTarget, appId, null /* info */); diff --git a/src/backupformat/rsync.js b/src/backupformat/rsync.js index c5a896037..6c00aef11 100644 --- a/src/backupformat/rsync.js +++ b/src/backupformat/rsync.js @@ -1,7 +1,6 @@ 'use strict'; exports = module.exports = { - getBackupFilePath, download, upload, @@ -28,16 +27,6 @@ const assert = require('assert'), stream = require('stream/promises'), syncer = require('../syncer.js'); -function getBackupFilePath(backupTarget, remotePath) { - assert.strictEqual(typeof backupTarget, 'object'); - assert.strictEqual(typeof remotePath, 'string'); - - // we don't have a rootPath for noop - if (backupTarget.provider === 'noop') return remotePath; - - return path.join(backupTarget.config.rootPath, remotePath); -} - async function addFile(sourceFile, encryption, uploader, progressCallback) { assert.strictEqual(typeof sourceFile, 'string'); assert.strictEqual(typeof encryption, 'object'); @@ -82,7 +71,7 @@ async function processSyncerChange(change, backupTarget, remotePath, dataLayout, debug('sync: processing task: %j', change); // the empty task.path is special to signify the directory const destPath = change.path && backupTarget.encryption?.encryptedFilenames ? hush.encryptFilePath(change.path, backupTarget.encryption) : change.path; - const backupFilePath = path.join(getBackupFilePath(backupTarget, remotePath), destPath); + const backupFilePath = path.join(backupTargets.getBackupFilePath(backupTarget, remotePath), destPath); if (change.operation === 'removedir') { debug(`Removing directory ${backupFilePath}`); @@ -268,7 +257,7 @@ async function download(backupTarget, remotePath, dataLayout, progressCallback) assert(dataLayout instanceof DataLayout, 'dataLayout must be a DataLayout'); assert.strictEqual(typeof progressCallback, 'function'); - const backupFilePath = getBackupFilePath(backupTarget, remotePath); + const backupFilePath = backupTargets.getBackupFilePath(backupTarget, remotePath); debug(`download: Downloading ${backupFilePath} to ${dataLayout.toString()}`); diff --git a/src/backupformat/tgz.js b/src/backupformat/tgz.js index ba38cd0b9..72fa3f724 100644 --- a/src/backupformat/tgz.js +++ b/src/backupformat/tgz.js @@ -16,16 +16,6 @@ const assert = require('assert'), tar = require('tar-stream'), zlib = require('zlib'); -function getBackupFilePath(backupTarget, remotePath) { - assert.strictEqual(typeof backupTarget, 'object'); - assert.strictEqual(typeof remotePath, 'string'); - - // we don't have a rootPath for noop - if (backupTarget.provider === 'noop') return remotePath; - - return path.join(backupTarget.config.rootPath, remotePath); -} - // In tar, the entry header contains the file size. If we don't provide it those many bytes, the tar will become corrupt // Linux provides no guarantee of how many bytes can be read from a file. This is the case with sqlite and log files // which are accessed by other processes when tar is in action. This class handles overflow and underflow @@ -236,7 +226,7 @@ async function download(backupTarget, remotePath, dataLayout, progressCallback) debug(`download: Downloading ${remotePath} to ${dataLayout.toString()}`); - const backupFilePath = getBackupFilePath(backupTarget, remotePath); + const backupFilePath = backupTargets.getBackupFilePath(backupTarget, remotePath); await promiseRetry({ times: 5, interval: 20000, debug }, async () => { progressCallback({ message: `Downloading backup ${backupFilePath}` }); @@ -254,7 +244,7 @@ async function upload(backupTarget, remotePath, dataLayout, progressCallback) { debug(`upload: Uploading ${dataLayout.toString()} to ${remotePath}`); - const backupFilePath = getBackupFilePath(backupTarget, remotePath); + const backupFilePath = backupTargets.getBackupFilePath(backupTarget, remotePath); await promiseRetry({ times: 5, interval: 20000, debug }, async () => { progressCallback({ message: `Uploading backup ${backupFilePath}` }); @@ -265,7 +255,6 @@ async function upload(backupTarget, remotePath, dataLayout, progressCallback) { } exports = module.exports = { - getBackupFilePath, download, upload, diff --git a/src/backuptargets.js b/src/backuptargets.js index 9560fc520..125f8a3e2 100644 --- a/src/backuptargets.js +++ b/src/backuptargets.js @@ -30,7 +30,9 @@ exports = module.exports = { getMountStatus, ensureMounted, - storageApi + storageApi, + + getBackupFilePath }; const assert = require('assert'), @@ -97,6 +99,16 @@ function storageApi(backupTarget) { } } +function getBackupFilePath(backupTarget, remotePath) { + assert.strictEqual(typeof backupTarget, 'object'); + assert.strictEqual(typeof remotePath, 'string'); + + // we don't have a rootPath for noop + if (backupTarget.provider === 'noop') return remotePath; + + return path.join(backupTarget.config.rootPath, remotePath); +} + function getRootPath(provider, config, mountPath) { assert.strictEqual(typeof config, 'object'); assert.strictEqual(typeof mountPath, 'string'); diff --git a/src/backuptask.js b/src/backuptask.js index 829c70eaa..18007abbe 100644 --- a/src/backuptask.js +++ b/src/backuptask.js @@ -206,12 +206,11 @@ async function copy(backupTarget, srcRemotePath, destRemotePath, progressCallbac assert.strictEqual(typeof destRemotePath, 'string'); assert.strictEqual(typeof progressCallback, 'function'); - const { config, format } = backupTarget; - const oldFilePath = backupFormat.api(format).getBackupFilePath(backupTarget, srcRemotePath); - const newFilePath = backupFormat.api(format).getBackupFilePath(backupTarget, destRemotePath); + const oldFilePath = backupTargets.getBackupFilePath(backupTarget, srcRemotePath); + const newFilePath = backupTargets.getBackupFilePath(backupTarget, destRemotePath); const startTime = new Date(); - const [copyError] = await safe(backupTargets.storageApi(backupTarget).copy(config, oldFilePath, newFilePath, progressCallback)); + const [copyError] = await safe(backupTargets.storageApi(backupTarget).copy(backupTarget.config, oldFilePath, newFilePath, progressCallback)); if (copyError) { debug(`copy: copied to ${destRemotePath} errored. error: ${copyError.message}`); throw copyError;