~mser/pkg.mser.at

7d1ee7d0db63abbafca2568d8a76718a8be484b0 — cryzed 2 years ago 1b8ed1a
Add arch-thin-backup
A packages/arch-thin-backup/PKGBUILD => packages/arch-thin-backup/PKGBUILD +18 -0
@@ 0,0 1,18 @@
pkgname='local-arch-thin-backup'
pkgver=1
pkgrel=1
arch=('any')
depends=('python' 'lostfiles')
source=('arch-thin-backup' 'arch-thin-backup.service' 'arch-thin-backup.timer')
sha256sums=('bdfa0d7ef21e7345561b65a1bf5568227bcd7f3a9a2f331997011b3d1f21c1fd'
            'a5e3cb518c982efcbb0544fffc106f383bdc103b80414e4396f7a5e5ec05d17c'
            '76294510190bf21b2d21c14cc74b6a7c7b7de48f4089ba850c15b916c43d4556')


package() {
    install -D --mode 755 'arch-thin-backup' --target-directory "$pkgdir/usr/bin"

    etc_systemd_system="$pkgdir/etc/systemd/system"
    install -D --mode 644 'arch-thin-backup.service' --target-directory "$etc_systemd_system"
    install -D --mode 644 'arch-thin-backup.timer' --target-directory "$etc_systemd_system"
}

A packages/arch-thin-backup/arch-thin-backup => packages/arch-thin-backup/arch-thin-backup +72 -0
@@ 0,0 1,72 @@
#!/usr/bin/env python

import argparse
import enum
import os
import pathlib
import subprocess
import sys
import tarfile
from datetime import datetime

APPLICATION_NAME = "arch-thin-backup"


class ExitCode(enum.IntEnum):
    SUCCESS = 0
    FAILURE = 1


def get_argument_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument("--output", "-o")
    parser.add_argument("--no-root", "-n", dest="root", action="store_false")
    return parser


def is_root() -> bool:
    return os.geteuid() == 0


def get_modified_backup_files() -> list[pathlib.Path]:
    process = subprocess.run(["pacman", "-Qii"], capture_output=True, text=True, check=True)
    return [pathlib.Path(line.split(None, 1)[1]) for line in process.stdout.splitlines() if line.startswith("MODIFIED")]


def lostfiles() -> list[pathlib.Path]:
    process = subprocess.run(["lostfiles", "strict"], capture_output=True, text=True, check=True)
    return [pathlib.Path(line) for line in process.stdout.splitlines()]


def get_filename() -> str:
    time_string = datetime.now().isoformat("-", "seconds").replace(":", "-")
    return f"{APPLICATION_NAME}-{time_string}.tar.lzma"


def run(arguments: argparse.Namespace) -> ExitCode:
    if arguments.root and not is_root():
        print("Must be run as root!", file=sys.stderr)
        return ExitCode.FAILURE

    filename = arguments.output or get_filename()
    print("Writing:", repr(filename))
    with tarfile.open(filename, "w:xz") as archive:
        for path in get_modified_backup_files():
            print("Adding:", repr(str(path)))
            archive.add(path)

        for path in lostfiles():
            print("Adding:", repr(str(path)))
            archive.add(path)

    return ExitCode.SUCCESS


def main() -> None:
    parser = get_argument_parser()
    arguments = parser.parse_args()
    parser.exit(run(arguments))


if __name__ == "__main__":
    main()

A packages/arch-thin-backup/arch-thin-backup.service => packages/arch-thin-backup/arch-thin-backup.service +9 -0
@@ 0,0 1,9 @@
[Unit]
Description=Arch Linux thin backup

[Service]
Type=oneshot
ExecStart=arch-thin-backup --output /root/arch-thin-backup.tar.lzma

[Install]
WantedBy=multi-user.target

A packages/arch-thin-backup/arch-thin-backup.timer => packages/arch-thin-backup/arch-thin-backup.timer +9 -0
@@ 0,0 1,9 @@
[Unit]
Description=Arch Linux thin backup daily

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target