From c88fe0ed3ebc2be4960833facbce1a078a7a1cf7 Mon Sep 17 00:00:00 2001 From: Kasra Bigdeli Date: Mon, 21 Sep 2026 21:49:35 -0700 Subject: [PATCH] refactor: make backup copy failures observable --- src/user/system/BackupManager.ts | 38 +++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/src/user/system/BackupManager.ts b/src/user/system/BackupManager.ts index 6793be6e..8ad30c7d 100644 --- a/src/user/system/BackupManager.ts +++ b/src/user/system/BackupManager.ts @@ -1,5 +1,5 @@ import SshClientImport = require('ssh2') -import { exec } from 'child_process' +import { execFile } from 'child_process' import * as fs from 'fs-extra' import * as path from 'path' import * as tar from 'tar' @@ -33,6 +33,31 @@ export interface IBackupCallbacks { } const BACKUP_META_DATA_ABS_PATH = `${CaptainConstants.restoreDirectoryPath}/meta/${BACKUP_JSON}` + +export function copyCaptainDataForBackup( + sourceDirectory: string, + destinationDirectory: string +): Promise { + return fs + .ensureDir(destinationDirectory) + .then( + () => + new Promise((resolve, reject) => { + execFile( + 'cp', + ['-rp', `${sourceDirectory}/.`, destinationDirectory], + (error) => { + if (error) { + reject(error) + return + } + resolve() + } + ) + }) + ) + .then(() => fs.remove(path.join(destinationDirectory, 'shared-logs'))) +} export default class BackupManager { private longOperationInProgress: boolean @@ -669,13 +694,10 @@ export default class BackupManager { // We cannot use fs.copy as it doesn't properly copy the broken SymLink which might exist in LetsEncrypt // https://github.com/jprichardson/node-fs-extra/issues/638 - return new Promise(function (resolve, reject) { - const child = exec( - `mkdir -p ${dest} && cp -rp ${CaptainConstants.captainDataDirectory}/. ${dest} && rm -rf ${dest}/shared-logs` - ) - child.addListener('error', reject) - child.addListener('exit', resolve) - }) + return copyCaptainDataForBackup( + CaptainConstants.captainDataDirectory, + dest + ) }) .then(function () { return iBackupCallbacks.getNodesInfo()