diff --git a/src/baudolo/backup/app.py b/src/baudolo/backup/app.py index 2829a52..c613793 100644 --- a/src/baudolo/backup/app.py +++ b/src/baudolo/backup/app.py @@ -226,19 +226,19 @@ def main() -> int: if args.everything: # "everything": always do pre-rsync, then stop + rsync again stoppable = filter_stoppable(containers) - backup_volume(versions_dir, volume_name, vol_dir) + backup_volume(versions_dir, volume_name, vol_dir, authoritative=False) change_containers_status(stoppable, "stop") - backup_volume(versions_dir, volume_name, vol_dir) + backup_volume(versions_dir, volume_name, vol_dir, authoritative=True) if not args.shutdown: change_containers_status(stoppable, "start") continue # default: rsync, and if needed stop + rsync - backup_volume(versions_dir, volume_name, vol_dir) + backup_volume(versions_dir, volume_name, vol_dir, authoritative=False) if requires_stop(containers, args.images_no_stop_required): stoppable = filter_stoppable(containers) change_containers_status(stoppable, "stop") - backup_volume(versions_dir, volume_name, vol_dir) + backup_volume(versions_dir, volume_name, vol_dir, authoritative=True) if not args.shutdown: change_containers_status(stoppable, "start") diff --git a/src/baudolo/backup/volume.py b/src/baudolo/backup/volume.py index 12fa8ea..ae2fc8a 100644 --- a/src/baudolo/backup/volume.py +++ b/src/baudolo/backup/volume.py @@ -24,16 +24,26 @@ def get_last_backup_dir( return None -def backup_volume(versions_dir: str, volume_name: str, volume_dir: str) -> None: - """Perform incremental file backup of a Docker volume.""" +def backup_volume( + versions_dir: str, volume_name: str, volume_dir: str, *, authoritative: bool +) -> None: + """Perform incremental file backup of a Docker volume. + + Args: + authoritative: compare source and destination by content instead of by + size and whole-second mtime. Required on a pass whose destination was + already written from a live source, where a file can differ while + both attributes still agree. + """ dest = os.path.join(volume_dir, "files") + "/" pathlib.Path(dest).mkdir(parents=True, exist_ok=True) last = get_last_backup_dir(versions_dir, volume_name, dest) link_dest = f"--link-dest='{last}'" if last else "" source = get_storage_path(volume_name) + verify = "--checksum " if authoritative else "" - cmd = f"rsync -abP --delete --delete-excluded {link_dest} {source} {dest}" + cmd = f"rsync -abP --delete --delete-excluded {verify}{link_dest} {source} {dest}" try: execute_shell_command(cmd)