Commit Graph
21 Commits
Author SHA1 Message Date
Fuxino 4ac8b64085 Test whole remote backups through a fake ssh command
Real rsync runs over fake ssh and sshpass scripts that execute the remote side locally, covering --link-dest, removal, key file, password and --remote-sudo without a server.
2026-10-21 22:48:35 +02:00
Fuxino 59a3f94ec8 Log verbose rsync output one line per message
With -v, the whole output was logged as a single Python list.
2026-10-21 22:41:29 +02:00
Fuxino 408beefc66 Keep only rsync's summary lines when not verbose
Every output line was kept in memory although only the last two were logged, and fewer than two lines (e.g. with --rsync-options q) raised an IndexError.
2026-10-21 22:40:17 +02:00
Fuxino b54f7e1817 Exit with simple_backup()'s return code when run as a script 2026-10-21 22:37:55 +02:00
Fuxino 9e6aadf7d3 Find rsync in PATH and pass the SSH password only to rsync
A missing /usr/bin/rsync ended in a traceback, possibly after --remove-before-backup had removed old backups, and left SSHPASS in the environment.
2026-10-21 22:36:03 +02:00
Fuxino ac59969d82 Catch all OS errors when removing old local backups
Errors other than a missing directory or denied permission (e.g. read-only filesystem, device busy) ended in a traceback after the backup.
2026-10-21 22:32:50 +02:00
Fuxino dc50ef1b07 Read ~/.ssh/config in the SSH pre-check
The paramiko pre-check ignored HostName, Port and IdentityFile, so hosts that rsync's ssh reached through ~/.ssh/config failed before the backup started.
2026-10-21 22:31:01 +02:00
Fuxino fa3ba2a6bd Make inputs and backup_dir optional in the config file
They can come from -i and -o; missing ones were rejected as a bad configuration file (exit code 6).
2026-10-21 22:26:55 +02:00
Fuxino e8b088f13e Use existing config inputs as is instead of globbing them
Paths containing glob characters, such as 'Photos [2020]', matched nothing and were skipped.
2026-10-21 22:23:22 +02:00
Fuxino 535f7a33fe Reject keep values below -1
A keep below -1 made remove_old_backups() delete every backup, including the new one, and then crash.
2026-10-21 22:16:47 +02:00
Fuxino 17c104c6c8 Add ruff linting
Configure ruff in pyproject.toml and apply its fixes: modern annotations
(X | None, builtin generics, collections.abc), sorted imports, explicit
stacklevel in test warnings.
2026-10-16 13:47:24 +02:00
Fuxino 8a479a8455 Base the progress bar on file counts
With --link-dest unchanged files are linked, not copied, so rsync's byte
percentage stayed near zero and the ETA was hours. Use the checked/total
file counts instead, and show no percentage or ETA while still scanning.
2026-10-15 20:32:44 +02:00
Fuxino 7cd90f8d11 Add a progress bar for rsync
On a terminal, run rsync with --info=progress2 and draw its updates as a
progress bar on stderr. The ETA is estimated locally, since rsync reports
the elapsed time when a file finishes. Disable it with --no-progress.
2026-10-14 09:46:50 +02:00
Fuxino d0fb5b65fb Read rsync output while it runs
Read the output as it arrives, split on newlines and carriage returns,
instead of all at once with communicate(). This is needed for the
progress bar. Invalid UTF-8 in the output is replaced instead of raising.
2026-10-14 09:42:37 +02:00
Fuxino a3ace84c8b Log each old backup as it is removed
Removing old backups can take minutes on a slow drive; logging each one with
its position (e.g. "(1/3)") shows that the backup is still progressing.
2026-10-14 09:40:35 +02:00
Fuxino 0829c33053 Fix mypy errors in simple_backup() and Backup
Accept None for the missing inputs, output, exclude and keep values and replace them with their defaults in __init__, and annotate the SSH client, which mypy typed as None and so skipped checking the remote code.
2026-10-14 08:37:06 +02:00
Fuxino cfe3b28436 Fix mypy errors in the tests
The config values are now a TypedDict, so check inputs for None before sorting, use literal keys and use ConfigArgs as the fake _read_config() return type.
2026-10-14 08:37:06 +02:00
Fuxino 8d08032b5d Add tests for remote backups
Use a fake SSH client that runs commands locally to test remote path resolution, removing old backups, finding the last backup and the rsync arguments, plus the login paths with a fake paramiko client and real keys made by ssh-keygen.
2026-10-14 08:23:25 +02:00
Fuxino 28ecff2306 Add tests for local backups
Run real rsync into a temp dir to test hard links, keep, remove-before-backup, stray files in the backup dir and the old folder name format, and use a fake Popen to test how rsync return codes are handled.
2026-10-14 08:15:07 +02:00
Fuxino dbb0aadc84 Add tests for command line handling and user detection
Test how command line and config values are combined, the exit codes for an incomplete SSH setup and a bad config, and the user detection under sudo/doas (simulated by patching geteuid and the environment).
2026-10-14 08:10:02 +02:00
Fuxino 41a45dad41 Add pytest setup and configuration tests
Configure pytest in pyproject.toml to import the repo copy, add a conftest that keeps tests out of the journal and desktop notifications, and test reading the config file and expanding paths.
2026-10-14 08:05:30 +02:00