From f914826959f6eaa661d3e4566bc0a0705cc61952 Mon Sep 17 00:00:00 2001 From: J H <2364004+Blu-J@users.noreply.github.com> Date: Wed, 8 Mar 2023 10:55:48 -0700 Subject: [PATCH] feat: Backup w/ readDir --- backups.ts | 124 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 76 insertions(+), 48 deletions(-) diff --git a/backups.ts b/backups.ts index d795352..2682081 100644 --- a/backups.ts +++ b/backups.ts @@ -1,5 +1,5 @@ -import { ok } from "./util.ts"; -import * as T from "./types.ts"; +import { ok } from "./util"; +import * as T from "./types"; export const DEFAULT_OPTIONS: T.BackupOptions = { delete: true, @@ -33,28 +33,24 @@ type BackupSet = { * srcVolume: 'main', srcPath:'smallData/', dstPath: 'main/smallData/', dstVolume: : Backups.BACKUP * }, { * srcVolume: 'main', srcPath:'bigData/', dstPath: 'main/bigData/', dstVolume: : Backups.BACKUP, options: {exclude:['bigData/excludeThis']}} - * ).build() + * ).build()q * ``` */ export class Backups { static BACKUP = "BACKUP" as const; - constructor( - private options = DEFAULT_OPTIONS, - private backupSet = [] as BackupSet[], - ) { - } + constructor(private options = DEFAULT_OPTIONS, private backupSet = [] as BackupSet[]) {} static volumes(...volumeNames: string[]) { - return new Backups().addSets(...volumeNames.map((srcVolume) => ({ - srcVolume, - srcPath: "./", - dstPath: `./${srcVolume}/`, - dstVolume: Backups.BACKUP, - }))); + return new Backups().addSets( + ...volumeNames.map((srcVolume) => ({ + srcVolume, + srcPath: "./", + dstPath: `./${srcVolume}/`, + dstVolume: Backups.BACKUP, + })) + ); } - static addSets( - ...options: BackupSet[] - ) { + static addSets(...options: BackupSet[]) { return new Backups().addSets(...options); } static with_options(options?: Partial) { @@ -68,23 +64,51 @@ export class Backups { return this; } volumes(...volumeNames: string[]) { - return this.addSets(...volumeNames.map((srcVolume) => ({ - srcVolume, - srcPath: "./", - dstPath: `./${srcVolume}/`, - dstVolume: Backups.BACKUP, - }))); - } - addSets( - ...options: BackupSet[] - ) { - options.forEach((x) => - this.backupSet.push({ ...x, options: { ...this.options, ...x.options } }) + return this.addSets( + ...volumeNames.map((srcVolume) => ({ + srcVolume, + srcPath: "./", + dstPath: `./${srcVolume}/`, + dstVolume: Backups.BACKUP, + })) ); + } + addSets(...options: BackupSet[]) { + options.forEach((x) => this.backupSet.push({ ...x, options: { ...this.options, ...x.options } })); return this; } build() { - const createBackup: T.ExpectedExports.createBackup = async (effects) => { + const createBackup: T.ExpectedExports.createBackup = async ({ effects }) => { + const previousItems = ( + await effects + .readDir({ + volumeId: Backups.BACKUP, + path: ".", + }) + .catch(() => []) + ).map((x) => `${x}`); + const backupPaths = this.backupSet + .filter((x) => x.dstVolume === Backups.BACKUP) + .map((x) => x.dstPath) + .map((x) => x.replace(/\.\/([^]*)\//, "$1")); + const filteredItems = previousItems.filter((x) => backupPaths.indexOf(x) === -1); + for (const itemToRemove of filteredItems) { + effects.error(`Trying to remove ${itemToRemove}`); + await effects + .removeDir({ + volumeId: Backups.BACKUP, + path: itemToRemove, + }) + .catch(() => + effects.removeFile({ + volumeId: Backups.BACKUP, + path: itemToRemove, + }) + ) + .catch(() => { + effects.warn(`Failed to remove ${itemToRemove} from backup volume`); + }); + } for (const item of this.backupSet) { if (notEmptyPath(item.dstPath)) { await effects.createDir({ @@ -92,17 +116,19 @@ export class Backups { path: item.dstPath, }); } - await effects.runRsync({ - ...item, - options: { - ...this.options, - ...item.options, - }, - }).wait(); + await effects + .runRsync({ + ...item, + options: { + ...this.options, + ...item.options, + }, + }) + .wait(); } return ok; }; - const restoreBackup: T.ExpectedExports.restoreBackup = async (effects) => { + const restoreBackup: T.ExpectedExports.restoreBackup = async ({ effects }) => { for (const item of this.backupSet) { if (notEmptyPath(item.srcPath)) { await effects.createDir({ @@ -110,16 +136,18 @@ export class Backups { path: item.srcPath, }); } - await effects.runRsync({ - options: { - ...this.options, - ...item.options, - }, - srcVolume: item.dstVolume, - dstVolume: item.srcVolume, - srcPath: item.dstPath, - dstPath: item.srcPath, - }).wait(); + await effects + .runRsync({ + options: { + ...this.options, + ...item.options, + }, + srcVolume: item.dstVolume, + dstVolume: item.srcVolume, + srcPath: item.dstPath, + dstPath: item.srcPath, + }) + .wait(); } return ok; };