|
|
@ -0,0 +1,72 @@ |
|
|
|
|
|
#!/usr/bin/env python |
|
|
|
|
|
import json |
|
|
|
|
|
import tempfile |
|
|
|
|
|
import subprocess |
|
|
|
|
|
import datetime |
|
|
|
|
|
from pathlib import Path |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_last_boot(): |
|
|
|
|
|
with subprocess.Popen( |
|
|
|
|
|
["journalctl", "--list-boots"], stdout=subprocess.PIPE |
|
|
|
|
|
) as proc: |
|
|
|
|
|
for line in proc.stdout.read().decode().split("\n"): |
|
|
|
|
|
info, end_time = line.split(chr(8212)) |
|
|
|
|
|
info = list(filter(bool, info.split(" "))) |
|
|
|
|
|
bootnum = info[0] |
|
|
|
|
|
if bootnum == "0": |
|
|
|
|
|
start_date_string = " ".join(info[3:5]) |
|
|
|
|
|
return datetime.datetime.fromisoformat(start_date_string).replace( |
|
|
|
|
|
tzinfo=datetime.timezone.utc |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_snapshot__after_datetime(start: datetime.datetime): |
|
|
|
|
|
with subprocess.Popen( |
|
|
|
|
|
["snapper", "--utc", "--iso", "--jsonout", "list", "-t", "pre-post"], |
|
|
|
|
|
stdout=subprocess.PIPE, |
|
|
|
|
|
) as proc: |
|
|
|
|
|
if proc.wait() != 0: |
|
|
|
|
|
raise PermissionError("Snapper needs root privileges to read snapshots") |
|
|
|
|
|
data = json.loads(proc.stdout.read().decode()) |
|
|
|
|
|
# ten years |
|
|
|
|
|
td = 3153600000 |
|
|
|
|
|
ret = None |
|
|
|
|
|
for snapshot in data["root"]: |
|
|
|
|
|
snapshot_date = datetime.datetime.fromisoformat(snapshot["date"]).replace( |
|
|
|
|
|
tzinfo=datetime.timezone.utc |
|
|
|
|
|
) |
|
|
|
|
|
d = (snapshot_date - start).total_seconds() |
|
|
|
|
|
if 0 < d < td: |
|
|
|
|
|
td = d |
|
|
|
|
|
ret = snapshot |
|
|
|
|
|
return ret |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_snapshot_path(snapshot): |
|
|
|
|
|
return ( |
|
|
|
|
|
Path(snapshot["subvolume"]) |
|
|
|
|
|
/ ".snapshots" |
|
|
|
|
|
/ Path(str(snapshot["number"])) |
|
|
|
|
|
/ "snapshot" |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def write_pacman_output(path): |
|
|
|
|
|
out_file = tempfile.NamedTemporaryFile("wt") |
|
|
|
|
|
proc = subprocess.Popen(["pacman", "-Q", "--dbpath", str(path)], stdout=out_file) |
|
|
|
|
|
proc.wait() |
|
|
|
|
|
return out_file |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def diff_tempfiles(old, new): |
|
|
|
|
|
subprocess.Popen(["diff", old.name, new.name, "--color=always", "--minimal"]) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
|
|
|
snapshot_data = get_snapshot__after_datetime(get_last_boot()) |
|
|
|
|
|
snapshot_root = get_snapshot_path(snapshot_data) |
|
|
|
|
|
db_root = "var/lib/pacman" |
|
|
|
|
|
old = write_pacman_output(snapshot_root / db_root) |
|
|
|
|
|
new = write_pacman_output(Path(snapshot_data["subvolume"]) / db_root) |
|
|
|
|
|
diff_tempfiles(old, new) |