mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-06-08 06:05:57 -04:00
Set each attribute distinctively on a file AND a directory at every level of a
>=3-deep tree and verify it per entry after transfer (metadata is applied as a
single-component op on an entry whose parent chain the resolver restructure
rewrites):
metadata-depth -p preserves exact file/dir modes; -t preserves file
mtimes; --chmod=D710,F600 rewrites them.
omit-times -O omits directory times (files still preserved); -J omits
symlink times.
sparse -S preserves a deep file's hole (allocated << size);
--no-sparse fills it.
xattrs-depth -X reproduces a user xattr on every entry (gated on xattr
support).
acls-depth -A reproduces a POSIX ACL on every entry (gated on ACL
support + setfacl/getfacl).
ownership-depth --groupmap and --chown=:GROUP remap the group of every
entry (non-root, to a secondary group); -o/--usermap gated
on root.
All green on master and under --protocol=29/30.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
58 lines
1.9 KiB
Python
58 lines
1.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Coverage of -p (perms), -t (times) and --chmod at depth.
|
|
|
|
Each attribute is set distinctively on a file AND a directory at every level of
|
|
a >=3-deep tree, then checked per entry after the transfer -- the metadata is
|
|
applied as a single-component operation on an entry whose parent chain the
|
|
resolver restructure rewrites, so it must be verified deep, not just at the
|
|
root.
|
|
"""
|
|
|
|
import os
|
|
|
|
from rsyncfns import (
|
|
FROMDIR, TODIR,
|
|
assert_mode, assert_mtime_close, make_tree, rmtree, run_rsync, test_fail,
|
|
walk_dirs, walk_files,
|
|
)
|
|
|
|
src = FROMDIR
|
|
FILE_MODE = 0o640
|
|
DIR_MODE = 0o750
|
|
BASE_MTIME = 1_400_000_000 # a fixed, clearly-old timestamp
|
|
|
|
|
|
def seed():
|
|
rmtree(src)
|
|
rmtree(TODIR)
|
|
make_tree(src, depth=3)
|
|
for i, f in enumerate(walk_files(src)):
|
|
os.chmod(f, FILE_MODE)
|
|
os.utime(f, (BASE_MTIME + i * 100, BASE_MTIME + i * 100))
|
|
for d in walk_dirs(src):
|
|
os.chmod(d, DIR_MODE)
|
|
|
|
|
|
# --- -p preserves exact file and directory modes at every level -------------
|
|
seed()
|
|
run_rsync('-rlpt', f'{src}/', f'{TODIR}/')
|
|
for f in walk_files(src):
|
|
assert_mode(TODIR / f.relative_to(src), FILE_MODE, label=f'-p file {f.name}')
|
|
for d in walk_dirs(src):
|
|
assert_mode(TODIR / d.relative_to(src), DIR_MODE, label=f'-p dir {d.name}')
|
|
|
|
# --- -t preserves file mtimes at every level --------------------------------
|
|
for f in walk_files(src):
|
|
rel = f.relative_to(src)
|
|
assert_mtime_close(TODIR / rel, f.stat().st_mtime, label=f'-t {rel}')
|
|
|
|
# --- --chmod rewrites modes at every level ----------------------------------
|
|
seed()
|
|
run_rsync('-a', '--chmod=D710,F600', f'{src}/', f'{TODIR}/')
|
|
for f in walk_files(src):
|
|
assert_mode(TODIR / f.relative_to(src), 0o600, label=f'--chmod file {f.name}')
|
|
for d in walk_dirs(src):
|
|
assert_mode(TODIR / d.relative_to(src), 0o710, label=f'--chmod dir {d.name}')
|
|
|
|
print("metadata-depth: -p / -t / --chmod verified per entry at depth")
|