fix(parity): init delete_suppressed; gate deleted-path retention

- Initialize PipelineContextSender.delete_suppressed=false: an uninitialized
  true silently skipped the --delete keep-set manifest under -m/--threads,
  so destination extras were never removed.
- Allocate/install the receiver deleted-path observer only when
  report_deletes is set (--info=del / -i / --out-format under --delete), cap
  the retained list at MAX_MANIFEST_ENTRIES, and free already-created lists
  on the receiver-pipeline create failure path.
- Validate report_deletes/report_stats/report_dest_info on receive.
- Correct stale comments (config.h report_deletes, delete_plan.h deleted
  count, multiprocessing.h stats locking, utils.h observer placement).
- Tests: sender delete_suppressed init, report_deletes gating (unit), and
  -m/--delete default delete-after keep-set removal (integration).
This commit is contained in:
2026-09-18 21:56:44 +02:00
parent a960391b34
commit a5d45ef266
10 changed files with 130 additions and 20 deletions
+15 -3
View File
@@ -47,9 +47,15 @@ PipelineContextReceiver* pipeline_context_receiver_create(Config* config, Queue*
context->would_delete = array_list_create(free);
if (!context->would_delete)
goto fail;
context->deleted_paths = array_list_create(free);
if (!context->deleted_paths)
goto fail;
/* The actually-removed path list is only needed to render rsync's
`deleting PATH` lines, which the client requests via report_deletes
(--info=del / -i / --out-format under --delete). A plain --delete run must
not allocate it or observe every removal. */
if (config->report_deletes) {
context->deleted_paths = array_list_create(free);
if (!context->deleted_paths)
goto fail;
}
return context;
fail:
@@ -60,6 +66,12 @@ fail:
cnd_destroy(&context->condition_not_full);
if (init >= 1)
mtx_destroy(&context->mutex);
/* Free every list that was already created before the failing allocation:
`context` itself is freed below, so they would otherwise leak. */
if (context->would_delete)
array_list_delete(context->would_delete);
if (context->deleted_paths)
array_list_delete(context->deleted_paths);
free(context);
return NULL;
}