mirror of
https://github.com/cupcakearmy/autorestic.git
synced 2025-09-08 11:30:40 +00:00
rewrite with commander
This commit is contained in:
144
src/backup.ts
144
src/backup.ts
@@ -1,111 +1,103 @@
|
||||
import { Writer } from 'clitastic'
|
||||
import { mkdirSync } from 'fs'
|
||||
|
||||
import { config, VERBOSE } from './autorestic'
|
||||
import { config, VERBOSE } from './'
|
||||
import { getEnvFromBackend } from './backend'
|
||||
import { LocationFromPrefixes } from './config'
|
||||
import { Locations, Location, Backend } from './types'
|
||||
import {
|
||||
exec,
|
||||
pathRelativeToConfigFile,
|
||||
getFlagsFromLocation,
|
||||
makeArrayIfIsNot,
|
||||
execPlain,
|
||||
MeasureDuration,
|
||||
fill,
|
||||
decodeLocationFromPrefix,
|
||||
checkIfDockerVolumeExistsOrFail,
|
||||
getPathFromVolume,
|
||||
exec,
|
||||
pathRelativeToConfigFile,
|
||||
getFlagsFromLocation,
|
||||
makeArrayIfIsNot,
|
||||
execPlain,
|
||||
MeasureDuration,
|
||||
fill,
|
||||
decodeLocationFromPrefix,
|
||||
checkIfDockerVolumeExistsOrFail,
|
||||
getPathFromVolume,
|
||||
} from './utils'
|
||||
|
||||
|
||||
|
||||
export const backupFromFilesystem = (from: string, location: Location, backend: Backend, tags?: string[]) => {
|
||||
const path = pathRelativeToConfigFile(from)
|
||||
const path = pathRelativeToConfigFile(from)
|
||||
|
||||
const { out, err, status } = exec(
|
||||
'restic',
|
||||
['backup', '.', ...getFlagsFromLocation(location, 'backup')],
|
||||
{ env: getEnvFromBackend(backend), cwd: path },
|
||||
)
|
||||
const { out, err, status } = exec('restic', ['backup', '.', ...getFlagsFromLocation(location, 'backup')], {
|
||||
env: getEnvFromBackend(backend),
|
||||
cwd: path,
|
||||
})
|
||||
|
||||
if (VERBOSE) console.log(out, err)
|
||||
if (status != 0 || err.length > 0)
|
||||
throw new Error(err)
|
||||
if (VERBOSE) console.log(out, err)
|
||||
if (status != 0 || err.length > 0) throw new Error(err)
|
||||
}
|
||||
|
||||
export const backupFromVolume = (volume: string, location: Location, backend: Backend) => {
|
||||
const tmp = getPathFromVolume(volume)
|
||||
try {
|
||||
mkdirSync(tmp)
|
||||
checkIfDockerVolumeExistsOrFail(volume)
|
||||
const tmp = getPathFromVolume(volume)
|
||||
try {
|
||||
mkdirSync(tmp)
|
||||
checkIfDockerVolumeExistsOrFail(volume)
|
||||
|
||||
// For incremental backups. Unfortunately due to how the docker mounts work the permissions get lost.
|
||||
// execPlain(`docker run --rm -v ${volume}:/data -v ${tmp}:/backup alpine cp -aT /data /backup`)
|
||||
execPlain(`docker run --rm -v ${volume}:/data -v ${tmp}:/backup alpine tar cf /backup/archive.tar -C /data .`)
|
||||
// For incremental backups. Unfortunately due to how the docker mounts work the permissions get lost.
|
||||
// execPlain(`docker run --rm -v ${volume}:/data -v ${tmp}:/backup alpine cp -aT /data /backup`)
|
||||
execPlain(`docker run --rm -v ${volume}:/data -v ${tmp}:/backup alpine tar cf /backup/archive.tar -C /data .`)
|
||||
|
||||
backupFromFilesystem(tmp, location, backend)
|
||||
} catch (e) {
|
||||
throw e
|
||||
} finally {
|
||||
execPlain(`rm -rf ${tmp}`)
|
||||
}
|
||||
backupFromFilesystem(tmp, location, backend)
|
||||
} catch (e) {
|
||||
throw e
|
||||
} finally {
|
||||
execPlain(`rm -rf ${tmp}`)
|
||||
}
|
||||
}
|
||||
|
||||
export const backupSingle = (name: string, to: string, location: Location) => {
|
||||
const delta = new MeasureDuration()
|
||||
const writer = new Writer(name + to.blue + ' : ' + 'Backing up... ⏳')
|
||||
const delta = new MeasureDuration()
|
||||
const writer = new Writer(name + to.blue + ' : ' + 'Backing up... ⏳')
|
||||
|
||||
try {
|
||||
const backend = config.backends[to]
|
||||
const [type, value] = decodeLocationFromPrefix(location.from)
|
||||
try {
|
||||
const backend = config.backends[to]
|
||||
const [type, value] = decodeLocationFromPrefix(location.from)
|
||||
|
||||
switch (type) {
|
||||
switch (type) {
|
||||
case LocationFromPrefixes.Filesystem:
|
||||
backupFromFilesystem(value, location, backend)
|
||||
break
|
||||
|
||||
case LocationFromPrefixes.Filesystem:
|
||||
backupFromFilesystem(value, location, backend)
|
||||
break
|
||||
case LocationFromPrefixes.DockerVolume:
|
||||
backupFromVolume(value, location, backend)
|
||||
break
|
||||
}
|
||||
|
||||
case LocationFromPrefixes.DockerVolume:
|
||||
backupFromVolume(value, location, backend)
|
||||
break
|
||||
|
||||
}
|
||||
|
||||
writer.done(`${name}${to.blue} : ${'Done ✓'.green} (${delta.finished(true)})`)
|
||||
} catch (e) {
|
||||
writer.done(`${name}${to.blue} : ${'Failed!'.red} (${delta.finished(true)}) ${e.message}`)
|
||||
}
|
||||
writer.done(`${name}${to.blue} : ${'Done ✓'.green} (${delta.finished(true)})`)
|
||||
} catch (e) {
|
||||
writer.done(`${name}${to.blue} : ${'Failed!'.red} (${delta.finished(true)}) ${e.message}`)
|
||||
}
|
||||
}
|
||||
|
||||
export const backupLocation = (name: string, location: Location) => {
|
||||
const display = name.yellow + ' ▶ '
|
||||
const filler = fill(name.length + 3)
|
||||
let first = true
|
||||
const display = name.yellow + ' ▶ '
|
||||
const filler = fill(name.length + 3)
|
||||
let first = true
|
||||
|
||||
if (location.hooks && location.hooks.before)
|
||||
for (const command of makeArrayIfIsNot(location.hooks.before)) {
|
||||
const cmd = execPlain(command, {})
|
||||
console.log(cmd.out, cmd.err)
|
||||
}
|
||||
if (location.hooks && location.hooks.before)
|
||||
for (const command of makeArrayIfIsNot(location.hooks.before)) {
|
||||
const cmd = execPlain(command, {})
|
||||
console.log(cmd.out, cmd.err)
|
||||
}
|
||||
|
||||
for (const t of makeArrayIfIsNot(location.to)) {
|
||||
backupSingle(first ? display : filler, t, location)
|
||||
if (first) first = false
|
||||
}
|
||||
for (const t of makeArrayIfIsNot(location.to)) {
|
||||
backupSingle(first ? display : filler, t, location)
|
||||
if (first) first = false
|
||||
}
|
||||
|
||||
if (location.hooks && location.hooks.after)
|
||||
for (const command of makeArrayIfIsNot(location.hooks.after)) {
|
||||
const cmd = execPlain(command)
|
||||
console.log(cmd.out, cmd.err)
|
||||
}
|
||||
if (location.hooks && location.hooks.after)
|
||||
for (const command of makeArrayIfIsNot(location.hooks.after)) {
|
||||
const cmd = execPlain(command)
|
||||
console.log(cmd.out, cmd.err)
|
||||
}
|
||||
}
|
||||
|
||||
export const backupAll = (locations?: Locations) => {
|
||||
if (!locations)
|
||||
locations = config.locations
|
||||
if (!locations) locations = config.locations
|
||||
|
||||
console.log('\nBacking Up'.underline.grey)
|
||||
for (const [name, location] of Object.entries(locations))
|
||||
backupLocation(name, location)
|
||||
console.log('\nBacking Up'.underline.grey)
|
||||
for (const [name, location] of Object.entries(locations)) backupLocation(name, location)
|
||||
}
|
||||
|
Reference in New Issue
Block a user