From 287c1eacacefdffe5421772e6cf166e1ebf5cebf Mon Sep 17 00:00:00 2001 From: Wes Barnett Date: Sat, 13 Mar 2021 07:08:40 -0500 Subject: [PATCH] Add options for important=yes userdata Check if user-specified packages and user-specified commands are in important lists and if so add userdata important=yes Fixes #38. --- extra/snap-pac.ini | 8 ++++++++ scripts/snap_pac.py | 28 ++++++++++++++++++++++++---- tests/test_script.py | 33 ++++++++++++++++++++++++++++++--- 3 files changed, 62 insertions(+), 7 deletions(-) diff --git a/extra/snap-pac.ini b/extra/snap-pac.ini index 7e32a4b..92c9825 100644 --- a/extra/snap-pac.ini +++ b/extra/snap-pac.ini @@ -2,6 +2,7 @@ # Each section corresponds with a snapper configuration. Add additional sections to add # other configurations to be snapshotted. By default, only the root configuration is snapshotted. +# Create a setion named [DEFAULT] to have a setting apply for all snapper configurations [root] # How many characters to limit the description for snapper. @@ -19,6 +20,13 @@ cleanup_algorithm = number # Post snapshot description. Default is the list of packages involved in the pacman transaction #post_description = pacman post snapshot +# Uncomment to add "important=yes" to userdata for snapshots referring to these packages +#important_packages = ["linux"] + +# Uncomment to add "important=yes" to userdata for snapshots that were created with the +#following commands +#important_commands = ["pacman -Syu"] + # Example for another snapper configuration named "home" # [home] # snapshot = True diff --git a/scripts/snap_pac.py b/scripts/snap_pac.py index 6b86dbd..87bbd01 100755 --- a/scripts/snap_pac.py +++ b/scripts/snap_pac.py @@ -18,6 +18,7 @@ from argparse import ArgumentParser from configparser import ConfigParser +import json import logging from pathlib import Path import os @@ -30,7 +31,8 @@ logging.basicConfig(format="%(message)s", level=logging.INFO) class SnapperCmd: - def __init__(self, config, snapshot_type, cleanup_algorithm, description="", nodbus=False, pre_number=None): + def __init__(self, config, snapshot_type, cleanup_algorithm, description="", + nodbus=False, pre_number=None, important=False): self.cmd = ["snapper"] if nodbus: self.cmd.append("--no-dbus") @@ -40,6 +42,8 @@ class SnapperCmd: self.cmd.append("--print-number") if description: self.cmd.append(f"--description \"{description}\"") + if important: + self.cmd.append("--userdata \"important=yes\"") if snapshot_type == "post": if pre_number is not None: self.cmd.append(f"--pre-number {pre_number}") @@ -69,7 +73,7 @@ def setup_config_parser(ini_file, parent_cmd, packages): "snapshot": False, "cleanup_algorithm": "number", "pre_description": parent_cmd, - "post_description": packages, + "post_description": " ".join(packages), "desc_limit": 72 } config["root"] = { @@ -100,13 +104,25 @@ def get_pre_number(snapshot_type, prefile): return pre_number +def check_important_commands(config, snapper_config, parent_cmd): + important_commands = json.loads(config.get(snapper_config, "important_commands")) + return parent_cmd in important_commands + + +def check_important_packages(config, snapper_config, packages): + important_packages = json.loads(config.get(snapper_config, "important_packages")) + print(important_packages) + print(packages) + return any(x in important_packages for x in packages) + + def main(snap_pac_ini, snapper_conf_file, args): if os.getenv("SNAP_PAC_SKIP", "n").lower() in ["y", "yes", "true", "1"]: return False parent_cmd = os.popen(f"ps -p {os.getppid()} -o args=").read().strip() - packages = " ".join([line.rstrip("\n") for line in sys.stdin]) + packages = [line.rstrip("\n") for line in sys.stdin] config = setup_config_parser(snap_pac_ini, parent_cmd, packages) snapper_configs = get_snapper_configs(snapper_conf_file) chroot = os.stat("/") != os.stat("/proc/1/root/.") @@ -123,7 +139,11 @@ def main(snap_pac_ini, snapper_conf_file, args): description = get_description(args.type, config, snapper_config) pre_number = get_pre_number(args.type, prefile) - snapper_cmd = SnapperCmd(snapper_config, args.type, cleanup_algorithm, description, chroot, pre_number) + important = (check_important_commands(config, snapper_config, parent_cmd) or + check_important_packages(config, snapper_config, packages)) + + snapper_cmd = SnapperCmd(snapper_config, args.type, cleanup_algorithm, + description, chroot, pre_number, important) num = snapper_cmd() logging.info(f"==> {snapper_config}: {num}") diff --git a/tests/test_script.py b/tests/test_script.py index a629e0f..2cafe39 100644 --- a/tests/test_script.py +++ b/tests/test_script.py @@ -6,8 +6,8 @@ import os import pytest from scripts.snap_pac import ( - SnapperCmd, get_pre_number, get_snapper_configs, main, setup_config_parser, - get_description + SnapperCmd, check_important_commands, check_important_packages, get_pre_number, get_snapper_configs, + main, setup_config_parser, get_description ) @@ -54,6 +54,11 @@ def prefile(): SnapperCmd("root", "post", "number", "bar", True, 1234), "snapper --no-dbus --config root create --type post --cleanup-algorithm number --print-number" " --description \"bar\" --pre-number 1234" + ), + ( + SnapperCmd("root", "post", "number", "bar", False, 1234, True), + "snapper --config root create --type post --cleanup-algorithm number --print-number" + " --description \"bar\" --userdata \"important=yes\" --pre-number 1234" ) ]) def test_snapper_cmd(snapper_cmd, actual_cmd): @@ -84,7 +89,7 @@ def test_setup_config_parser(config): f.write("desc_limit = 3\n") f.write("post_description = a really long description\n") name = f.name - config2 = setup_config_parser(name, "foo", "bar") + config2 = setup_config_parser(name, "foo", ["bar"]) assert config == config2 @@ -104,3 +109,25 @@ def test_no_prefile(): @pytest.mark.parametrize("snapshot_type, description", [("pre", "foo"), ("post", "a r")]) def test_get_description(snapshot_type, description, config): assert get_description(snapshot_type, config, "home") == description + + +def test_important_commands(): + parent_cmd = "pacman -Syu" + with tempfile.NamedTemporaryFile("w", delete=False) as f: + f.write("[DEFAULT]\n") + f.write("important_commands = [\"pacman -Syu\"]\n") + name = f.name + config = setup_config_parser(name, parent_cmd, ["bar"]) + important = check_important_commands(config, "root", parent_cmd) + assert important + + +def test_important_packages(): + packages = ["bar", "linux", "vim"] + with tempfile.NamedTemporaryFile("w", delete=False) as f: + f.write("[DEFAULT]\n") + f.write("important_packages = [\"linux\"]\n") + name = f.name + config = setup_config_parser(name, "pacman -S", packages) + important = check_important_packages(config, "root", packages) + assert important