Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
mgorny opened this issue Apr 3, 2025 · 1 comment
Labels
bug Needs Triage Issues that need to be evaluated for severity and status.

Comments

@mgorny
Copy link
Contributor

mgorny commented Apr 3, 2025

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
@mgorny mgorny added bug Needs Triage Issues that need to be evaluated for severity and status. labels Apr 3, 2025
@webknjaz
Copy link
Member

webknjaz commented Apr 4, 2025

Interesting finding!
I think historically, packaging was moving away from symlinks due to wheels needing to be unpacked into file systems that don't support them. But for sdists, it's always been rather undefined. This allowed people to justify not publishing wheels even — we even did this in ansible-core for a very long time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Needs Triage Issues that need to be evaluated for severity and status.
Projects
None yet
Development

No branches or pull requests

2 participants