@@ -865,64 +865,57 @@ def _meson_version(self) -> str:
865
865
866
866
def sdist (self , directory : Path ) -> pathlib .Path :
867
867
"""Generates a sdist (source distribution) in the specified directory."""
868
- # generate meson dist file
868
+ # Generate meson dist file.
869
869
self ._run (self ._meson + ['dist' , '--allow-dirty' , '--no-tests' , '--formats' , 'gztar' , * self ._meson_args ['dist' ]])
870
870
871
- # move meson dist file to output path
872
871
dist_name = f'{ self ._metadata .distribution_name } -{ self ._metadata .version } '
873
872
meson_dist_name = f'{ self ._meson_name } -{ self ._meson_version } '
874
873
meson_dist_path = pathlib .Path (self ._build_dir , 'meson-dist' , f'{ meson_dist_name } .tar.gz' )
875
- sdist = pathlib .Path (directory , f'{ dist_name } .tar.gz' )
874
+ sdist_path = pathlib .Path (directory , f'{ dist_name } .tar.gz' )
876
875
877
- with tarfile .open (meson_dist_path , 'r:gz' ) as meson_dist , mesonpy ._util .create_targz (sdist ) as tar :
876
+ with tarfile .open (meson_dist_path , 'r:gz' ) as meson_dist , mesonpy ._util .create_targz (sdist_path ) as sdist :
878
877
for member in meson_dist .getmembers ():
879
- # calculate the file path in the source directory
880
- assert member .name , member .name
881
- member_parts = member .name .split ('/' )
882
- if len (member_parts ) <= 1 :
883
- continue
884
- path = self ._source_dir .joinpath (* member_parts [1 :])
885
-
886
- if not path .exists () and member .isfile ():
887
- # File doesn't exists on the source directory but exists on
888
- # the Meson dist, so it is generated file, which we need to
889
- # include.
890
- # See https://mesonbuild.com/Reference-manual_builtin_meson.html#mesonadd_dist_script
891
-
892
- # MESON_DIST_ROOT could have a different base name
893
- # than the actual sdist basename, so we need to rename here
878
+ if member .isfile ():
894
879
file = meson_dist .extractfile (member .name )
895
- member .name = str (pathlib .Path (dist_name , * member_parts [1 :]).as_posix ())
896
- tar .addfile (member , file )
897
- continue
898
-
899
- if not path .is_file ():
900
- continue
901
880
902
- info = tarfile .TarInfo (member .name )
903
- file_stat = os .stat (path )
904
- info .mtime = member .mtime
905
- info .size = file_stat .st_size
906
- info .mode = int (oct (file_stat .st_mode )[- 3 :], 8 )
907
-
908
- # rewrite the path if necessary, to match the sdist distribution name
909
- if dist_name != meson_dist_name :
910
- info .name = pathlib .Path (
911
- dist_name ,
912
- path .relative_to (self ._source_dir )
913
- ).as_posix ()
914
-
915
- with path .open ('rb' ) as f :
916
- tar .addfile (info , fileobj = f )
917
-
918
- # add PKG-INFO to dist file to make it a sdist
919
- pkginfo_info = tarfile .TarInfo (f'{ dist_name } /PKG-INFO' )
920
- pkginfo_info .mtime = time .time () # type: ignore[assignment]
881
+ # Reset pax extended header. The tar archive member may be
882
+ # using pax headers to store some file metadata. The pax
883
+ # headers are not reset when the metadata is modified and
884
+ # they take precedence when the member is deserialized.
885
+ # This is relevant because when rewriting the member name,
886
+ # the length of the path may shrink from being more than
887
+ # 100 characters (requiring the path to be stored in the
888
+ # pax headers) to being less than 100 characters. When this
889
+ # happens, the tar archive member is serialized with the
890
+ # shorter name in the regular header and the longer one in
891
+ # the extended pax header. The archives handled here are
892
+ # not expected to use extended pax headers other than for
893
+ # the ones required to encode file metadata. The easiest
894
+ # solution is to reset the pax extended headers.
895
+ member .pax_headers = {}
896
+
897
+ # Rewrite the path to match the sdist distribution name.
898
+ stem = member .name .split ('/' , 1 )[1 ]
899
+ member .name = '/' .join ((dist_name , stem ))
900
+
901
+ # Reset owner and group to root:root. This mimics what
902
+ # 'git archive' does and makes the sdist reproducible upon
903
+ # being built by different users.
904
+ member .uname = member .gname = 'root'
905
+ member .uid = member .gid = 0
906
+
907
+ sdist .addfile (member , file )
908
+
909
+ # Add 'PKG-INFO'.
910
+ member = tarfile .TarInfo (f'{ dist_name } /PKG-INFO' )
911
+ member .uid = member .gid = 0
912
+ member .uname = member .gname = 'root'
913
+ member .mtime = time .time ()
921
914
metadata = bytes (self ._metadata .as_rfc822 ())
922
- pkginfo_info .size = len (metadata )
923
- tar .addfile (pkginfo_info , fileobj = io .BytesIO (metadata ))
915
+ member .size = len (metadata )
916
+ sdist .addfile (member , io .BytesIO (metadata ))
924
917
925
- return sdist
918
+ return sdist_path
926
919
927
920
def wheel (self , directory : Path ) -> pathlib .Path :
928
921
"""Generates a wheel in the specified directory."""
0 commit comments