Merge branch 'fix/parity-review-b' into feat/parity-fixes

# Conflicts:
#	src/shared/delete_plan.h
#	tests/integration/test_delete_timing_parity.py
This commit is contained in:
2026-09-18 22:11:02 +02:00
11 changed files with 381 additions and 32 deletions
+1 -1
View File
@@ -72,7 +72,7 @@ static void log_server_rejection(const char* context) {
* continues past an unreadable subdirectory so the readable tree transfers, and
* always reports the partial transfer (exit 23); this only decides whether the
* deletion phase is skipped. Returns true when deletion may proceed. */
static bool ignore_errors_allows_delete(const Config* config, bool had_io_error) {
bool ignore_errors_allows_delete(const Config* config, bool had_io_error) {
return !had_io_error || (config && config->ignore_errors);
}
+6
View File
@@ -23,6 +23,12 @@ void client_set_abort_armed(bool armed);
* config_delete() once the call returns). */
int send_files(Config* config);
int send_files_multithreaded(Config** config);
/* rsync's --ignore-errors deletion gate: with no I/O error during the scan the
* deletion phase always proceeds; with one it is suppressed unless
* `--ignore-errors` was given. Exposed so the decision can be unit-tested
* without a privileged (mode-000) source directory. See client_send.c. */
bool ignore_errors_allows_delete(const Config* config, bool had_io_error);
/* Phase 6 residual-batch (client-only). See client_send.c. */
int write_batch_from_source(const Config* config, const char* batch_path);
int apply_batch_to_dest(const Config* config, const char* batch_path, const char* dest_root);
+4 -4
View File
@@ -77,10 +77,10 @@ int delete_plan_session_receive(DeletePlanSession* session, const Config* config
DeleteCommitResult delete_plan_session_commit(DeletePlanSession* session, const Config* config);
/* True once the shared --max-delete budget stopped part of a deletion. */
bool delete_plan_session_limit_reached(const DeletePlanSession* session);
/* Number of destination entries the session's plans ACTUALLY removed, for the
end-of-transfer stats. A --delete-delay entry only snapshotted for removal
that survives the commit (e.g. a directory refilled before it is removed, so
unlink/rmdir fails with ENOTEMPTY) is not counted. */
/* Number of destination entries the session actually removed, for the
end-of-transfer stats. For --delete-delay this excludes a snapshotted entry
that survived (e.g. a refilled directory that failed ENOTEMPTY), even though
that entry already consumed --max-delete budget at snapshot time. */
size_t delete_plan_session_deleted(const DeletePlanSession* session);
/* Install an observer invoked for every destination-relative path the session
truly removes (including the deferred --delete-delay commit), so the receiver