feat(delete): per-directory delete plans for --delete-during/--delete-delay (protocol 2.24.0)
Stream one delete plan per source directory from sender to receiver instead of a single whole-tree keep-set manifest: - --delete-during applies each directory's extras as its plan arrives, before that directory's data (rsync's generator-order deletion). - --delete-delay snapshots each directory's extras while the plan arrives and commits the removals only after a fully-successful transfer, so files created after the scan survive (matching rsync's delete-delay, not delete-after). - Type conflicts (a destination file blocking a source directory, or vice versa) are cleared immediately in both modes, so the nested write succeeds. The plan carries the destination-relative directory, its kept child directory names and its kept child file names; the first frame also carries the global protected prefixes, size-skipped prefixes and --delete-missing-args paths. --delete-before keeps the existing whole-tree early manifest; plain --delete and --delete-after keep the end-of-transfer manifest commit. Preserves the existing safety surface: protected/size-skipped prefixes and the --delay-updates/basis skips are honored at any depth, deletion is scoped to the synchronized directories (--files-from), MAX_SERVER_DELETE_COUNT and --max-delete (partial + exit 25) are shared across plans, symlinks are never followed, and paths are confined to the receive root.
This commit is contained in:
@@ -139,6 +139,11 @@ DeleteWalkResult delete_extras_limited(const char* dest_root, const ArrayList* m
|
||||
const DeleteSkipEntry* skips, int skip_count,
|
||||
size_t* deleted_out, size_t* skipped_out);
|
||||
bool delete_extras(const char* dest_root, const ArrayList* manifest);
|
||||
/* Open the existing destination directory at `dest_root`, confined to the
|
||||
authorized root with an O_NOFOLLOW component walk (the same confinement the
|
||||
deletion walker uses for its root). Returns a new fd the caller owns, or -1
|
||||
on error (including a destination that does not exist). */
|
||||
int utils_open_authorized_destination(const char* dest_root);
|
||||
bool utils_set_authorized_root(int fd, const char* canonical_path);
|
||||
/* The fd-only compatibility form is fail-closed for path-based operations;
|
||||
* callers should use utils_set_authorized_root with the canonical identity. */
|
||||
|
||||
Reference in New Issue
Block a user