mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-08-02 00:36:35 -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>
53 lines
1.5 KiB
Python
53 lines
1.5 KiB
Python
#!/usr/bin/env python3
|
|
"""Coverage of -X (xattrs) at depth.
|
|
|
|
xattrs_test.py exercises a shallow tree; this companion sets a distinctive user
|
|
xattr on a file AND a directory at every level of a >=3-deep tree and checks
|
|
that -X reproduces them all (the xattr is applied per entry, on a name whose
|
|
parent chain the resolver restructure rewrites).
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
|
|
from rsyncfns import (
|
|
FROMDIR, TODIR,
|
|
make_tree, rmtree, run_rsync, test_fail, test_skipped,
|
|
walk_dirs, walk_files, xattr_dump, xattr_set, xattrs_supported,
|
|
)
|
|
|
|
if not xattrs_supported():
|
|
test_skipped("rsync built without xattr support (or no xattr tooling here)")
|
|
|
|
src = FROMDIR
|
|
rmtree(src)
|
|
rmtree(TODIR)
|
|
make_tree(src, depth=3)
|
|
|
|
entries = [p.relative_to(src) for p in (walk_dirs(src) + walk_files(src))]
|
|
entries.sort()
|
|
|
|
os.chdir(src)
|
|
try:
|
|
for i, rel in enumerate(entries):
|
|
xattr_set('depth', f'value-{i}-{rel}', str(rel))
|
|
except OSError as e:
|
|
test_skipped(f"unable to set an xattr on this filesystem: {e}")
|
|
|
|
want = xattr_dump(*[str(r) for r in entries])
|
|
|
|
run_rsync('-aX', '-f-x_system.*', '-f-x_security.*', '--super',
|
|
f'{src}/', f'{TODIR}/')
|
|
|
|
os.chdir(TODIR)
|
|
got = xattr_dump(*[str(r) for r in entries])
|
|
|
|
if got != want:
|
|
from difflib import unified_diff
|
|
sys.stdout.write(''.join(unified_diff(
|
|
want.splitlines(keepends=True), got.splitlines(keepends=True),
|
|
fromfile='source', tofile='dest')))
|
|
test_fail("xattrs differ between source and destination at depth")
|
|
|
|
print("xattrs-depth: -X reproduced a user xattr on every entry at depth")
|