Skip to content

[BUG] When source tree contains a directory symlink, the directory is randomly packaged either as the original or symlink path #4937

Open
@mgorny

Description

@mgorny

setuptools version

78.1.0

Python version

3.13.2

OS

Gentoo Linux amd64

Additional environment information

No response

Description

When the source tree contains a directory symlink such as b -> a, then setuptools randomly includes the directory as either a or b (and no symlink). The actual result seems to depend on the filesystem order: if the symlink is created first, then the original directory (i.e. a) is included in the sdist. However, if the symlink is created after the directory, the directory is included as b instead of a.

Expected behavior

I expected the original directory to be preserved in the source distribution at its original location. I don't have a hard opinion whether the symlink should be replaced by a copy of the directory, or be ignored — but it definitely shouldn't cause the original directory to disappear.

How to Reproduce

cat > pyproject.toml <<EOF
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

[project]
name = "test"
version = "0"
EOF
echo "graft foo" > MANIFEST.in
mkdir -p foo/a
touch foo/a/{a,b,c}
ln -s a foo/b
python -m build -s
tar -tf dist/test-0.tar.gz

Output

$ python -m build -s
* Creating isolated environment: venv+pip...
* Installing packages in isolated environment:
  - setuptools
* Getting build dependencies for sdist...
running egg_info
writing test.egg-info/PKG-INFO
writing dependency_links to test.egg-info/dependency_links.txt
writing top-level names to test.egg-info/top_level.txt
reading manifest file 'test.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'test.egg-info/SOURCES.txt'
* Building sdist...
running sdist
running egg_info
writing test.egg-info/PKG-INFO
writing dependency_links to test.egg-info/dependency_links.txt
writing top-level names to test.egg-info/top_level.txt
reading manifest file 'test.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'test.egg-info/SOURCES.txt'
warning: sdist: standard file not found: should have one of README, README.rst, README.txt, README.md

running check
creating test-0
creating test-0/foo/b
creating test-0/test.egg-info
copying files to test-0...
copying MANIFEST.in -> test-0
copying pyproject.toml -> test-0
copying foo/b/a -> test-0/foo/b
copying foo/b/b -> test-0/foo/b
copying foo/b/c -> test-0/foo/b
copying test.egg-info/PKG-INFO -> test-0/test.egg-info
copying test.egg-info/SOURCES.txt -> test-0/test.egg-info
copying test.egg-info/dependency_links.txt -> test-0/test.egg-info
copying test.egg-info/top_level.txt -> test-0/test.egg-info
copying test.egg-info/SOURCES.txt -> test-0/test.egg-info
Writing test-0/setup.cfg
Creating tar archive
removing 'test-0' (and everything under it)
Successfully built test-0.tar.gz
$ tar -tf dist/test-0.tar.gz 
test-0/
test-0/MANIFEST.in
test-0/PKG-INFO
test-0/foo/
test-0/foo/b/
test-0/foo/b/a
test-0/foo/b/b
test-0/foo/b/c
test-0/pyproject.toml
test-0/setup.cfg
test-0/test.egg-info/
test-0/test.egg-info/PKG-INFO
test-0/test.egg-info/SOURCES.txt
test-0/test.egg-info/dependency_links.txt
test-0/test.egg-info/top_level.txt

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs TriageIssues that need to be evaluated for severity and status.bug

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions