Document Python/external-rsync backend differences (#20)

* Document Python/external-rsync backend differences

- Note that mixing --external-rsync (which can recreate device/socket
  entries via --archive's -D) with the default Python hardlink-forward
  step is unsafe: _recursive_hardlink() only understands files,
  symlinks, and directories and errors on anything else.
- Note that --dry-run is I/O-free with --external-rsync but still
  fully copies into a throwaway staging directory with the Python
  backend, though neither leaves a lasting change.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* Clarify external-rsync dry-run description

Copilot review feedback on PR #20: rsync's --dry-run still reads and
stats source files to compute what would change, it just avoids
writing to the destination - "performs no I/O" overstated that.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

---------

Co-authored-by: Maxim Shulga <maxim.shulga@alludo.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
authored and GitHub committed 2026-08-06 17:20:47 +00:00
1 parent 87cdb5cadb
commit 4a4797e959
2 files changed
+17 -1

No files matched your search

+1 -1
View File
@@ -141,7 +141,7 @@ Acceptance criteria:
- [x] Document behavior for ACLs, xattrs, flags, sparse files, source hardlinks,
ownership, permissions, and timestamps.
- [x] Add an explicit one-filesystem policy.
- [ ] Make Python and external implementations provide equivalent guarantees or
- [x] Make Python and external implementations provide equivalent guarantees or
document every difference.
- [ ] Test supported behavior on Linux and macOS.
+16
View File
@@ -223,6 +223,22 @@ backups/
root.** In the Python backend a failed `chown` is caught and logged,
not fatal; with `--external-rsync`, rsync itself just skips
ownership it isn't permitted to set.
- **Do not mix backends across runs of the same backup.** The default
Python backend excludes special entries (see above) and its default
hardlink-forward step only understands files, symlinks, and
directories - it raises an error on anything else. `--external-rsync`
can recreate device nodes and sockets (as `root`, via `--archive`'s
`-D`), so a snapshot it created can contain entries the Python
backend's hardlinker cannot carry forward into the next backup. Pick
one of `--external-rsync`/`--external-hardlink` or the Python
defaults and use it consistently for a given backup destination.
- **`--dry-run` behaves differently per backend, though neither leaves
a lasting change.** With `--external-rsync`, rsync itself avoids
writing to the destination (it still reads and stats files to
compute what would change). With the Python backend, files are still
fully copied into a throwaway staging directory, which is then
deleted - correct, but slower and more I/O-heavy than the external
backend's dry run.
## Development