Files
bongo/contrib/testing/store-backup-compare.py
T
2026-07-23 15:22:14 +02:00

69 lines
2.1 KiB
Python
Executable File

#!/usr/bin/env python3
"""Compare two Bongo PAX backups while ignoring generated timestamps."""
from __future__ import annotations
import argparse
import hashlib
import tarfile
GENERATED_TIMESTAMP_PROPERTIES = {
"BONGO.nmap.created",
"BONGO.nmap.lastmodified",
}
def read_archive(path):
result = {}
with tarfile.open(path, "r:*") as archive:
for member in archive.getmembers():
payload = b""
if member.isfile():
source = archive.extractfile(member)
if source is None:
raise ValueError("cannot read %s from %s" % (
member.name, path))
payload = source.read()
metadata = {
key: value for key, value in member.pax_headers.items()
if key not in GENERATED_TIMESTAMP_PROPERTIES
}
result[member.name] = (
member.isdir(), member.isfile(), member.size, member.mtime,
hashlib.sha256(payload).hexdigest(), metadata)
return result
def main():
parser = argparse.ArgumentParser()
parser.add_argument("source", help="backup made before restore")
parser.add_argument("restored", help="backup made after restore")
args = parser.parse_args()
source = read_archive(args.source)
restored = read_archive(args.restored)
if source != restored:
missing = sorted(set(source) - set(restored))
extra = sorted(set(restored) - set(source))
changed = sorted(
name for name in set(source) & set(restored)
if source[name] != restored[name])
if missing:
print("Missing:", ", ".join(missing))
if extra:
print("Extra:", ", ".join(extra))
if changed:
print("Changed:", ", ".join(changed))
return 1
file_count = sum(1 for item in source.values() if item[1])
directory_count = sum(1 for item in source.values() if item[0])
print("PASS: %d files and %d collections are equivalent" % (
file_count, directory_count))
return 0
if __name__ == "__main__":
raise SystemExit(main())