Skip to content

Commit f7f2303

Browse files
committed
ENH: do not include uncommitted changes in the sdist
Including uncommitted changes in the sdist was implemented in mesonbuild#58 after the discussion in mesonbuild#53. However, the current behavior for which uncommitted changes to files under version control are included but not other files, is a hard to justify surprising half measure. After careful analysis, it has been determined that none of the use cases for this feature is still valid. Removing it makes the implementation easier, and the behavior less surprising and easier to document and explain. While at it, modernize the associated test.
1 parent d940353 commit f7f2303

File tree

2 files changed

+37
-61
lines changed

2 files changed

+37
-61
lines changed

mesonpy/__init__.py

+22-45
Original file line numberDiff line numberDiff line change
@@ -860,64 +860,41 @@ def _meson_version(self) -> str:
860860

861861
def sdist(self, directory: Path) -> pathlib.Path:
862862
"""Generates a sdist (source distribution) in the specified directory."""
863-
# generate meson dist file
863+
# Generate meson dist file.
864864
self._run(self._meson + ['dist', '--allow-dirty', '--no-tests', '--formats', 'gztar', *self._meson_args['dist']])
865865

866-
# move meson dist file to output path
867866
dist_name = f'{self._metadata.distribution_name}-{self._metadata.version}'
868867
meson_dist_name = f'{self._meson_name}-{self._meson_version}'
869868
meson_dist_path = pathlib.Path(self._build_dir, 'meson-dist', f'{meson_dist_name}.tar.gz')
870-
sdist = pathlib.Path(directory, f'{dist_name}.tar.gz')
869+
sdist_path = pathlib.Path(directory, f'{dist_name}.tar.gz')
871870

872-
with tarfile.open(meson_dist_path, 'r:gz') as meson_dist, mesonpy._util.create_targz(sdist) as tar:
871+
with tarfile.open(meson_dist_path, 'r:gz') as meson_dist, mesonpy._util.create_targz(sdist_path) as sdist:
873872
for member in meson_dist.getmembers():
874-
# calculate the file path in the source directory
875-
assert member.name, member.name
876-
member_parts = member.name.split('/')
877-
if len(member_parts) <= 1:
878-
continue
879-
path = self._source_dir.joinpath(*member_parts[1:])
873+
if member.isfile():
874+
file = meson_dist.extractfile(member.name)
880875

881-
if not path.exists() and member.isfile():
882-
# File doesn't exists on the source directory but exists on
883-
# the Meson dist, so it is generated file, which we need to
884-
# include.
885-
# See https://mesonbuild.com/Reference-manual_builtin_meson.html#mesonadd_dist_script
876+
# Rewrite the path to match the sdist distribution name.
877+
stem = member.name.split('/', 1)[1]
878+
member.name = '/'.join((dist_name, stem))
886879

887-
# MESON_DIST_ROOT could have a different base name
888-
# than the actual sdist basename, so we need to rename here
889-
file = meson_dist.extractfile(member.name)
890-
member.name = str(pathlib.Path(dist_name, *member_parts[1:]).as_posix())
891-
tar.addfile(member, file)
892-
continue
880+
# Reset owner and group to root:root. This mimics what
881+
# 'git archive' does and makes the sdist reproducible upon
882+
# being built by different users.
883+
member.uname = member.gname = 'root'
884+
member.uid = member.gid = 0
893885

894-
if not path.is_file():
895-
continue
886+
sdist.addfile(member, file)
896887

897-
info = tarfile.TarInfo(member.name)
898-
file_stat = os.stat(path)
899-
info.mtime = member.mtime
900-
info.size = file_stat.st_size
901-
info.mode = int(oct(file_stat.st_mode)[-3:], 8)
902-
903-
# rewrite the path if necessary, to match the sdist distribution name
904-
if dist_name != meson_dist_name:
905-
info.name = pathlib.Path(
906-
dist_name,
907-
path.relative_to(self._source_dir)
908-
).as_posix()
909-
910-
with path.open('rb') as f:
911-
tar.addfile(info, fileobj=f)
912-
913-
# add PKG-INFO to dist file to make it a sdist
914-
pkginfo_info = tarfile.TarInfo(f'{dist_name}/PKG-INFO')
915-
pkginfo_info.mtime = time.time() # type: ignore[assignment]
888+
# Add 'PKG-INFO'.
889+
member = tarfile.TarInfo(f'{dist_name}/PKG-INFO')
890+
member.uid = member.gid = 0
891+
member.uname = member.gname = 'root'
892+
member.mtime = time.time()
916893
metadata = bytes(self._metadata.as_rfc822())
917-
pkginfo_info.size = len(metadata)
918-
tar.addfile(pkginfo_info, fileobj=io.BytesIO(metadata))
894+
member.size = len(metadata)
895+
sdist.addfile(member, io.BytesIO(metadata))
919896

920-
return sdist
897+
return sdist_path
921898

922899
def wheel(self, directory: Path) -> pathlib.Path:
923900
"""Generates a wheel in the specified directory."""

tests/test_sdist.py

+15-16
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# SPDX-License-Identifier: MIT
44

55
import os
6+
import pathlib
67
import re
78
import stat
89
import sys
@@ -122,37 +123,35 @@ def test_contents_subdirs(sdist_subdirs):
122123

123124

124125
def test_contents_unstaged(package_pure, tmp_path):
125-
new_data = textwrap.dedent('''
126-
def bar():
127-
return 'foo'
126+
new = textwrap.dedent('''
127+
def bar():
128+
return 'foo'
128129
''').strip()
129130

130-
with open('pure.py', 'r') as f:
131-
old_data = f.read()
132-
133-
try:
134-
with in_git_repo_context():
135-
with open('pure.py', 'w') as f, open('crap', 'x'):
136-
f.write(new_data)
131+
old = pathlib.Path('pure.py').read_text()
137132

133+
with in_git_repo_context():
134+
try:
135+
pathlib.Path('pure.py').write_text(new)
136+
pathlib.Path('other.py').touch()
138137
sdist_path = mesonpy.build_sdist(os.fspath(tmp_path))
139-
finally:
140-
with open('pure.py', 'w') as f:
141-
f.write(old_data)
142-
os.unlink('crap')
138+
finally:
139+
pathlib.Path('pure.py').write_text(old)
140+
pathlib.Path('other.py').unlink()
143141

144142
with tarfile.open(tmp_path / sdist_path, 'r:gz') as sdist:
145143
names = {member.name for member in sdist.getmembers()}
146144
mtimes = {member.mtime for member in sdist.getmembers()}
147-
read_data = sdist.extractfile('pure-1.0.0/pure.py').read().replace(b'\r\n', b'\n')
145+
data = sdist.extractfile('pure-1.0.0/pure.py').read().replace(b'\r\n', b'\n')
148146

147+
# Verify that uncommitted changes are not included in the sdist.
149148
assert names == {
150149
'pure-1.0.0/PKG-INFO',
151150
'pure-1.0.0/meson.build',
152151
'pure-1.0.0/pure.py',
153152
'pure-1.0.0/pyproject.toml',
154153
}
155-
assert read_data == new_data.encode()
154+
assert data == old.encode()
156155

157156
# All the archive members have a valid mtime.
158157
assert 0 not in mtimes

0 commit comments

Comments
 (0)