Copy regular files and fix symlinks from *src_section* into *dst_section*.
(
src_section: Path,
dst_section: Path,
src_dir: Path,
stats: Stats,
*,
dry_run: bool = False,
)
| 72 | |
| 73 | |
| 74 | def process_section( |
| 75 | src_section: Path, |
| 76 | dst_section: Path, |
| 77 | src_dir: Path, |
| 78 | stats: Stats, |
| 79 | *, |
| 80 | dry_run: bool = False, |
| 81 | ) -> None: |
| 82 | """Copy regular files and fix symlinks from *src_section* into *dst_section*.""" |
| 83 | if not dry_run: |
| 84 | dst_section.mkdir(parents=True, exist_ok=True) |
| 85 | |
| 86 | for entry in sorted(os.scandir(src_section), key=lambda e: e.name): |
| 87 | dst_path = dst_section / entry.name |
| 88 | |
| 89 | # Remove any stale file or symlink at the destination so we |
| 90 | # don't fail trying to write through a broken symlink from a |
| 91 | # previous run. |
| 92 | if not dry_run and (dst_path.is_symlink() or dst_path.exists()): |
| 93 | dst_path.unlink() |
| 94 | |
| 95 | if entry.is_dir(follow_symlinks=False): |
| 96 | logger.debug("skipping nested directory: %s", entry.name) |
| 97 | stats.dirs_skipped += 1 |
| 98 | continue |
| 99 | |
| 100 | if entry.is_symlink(): |
| 101 | raw_target = os.readlink(entry.path) |
| 102 | new_target = _rewrite_target(raw_target, src_dir) |
| 103 | |
| 104 | if new_target is None: |
| 105 | logger.debug( |
| 106 | "skipping broken symlink: %s -> %s", entry.name, raw_target |
| 107 | ) |
| 108 | stats.symlinks_skipped += 1 |
| 109 | continue |
| 110 | |
| 111 | # For same-section links, verify target exists. |
| 112 | if new_target == raw_target and not (src_section / raw_target).exists(): |
| 113 | logger.debug( |
| 114 | "skipping broken symlink: %s -> %s", entry.name, raw_target |
| 115 | ) |
| 116 | stats.symlinks_skipped += 1 |
| 117 | continue |
| 118 | |
| 119 | if not dry_run: |
| 120 | os.symlink(new_target, dst_path) |
| 121 | |
| 122 | if new_target != raw_target: |
| 123 | logger.debug( |
| 124 | "rewriting symlink: %s -> %s (was %s)", |
| 125 | entry.name, |
| 126 | new_target, |
| 127 | raw_target, |
| 128 | ) |
| 129 | stats.symlinks_rewritten += 1 |
| 130 | else: |
| 131 | stats.symlinks_copied += 1 |
no test coverage detected