Skip to content

Commit 4421322

Browse files
committed
ENH: add support for symbolic links in package repository
Symbolic links are included as regular files in the sdist archive. Only symbolic links pointing to files withing the archive are supported.
1 parent 1c8092d commit 4421322

File tree

10 files changed

+71
-0
lines changed

10 files changed

+71
-0
lines changed

mesonpy/__init__.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import os
2424
import pathlib
2525
import platform
26+
import posixpath
2627
import re
2728
import shutil
2829
import subprocess
@@ -937,6 +938,21 @@ def sdist(self, directory: Path) -> pathlib.Path:
937938

938939
with tarfile.open(meson_dist_path, 'r:gz') as meson_dist, mesonpy._util.create_targz(sdist_path) as sdist:
939940
for member in meson_dist.getmembers():
941+
# Recursively resolve symbolic links. The source distribution
942+
# archive format specification allows for symbolic links as
943+
# long as the target path does not include a '..' component.
944+
# This makes symbolic links support unusable in most cases,
945+
# therefore include the symbolic link targets as regular files
946+
# in all cases.
947+
while member.issym():
948+
target = posixpath.normpath(posixpath.join(posixpath.dirname(member.name), member.linkname))
949+
try:
950+
member = meson_dist.getmember(target).replace(name=member.name)
951+
except KeyError:
952+
# Symbolic link with absolute path target, pointing
953+
# outside the archive, or dangling: ignore.
954+
break
955+
940956
if member.isfile():
941957
file = meson_dist.extractfile(member.name)
942958

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# SPDX-FileCopyrightText: 2025 The meson-python developers
2+
#
3+
# SPDX-License-Identifier: MIT

tests/packages/symlinks/baz.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/__init__.py
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# SPDX-FileCopyrightText: 2021 The meson-python developers
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
project('symlinks', version: '1.0.0')
6+
7+
py = import('python').find_installation()
8+
9+
py.install_sources(
10+
'__init__.py',
11+
'submodule/__init__.py',
12+
'submodule/aaa.py',
13+
'submodule/bbb.py',
14+
subdir: 'symlinks',
15+
preserve_path: true,
16+
)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# SPDX-FileCopyrightText: 2021 The meson-python developers
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
[build-system]
6+
build-backend = 'mesonpy'
7+
requires = ['meson-python']

tests/packages/symlinks/qux.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../__init__.py
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../__init__.py
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# SPDX-FileCopyrightText: 2024 The meson-python developers
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
def foo():
6+
return 42
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
aaa.py

tests/test_sdist.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,3 +216,22 @@ def test_reproducible(package_pure, tmp_path):
216216

217217
assert sdist_path_a == sdist_path_b
218218
assert tmp_path.joinpath('a', sdist_path_a).read_bytes() == tmp_path.joinpath('b', sdist_path_b).read_bytes()
219+
220+
221+
def test_symlinks(sdist_symlinks):
222+
with tarfile.open(sdist_symlinks, 'r:gz') as sdist:
223+
names = {member.name for member in sdist.getmembers()}
224+
mtimes = {member.mtime for member in sdist.getmembers()}
225+
226+
assert names == {
227+
'symlinks-1.0.0/PKG-INFO',
228+
'symlinks-1.0.0/meson.build',
229+
'symlinks-1.0.0/pyproject.toml',
230+
'symlinks-1.0.0/__init__.py',
231+
'symlinks-1.0.0/submodule/__init__.py',
232+
'symlinks-1.0.0/submodule/aaa.py',
233+
'symlinks-1.0.0/submodule/bbb.py',
234+
}
235+
236+
# All the archive members have a valid mtime.
237+
assert 0 not in mtimes

0 commit comments

Comments
 (0)