Skip to content

fix: follow symlinks when copying license files - #2607

Open
wolfv wants to merge 6 commits into
mainfrom
claude/github-issue-2575-8a4boq
Open

fix: follow symlinks when copying license files#2607
wolfv wants to merge 6 commits into
mainfrom
claude/github-issue-2575-8a4boq

Conversation

@wolfv

@wolfv wolfv commented Jun 30, 2026

Copy link
Copy Markdown
Member

Summary

This change adds support for dereferencing symlinks when copying license files, ensuring that symlinked licenses are packaged as actual content rather than potentially dangling symlinks.

Key Changes

  • Added dereference_symlinks field to CopyDir struct with a new builder method to enable the behavior
  • Modified the symlink handling logic in CopyDir::run() to skip symlink-specific processing when dereferencing is enabled, allowing the standard file/directory copy logic to follow and materialize symlink targets
  • Updated copy_license_files() in packaging.rs to enable symlink dereferencing for all three license file copy operations (work directory, recipe directory, and source directories)
  • Added comprehensive tests covering:
    • Successful dereferencing of a symlinked file with relative path resolution
    • Error handling for broken symlinks (now surfaces as a clear copy error instead of silently creating a dangling symlink)
  • Updated CHANGELOG.md documenting the fix

Implementation Details

When dereference_symlinks(true) is set, symlinks are no longer copied as symlinks. Instead, the code falls through to the regular file/directory branches which use is_dir() and reflink_or_copy() - both of which follow symlinks. This approach:

  • Materializes symlinked files as real content in the package
  • Handles relative symlinks correctly (e.g., ../LICENSE)
  • Surfaces broken symlinks as clear copy errors rather than silently creating dangling symlinks
  • Works consistently across Unix and Windows platforms

The feature is disabled by default and only enabled for license file copying operations.

https://claude.ai/code/session_01Fcmrv6nQdGYURcZ3vB5vyh

@wolfv wolfv changed the title Follow symlinks when copying license files fix: follow symlinks when copying license files Jun 30, 2026
@wolfv
wolfv requested a review from pavelzw June 30, 2026 12:29
claude added 6 commits June 30, 2026 15:42
When a `license_file` entry matched a symlink, `CopyDir` copied the symlink
verbatim. If the link target was outside the glob-matched set (e.g. a license
symlinked to `../../LICENSE`), the package ended up containing only a dangling
symlink and the actual license content was lost.

Add a `dereference_symlinks` option to `CopyDir` and enable it for license
copying so symlinked licenses are materialized as real content. A broken
symlink can no longer be silently packaged and now surfaces as a clear copy
error.

Fixes #2575

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fcmrv6nQdGYURcZ3vB5vyh
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fcmrv6nQdGYURcZ3vB5vyh
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fcmrv6nQdGYURcZ3vB5vyh
Relying on the OS to follow a symlink during the copy fails on Windows for
relative reparse targets. Resolve the link target ourselves (relative to the
link's parent) and copy from the resolved path so a symlinked license is
materialized as real content on all platforms.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fcmrv6nQdGYURcZ3vB5vyh
Builds a recipe whose license_file is a symlink pointing outside the matched
set and asserts the packaged license is real content, not a dangling symlink.
This covers the packaging wiring that enables symlink dereferencing, which the
copy_dir unit tests do not exercise.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fcmrv6nQdGYURcZ3vB5vyh
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fcmrv6nQdGYURcZ3vB5vyh
@wolfv
wolfv force-pushed the claude/github-issue-2575-8a4boq branch from 52a823f to 0aa53ab Compare June 30, 2026 15:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants