|
|
|
@@ -4,33 +4,14 @@ import { program } from "commander"
|
|
|
|
|
import { parseJSON, parseTOML, stringifyJSON } from "confbox"
|
|
|
|
|
import fs from "node:fs"
|
|
|
|
|
import path from "node:path"
|
|
|
|
|
import util from 'node:util'
|
|
|
|
|
import strftime from 'strftime'
|
|
|
|
|
import { spawnSync } from "node:child_process"
|
|
|
|
|
|
|
|
|
|
let logfd = 1
|
|
|
|
|
|
|
|
|
|
function logToFile() {
|
|
|
|
|
// Source - https://stackoverflow.com/a
|
|
|
|
|
// Posted by Clément Désiles, modified by community. See post 'Timeline' for change history
|
|
|
|
|
// Retrieved 2026-01-14, License - CC BY-SA 3.0
|
|
|
|
|
|
|
|
|
|
logfd = fs.openSync('/etc/snapback/log.txt','w')
|
|
|
|
|
const logFile = fs.createWriteStream('', { 'fd':logfd });
|
|
|
|
|
const logStdout = process.stdout;
|
|
|
|
|
|
|
|
|
|
console.log = function (...args) {
|
|
|
|
|
logFile.write(util.format.apply(null, args) + '\n');
|
|
|
|
|
logStdout.write(util.format.apply(null, args) + '\n');
|
|
|
|
|
}
|
|
|
|
|
console.error = console.log;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let config: { [key: string]: string|undefined } = {}
|
|
|
|
|
let index: { [key: string]: { [key: string]: string|undefined }|undefined } = {}
|
|
|
|
|
|
|
|
|
|
function sugoiSpawn(...command: string[]) {
|
|
|
|
|
const result = spawnSync(command.shift()!, command, { stdio: ['ignore',logfd,logfd] })
|
|
|
|
|
const result = spawnSync(command.shift()!, command, { stdio: 'inherit' })
|
|
|
|
|
if (result.error) throw result.error
|
|
|
|
|
if (result.status !== 0) process.exit(result.status)
|
|
|
|
|
return result
|
|
|
|
@@ -75,7 +56,6 @@ program.command('install').description('installs snapback on your system')
|
|
|
|
|
program.command('create-snapshot-post <subvolume> <fstype> <number>')
|
|
|
|
|
.description('create a backup after a snapshot')
|
|
|
|
|
.action(function (subvolume, fstype, number) {
|
|
|
|
|
logToFile()
|
|
|
|
|
if (!config[subvolume]) {console.log(subvolume + ' not configured for snapback'); return}
|
|
|
|
|
const destination = strftime(config[subvolume])
|
|
|
|
|
const dirname = path.dirname(destination)
|
|
|
|
@@ -93,7 +73,6 @@ program.command('create-snapshot-post <subvolume> <fstype> <number>')
|
|
|
|
|
program.command('delete-snapshot-post <subvolume> <fstype> <number>')
|
|
|
|
|
.description('delete a backup after deleting a snapshot')
|
|
|
|
|
.action(function (subvolume, fstype, number) {
|
|
|
|
|
logToFile()
|
|
|
|
|
if (!index[subvolume]) {
|
|
|
|
|
console.log('no backups indexed for ' + subvolume)
|
|
|
|
|
return
|
|
|
|
@@ -108,20 +87,6 @@ program.command('delete-snapshot-post <subvolume> <fstype> <number>')
|
|
|
|
|
console.log('deleted backup at '+destination)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
program.command('delete-config-post <subvolume> <fstype>')
|
|
|
|
|
.description('delete metadata of deleted subvolume, retaining backups')
|
|
|
|
|
.action(function (subvolume, fstype) {
|
|
|
|
|
logToFile()
|
|
|
|
|
delete index[subvolume]
|
|
|
|
|
if (!config[subvolume]) {
|
|
|
|
|
console.log(subvolume + ' not configured for snapback')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
const destination = strftime(config[subvolume])
|
|
|
|
|
const dirname = path.dirname(destination)
|
|
|
|
|
console.log('existing backups remain at '+dirname)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
program.parse()
|
|
|
|
|
|
|
|
|
|
if (Object.keys(index).length) fs.writeFileSync(program.opts().indexFile,stringifyJSON(index), 'utf8')
|
|
|
|
|
fs.writeFileSync(program.opts().indexFile,stringifyJSON(index), 'utf8')
|