mirror of
https://github.com/cupcakearmy/autorestic.git
synced 2025-09-02 08:40:39 +00:00
Fix #2: support pruning and forget via snapshot policies
This commit is contained in:
@@ -18,8 +18,9 @@ export const { _: commands, ...flags } = minimist(process.argv.slice(2), {
|
||||
a: 'all',
|
||||
l: 'location',
|
||||
b: 'backend',
|
||||
d: 'dry-run',
|
||||
},
|
||||
boolean: ['a'],
|
||||
boolean: ['a', 'd'],
|
||||
string: ['l', 'b'],
|
||||
})
|
||||
|
||||
|
60
src/forget.ts
Normal file
60
src/forget.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { Writer } from 'clitastic'
|
||||
|
||||
import { config, VERBOSE } from './autorestic'
|
||||
import { getEnvFromBackend } from './backend'
|
||||
import { Locations, Location, ForgetPolicy, Flags } from './types'
|
||||
import { exec, ConfigError } from './utils'
|
||||
|
||||
export const forgetSingle = (dryRun: boolean, name: string, from: string, to: string, policy: ForgetPolicy) => {
|
||||
if (!config) throw ConfigError
|
||||
const writer = new Writer(name + to.blue + ' : ' + 'Removing old spnapshots… ⏳')
|
||||
const backend = config.backends[to]
|
||||
const flags = [] as any[]
|
||||
for (const [name, value] of Object.entries(policy)) {
|
||||
flags.push(`--keep-${name}`)
|
||||
flags.push(value)
|
||||
}
|
||||
if (dryRun) {
|
||||
flags.push('--dry-run')
|
||||
}
|
||||
const env = getEnvFromBackend(backend)
|
||||
writer.appendLn(name + to.blue + ' : ' + 'Forgeting old snapshots… ⏳')
|
||||
const cmd = exec('restic', ['forget', '--path', from, '--prune', ...flags], {env})
|
||||
|
||||
if (VERBOSE) console.log(cmd.out, cmd.err)
|
||||
writer.done(name + to.blue + ' : ' + 'Done ✓'.green)
|
||||
}
|
||||
|
||||
export const forgetLocation = (dryRun: boolean, name: string, backup: Location, policy?: ForgetPolicy) => {
|
||||
const display = name.yellow + ' ▶ '
|
||||
if (!policy) {
|
||||
console.log(display + 'skipping, no policy declared')
|
||||
}
|
||||
else {
|
||||
if (Array.isArray(backup.to)) {
|
||||
let first = true
|
||||
for (const t of backup.to) {
|
||||
const nameOrBlankSpaces: string = first
|
||||
? display
|
||||
: new Array(name.length + 3).fill(' ').join('')
|
||||
forgetSingle(dryRun, nameOrBlankSpaces, backup.from, t, policy)
|
||||
if (first) first = false
|
||||
}
|
||||
} else forgetSingle(dryRun, display, backup.from, backup.to, policy)
|
||||
}
|
||||
}
|
||||
|
||||
export const forgetAll = (dryRun: boolean, backups?: Locations) => {
|
||||
if (!config) throw ConfigError
|
||||
if (!backups) {
|
||||
backups = config.locations
|
||||
}
|
||||
|
||||
console.log('\nRemoving old shapshots according to policy'.underline.grey)
|
||||
if (dryRun) console.log('Running in dry-run mode, not touching data\n'.yellow)
|
||||
|
||||
for (const [name, backup] of Object.entries(backups)) {
|
||||
var policy = config.locations[name].keep
|
||||
forgetLocation(dryRun, name, backup, policy)
|
||||
}
|
||||
}
|
@@ -7,6 +7,7 @@ import { join, resolve } from 'path'
|
||||
import { config, INSTALL_DIR, VERSION } from './autorestic'
|
||||
import { checkAndConfigureBackends, getEnvFromBackend } from './backend'
|
||||
import { backupAll } from './backup'
|
||||
import { forgetAll } from './forget'
|
||||
import { Backends, Flags, Locations } from './types'
|
||||
import {
|
||||
checkIfCommandIsAvailable,
|
||||
@@ -102,6 +103,22 @@ const handlers: Handlers = {
|
||||
w.done(name.green + '\t\tDone 🎉')
|
||||
}
|
||||
},
|
||||
forget(args, flags) {
|
||||
if (!config) throw ConfigError
|
||||
checkIfResticIsAvailable()
|
||||
const locations: Locations = parseLocations(flags)
|
||||
|
||||
const backends = new Set<string>()
|
||||
for (const to of Object.values(locations).map(location => location.to))
|
||||
Array.isArray(to) ? to.forEach(t => backends.add(t)) : backends.add(to)
|
||||
|
||||
checkAndConfigureBackends(
|
||||
filterObjectByKey(config.backends, Array.from(backends))
|
||||
)
|
||||
forgetAll(flags['dry-run'], locations)
|
||||
|
||||
console.log('\nFinished!'.underline + ' 🎉')
|
||||
},
|
||||
exec(args, flags) {
|
||||
checkIfResticIsAvailable()
|
||||
const backends = parseBackend(flags)
|
||||
@@ -219,6 +236,7 @@ export const help = () => {
|
||||
'\nCommands:'.yellow +
|
||||
'\n check [-b, --backend] [-a, --all] Check backends' +
|
||||
'\n backup [-l, --location] [-a, --all] Backup all or specified locations' +
|
||||
'\n forget [-l, --location] [-a, --all] [--dry-run] Forget old snapshots according to declared policies' +
|
||||
'\n restore [-l, --location] [-- --target <out dir>] Restore all or specified locations' +
|
||||
'\n' +
|
||||
'\n exec [-b, --backend] [-a, --all] <command> -- [native options] Execute native restic command' +
|
||||
|
12
src/types.ts
12
src/types.ts
@@ -62,9 +62,21 @@ export type Backend =
|
||||
|
||||
export type Backends = { [name: string]: Backend }
|
||||
|
||||
export type ForgetPolicy = {
|
||||
last?: number,
|
||||
hourly?: number,
|
||||
daily?: number,
|
||||
weekly?: number,
|
||||
monthly?: number,
|
||||
yearly?: number,
|
||||
within?: string,
|
||||
tags?: string[],
|
||||
}
|
||||
|
||||
export type Location = {
|
||||
from: string
|
||||
to: string | string[]
|
||||
keep?: ForgetPolicy
|
||||
}
|
||||
|
||||
export type Locations = { [name: string]: Location }
|
||||
|
Reference in New Issue
Block a user