@@ -13,10 +13,14 @@ class HybridPackager(Packager):
1313 """
1414 A packager that combines multiple other packagers into one final archive.
1515 Each subpackager is mapped to a target directory name, which will become
16- the top-level folder under which that packager’s content is placed.
16+ the top-level folder under which that packager's content is placed.
17+
18+ If `extract_at_root` is True, the contents of each sub-packager are extracted
19+ directly at the root of the final archive (i.e. without being nested in a subfolder).
1720 """
1821
1922 sub_packagers : Dict [str , Packager ] = field (default_factory = dict )
23+ extract_at_root : bool = False
2024
2125 def package (self , path : Path , job_dir : str , name : str ) -> str :
2226 final_tar_gz = os .path .join (job_dir , f"{ name } .tar.gz" )
@@ -28,7 +32,8 @@ def package(self, path: Path, job_dir: str, name: str) -> str:
2832 ctx = Context ()
2933 ctx .run (f"tar -cf { tmp_tar } --files-from /dev/null" )
3034
31- # For each subpackager, run its .package() method and extract to a subfolder
35+ # For each subpackager, run its .package() method,
36+ # extract the content and add it to the final tar
3237 for folder_name , packager in self .sub_packagers .items ():
3338 subarchive_path = packager .package (path , job_dir , f"{ name } _{ folder_name } " )
3439
@@ -38,7 +43,22 @@ def package(self, path: Path, job_dir: str, name: str) -> str:
3843 os .makedirs (tmp_extract_dir , exist_ok = True )
3944
4045 ctx .run (f"tar -xf { subarchive_path } -C { tmp_extract_dir } " )
41- ctx .run (f"tar -rf { tmp_tar } -C { tmp_extract_dir } . --transform='s,^,{ folder_name } /,'" )
46+
47+ # If extract_at_root is True then add files directly to the archive root.
48+ # Otherwise, add them under a subfolder named after the key.
49+ if self .extract_at_root :
50+ ctx .run (f"tar -rf { tmp_tar } -C { tmp_extract_dir } ." )
51+ else :
52+ sysname = os .uname ().sysname
53+ if sysname == "Darwin" :
54+ # BSD tar uses the -s option with a chosen delimiter (here we use a comma)
55+ # The first -s replaces an entry that is exactly "."
56+ # The second -s replaces entries starting with "./" (i.e. files inside)
57+ transform_option = f"-s ',^\\ .$,{ folder_name } ,' -s ',^\\ ./,{ folder_name } /,'"
58+ else :
59+ transform_option = f"--transform='s,^,{ folder_name } /,'"
60+ ctx .run (f"tar { transform_option } -rf { tmp_tar } -C { tmp_extract_dir } ." )
61+
4262 ctx .run (f"rm -rf { tmp_extract_dir } " )
4363 ctx .run (f"rm { subarchive_path } " )
4464
0 commit comments