#!/usr/bin/env nodejs function string_coin( template, arguments_ ) { let result = template; Object.entries(arguments_).forEach( ([key, value]) => { result = result.replace(new RegExp("{{" + key + "}}", "g"), value); } ); return result; } function borg_init( repository_directory, { "encryption": encryption = "none", } = { } ) { return string_coin( "borg init --encryption={{encryption}} {{repository_directory}}\n", { "repository_directory": repository_directory, "encryption": encryption, } ); } function borg_create( repository_directory, archive_name, directories, { "compression": compression = "none", } = { } ) { return string_coin( "borg create --compression={{compression}} {{repository_directory}}::{{archive_name}} {{directories}}\n", { "repository_directory": repository_directory, "archive_name": archive_name, "compression": compression, "directories": directories.join(" "), } ) } function borg_prune( repository_directory, age, { "keep_weekly": keep_weekly = null, "keep_yearly": keep_yearly = null, } = { } ) { return string_coin( "borg prune --keep-within=2w{{macro_keep_weekly}}{{macro_keep_yearly}} {{repository_directory}}\n", { "repository_directory": repository_directory, "keep_within": age, "macro_keep_weekly": ((keep_weekly === null) ? "" : string_coin(" --keep-weekly={{x}}", {"x": keep_weekly.toFixed(0)})), "macro_keep_yearly": ((keep_yearly === null) ? "" : string_coin(" --keep-yearly={{x}}", {"x": keep_yearly.toFixed(0)})), } ) } function get_conf( ) { const _fs = require("fs"); const conf = JSON.parse(_fs.readFileSync("conf.json")); return conf; } function get_stamp( ) { const date = (new Date(Date.now())); return string_coin( "{{year}}{{month}}{{day}}", { "year": date.getFullYear().toFixed(0).padStart(4, "0"), "month": (date.getMonth()+1).toFixed(0).padStart(2, "0"), "day": date.getDate().toFixed(0).padStart(2, "0"), } ); } function get_repository_directory( conf ) { return conf.target.data.repository; } function init( conf ) { const repository_directory = get_repository_directory(conf); if (false) { process.stdout.write( string_coin( "mkdir --parents {{repository_directory}}\n", { "repository_directory": repository_directory, } ) ); } process.stdout.write( borg_init( repository_directory, { "encryption": "none", } ) ); } function run( conf, stamp ) { const repository_directory = get_repository_directory(conf); conf.concerns.forEach( concern => { process.stdout.write( string_coin( "## {{name}}\n", { "name": concern.name, } ) ); process.stdout.write( borg_create( repository_directory, string_coin( "{{concern_name}}-{{stamp}}", { "concern_name": concern.name, "stamp": stamp, } ), [concern.source_directory], { "compression": conf.target.data.compression, } ) ); process.stdout.write( borg_prune( repository_directory, "2w", { "keep_weekly": 7, "keep_yearly": 2, } ) ); process.stdout.write( "\n" ); } ); } function main( args ) { // args const action = (args.shift() ?? "run"); // exec switch (action) { case "init": { const conf = get_conf(); init(conf); break; } case "run": { const conf = get_conf(); const stamp = get_stamp(); run(conf, stamp); break; } default: { throw (new Error("unhandled action: " + action)); break; } } } main(process.argv.slice(2));