Files
rsync/testsuite/hardlinks-deep_test.py
Andrew Tridgell 0d546ee3b4 testsuite: structure / recursion / link coverage at depth
Cover the structure and link options at >=3 levels and across directories,
asserting each option's specific effect:

  links            -l keeps a symlink, -L dereferences it, -k follows a
                   directory symlink -- all on a symlink several levels deep.
  dirs             -d copies the top layer (file + empty dir) without recursing.
  prune-empty-dirs -m drops empty chains and chains emptied by an exclude,
                   keeps populated ones.
  hardlinks-deep   -H preserves a hard link whose names live in different
                   directories at depth; without -H they become separate inodes.
  delete-deep      --delete removes a deep extraneous file/subtree; the four
                   delete-timing variants agree; --max-delete caps deletions;
                   --existing / --ignore-existing select/skip correctly.
  relative-implied -R mirrors an implied directory's mode at depth;
                   --no-implied-dirs does not (proto 30+).

Green on master and under --protocol=29/30 (the --no-implied-dirs sub-case is
gated to protocol >= 30, where multi-component sender paths are accepted).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 12:31:52 +10:00

37 lines
1.2 KiB
Python

#!/usr/bin/env python3
"""Coverage of -H across directory boundaries.
hardlinks_test.py exercises -H on sibling files at the tree root; this
companion checks that -H preserves a hard link whose two names live in
DIFFERENT directories several levels deep (the cross-directory case the
resolver restructure touches), and that without -H the names become
independent inodes.
"""
from rsyncfns import (
FROMDIR, TODIR,
assert_hardlinked, assert_not_hardlinked, makepath, rmtree, run_rsync,
)
import os
src = FROMDIR
a = os.path.join('a', 'aa', 'orig')
b = os.path.join('b', 'bb', 'hardlink')
rmtree(src)
rmtree(TODIR)
makepath(src / 'a' / 'aa', src / 'b' / 'bb')
(src / a).write_text("shared content across directories\n")
os.link(src / a, src / b) # one inode, two names in different dirs
# -H preserves the cross-directory hard link.
run_rsync('-aH', f'{src}/', f'{TODIR}/')
assert_hardlinked(TODIR / a, TODIR / b, label='-H cross-dir hardlink')
# Without -H the two names are copied as independent files.
rmtree(TODIR)
run_rsync('-a', f'{src}/', f'{TODIR}/')
assert_not_hardlinked(TODIR / a, TODIR / b, label='no -H => separate inodes')
print("hardlinks-deep: -H preserves a cross-directory hard link at depth")