| 
14 | 14 | import argparse  | 
15 | 15 | import collections  | 
16 | 16 | import contextlib  | 
 | 17 | +import copy  | 
17 | 18 | import difflib  | 
18 | 19 | import functools  | 
19 | 20 | import importlib.machinery  | 
 | 
23 | 24 | import os  | 
24 | 25 | import pathlib  | 
25 | 26 | import platform  | 
 | 27 | +import posixpath  | 
26 | 28 | import re  | 
27 | 29 | import shutil  | 
28 | 30 | import subprocess  | 
@@ -937,6 +939,33 @@ def sdist(self, directory: Path) -> pathlib.Path:  | 
937 | 939 | 
 
  | 
938 | 940 |         with tarfile.open(meson_dist_path, 'r:gz') as meson_dist, mesonpy._util.create_targz(sdist_path) as sdist:  | 
939 | 941 |             for member in meson_dist.getmembers():  | 
 | 942 | +                # Recursively resolve symbolic links.  The source distribution  | 
 | 943 | +                # archive format specification allows for symbolic links as  | 
 | 944 | +                # long as the target path does not include a '..' component.  | 
 | 945 | +                # This makes symbolic links support unusable in most cases,  | 
 | 946 | +                # therefore include the symbolic link targets as regular files  | 
 | 947 | +                # in all cases.  | 
 | 948 | +                while member.issym():  | 
 | 949 | +                    name = member.name  | 
 | 950 | +                    target = posixpath.normpath(posixpath.join(posixpath.dirname(member.name), member.linkname))  | 
 | 951 | +                    try:  | 
 | 952 | +                        # This can be implemented using the .replace() method  | 
 | 953 | +                        # in Python 3.12 and later. The .replace() method was  | 
 | 954 | +                        # added as part of PEP 706 and back-ported to Python  | 
 | 955 | +                        # 3.9 and later in patch releases, thus it cannot be  | 
 | 956 | +                        # relied upon until the minimum supported Python  | 
 | 957 | +                        # version is 3.12.  | 
 | 958 | +                        member = copy.copy(meson_dist.getmember(target))  | 
 | 959 | +                        member.name = name  | 
 | 960 | +                    except KeyError:  | 
 | 961 | +                        warnings.warn(  | 
 | 962 | +                            'symbolic link with absolute path target, pointing outside the '  | 
 | 963 | +                            f'archive, or dangling ignored: {name}', stacklevel=1)  | 
 | 964 | +                        break  | 
 | 965 | +                    if member.isdir():  | 
 | 966 | +                        warnings.warn(  | 
 | 967 | +                            f'symbolic link pointing to a directory ignored: {name}', stacklevel=1)  | 
 | 968 | + | 
940 | 969 |                 if member.isfile():  | 
941 | 970 |                     file = meson_dist.extractfile(member.name)  | 
942 | 971 | 
 
  | 
 | 
0 commit comments