diff --git a/src/client/usage.c b/src/client/usage.c
index 51f96d7..c393766 100644
--- a/src/client/usage.c
+++ b/src/client/usage.c
@@ -282,8 +282,8 @@ void print_usage(void) {
printf(" --partial Keep partial files on interrupted transfer\n");
printf(" --partial-dir
Directory for partial files\n");
printf(" -T, --temp-dir Scratch dir for temp files before atomic install.\n");
- printf(" Relative dirs resolve below the destination root; absolute\n");
- printf(" dirs are used as-is (rsync semantics). The dir must\n");
+ printf(" Confined to the receive root: a relative dir resolves below\n");
+ printf(" it and an absolute/traversal dir is rejected. The dir must\n");
printf(" already exist; a different filesystem falls back to a\n");
printf(" non-atomic copy instead of aborting\n");
printf(" --fastsync-server-path \n");
diff --git a/tests/integration/test_output_parity.py b/tests/integration/test_output_parity.py
index 83f54bb..81a4efb 100644
--- a/tests/integration/test_output_parity.py
+++ b/tests/integration/test_output_parity.py
@@ -534,22 +534,10 @@ class TestWireStatsParity:
@requires_rsync
@pytest.mark.ci
- @pytest.mark.parametrize("mt", [
- False,
- pytest.param(
- True,
- marks=pytest.mark.xfail(
- reason="known gap: the --threads dry-run delete path does not "
- "consume the receiver's STATUS_STATS delete list yet, so "
- "`-n --delete` emits no *deleting lines (tracked by the "
- "parity-blockers STATUS_STATS fix)",
- strict=False,
- ),
- ),
- ])
+ @pytest.mark.parametrize("mt", [False, True])
def test_dry_run_delete_lines_match_rsync(self, mt):
"""-n --delete emits transfer-relative `*deleting` lines like rsync
- (single-threaded; the --threads variant is a documented xfail)."""
+ (single-threaded and --threads)."""
source = os.path.join(TEST_DATA_DIR, "wire_del_src")
dest = os.path.join(TEST_DATA_DIR, "wire_del_dst")
rdst = os.path.join(TEST_DATA_DIR, "wire_del_rdst")
diff --git a/tests/integration/test_parity_selection.py b/tests/integration/test_parity_selection.py
index 68e68b7..0d240bd 100644
--- a/tests/integration/test_parity_selection.py
+++ b/tests/integration/test_parity_selection.py
@@ -101,8 +101,15 @@ class TestRelativeGeneral:
fs = os.stat(os.path.join(dest, rel))
assert (rs.st_mode & 0o7777) == (fs.st_mode & 0o7777), \
f"mode mismatch for {rel} with {extra}"
- assert int(rs.st_mtime) == int(fs.st_mtime), \
- f"mtime mismatch for {rel} with {extra}"
+ if extra == ["--no-implied-dirs"]:
+ # The implied parent directory is created at run time (no
+ # metadata applied), so rsync's and FastSync's separate runs
+ # can differ by a second; compare with a tolerance.
+ assert abs(rs.st_mtime - fs.st_mtime) <= 2, \
+ f"mtime mismatch for {rel} with {extra}"
+ else:
+ assert int(rs.st_mtime) == int(fs.st_mtime), \
+ f"mtime mismatch for {rel} with {extra}"
class TestDirsOneLevel: