feat: per-attribute preservation flags -p/-t/-o/-g with --no-* negations (protocol 2.22.0)
Split FastSync's single use_metadata bundle into four independent rsync-parity attributes: preserve_perms, preserve_times, preserve_owner, preserve_group. use_metadata is now a derived transport bit (config_derived_use_metadata). CLI: real -p/--perms, -t/--times, -o/--owner, -g/--group plus --no-perms/--no-times/--no-owner/--no-group (short and long) and --no-preserve; -a is now rsync -rlptgoD; --preserve = -pt; -A implies -p; -X does not; --chmod implies -p; --usermap/--groupmap/--chown imply owner/group per side; --incremental/--delta still auto-preserve unless negated. Receiver: per-attribute FileAttrPolicy gating for files, dirs (modes applied at end of transfer), symlinks and specials; rsync -E read-bit rule; new files get source_mode & ~umask sanitized (no group/other write); per-side identity resolution; deferred directory metadata; batch dir-metadata replay; daemon modules without 'client owner = yes' no longer refuse plain -a but force super off (no ownership) with a warning. Wire: PROTOCOL_VERSION 2.21.0 -> 2.22.0 (four appended config bools, golden 653 / 95530566005420798). FileMetadata/chunk/batch framing unchanged. Docs/CHANGELOG/CMake updated to 2.22.0.
This commit is contained in:
@@ -881,9 +881,16 @@ class TestExecutability:
|
||||
assert result.returncode == 0, f"Executability sync failed: {result.stderr[:200]}"
|
||||
received_file = os.path.join(get_dest_received_dir(dest, source), "tool.sh")
|
||||
received_mode = os.stat(received_file).st_mode
|
||||
assert received_mode & 0o111 == 0o111
|
||||
assert received_mode & 0o600 == 0o600
|
||||
assert received_mode & 0o077 == 0o011
|
||||
# rsync -E on a fresh destination: the base is source & ~umask, then the
|
||||
# execute bits are derived from that base's read bits. For a source of
|
||||
# 0751 this is exactly source & ~umask (owner rwx, group r-x, other --x
|
||||
# under the usual 022 umask => group/other bits 0o051, not 0o011).
|
||||
current_umask = os.umask(0)
|
||||
os.umask(current_umask)
|
||||
expected_mode = 0o751 & ~current_umask
|
||||
assert received_mode & 0o777 == expected_mode, (
|
||||
f"expected mode {oct(expected_mode)}, got {oct(received_mode & 0o777)}"
|
||||
)
|
||||
|
||||
|
||||
class TestChmod:
|
||||
|
||||
Reference in New Issue
Block a user