Skip to content

Commit f10f3fe

Browse files
committed
Add support for downloading a single file and putting it in an archive
1 parent 5a03d0f commit f10f3fe

File tree

1 file changed

+46
-5
lines changed

1 file changed

+46
-5
lines changed

src/taskgraph/run-task/fetch-content

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -480,12 +480,31 @@ def should_repack_archive(
480480
return True
481481

482482

483+
EXECUTABLE_SIGNATURES = [
484+
b"\xFE\xED\xFA\xCE", # mach-o 32-bits big endian
485+
b"\xCE\xFA\xED\xFE", # mach-o 32-bits little endian
486+
b"\xFE\xED\xFA\xCF", # mach-o 64-bits big endian
487+
b"\xCF\xFA\xED\xFE", # mach-o 64-bits little endian
488+
b"\xCA\xFE\xBA\xBE", # mach-o FAT binary
489+
b"\x7F\x45\x4C\x46", # Elf binary
490+
]
491+
492+
483493
def repack_archive(
484-
orig: pathlib.Path, dest: pathlib.Path, strip_components=0, prefix=""
494+
orig: pathlib.Path,
495+
dest: pathlib.Path,
496+
strip_components=0,
497+
prefix="",
498+
single_file=False,
485499
):
486500
assert orig != dest
487501
log(f"Repacking {orig} as {dest}")
488-
orig_typ, ifh = open_stream(orig)
502+
if single_file:
503+
ifh = io.BufferedReader(orig.open(mode="rb"))
504+
signature = ifh.peek(4)[:4]
505+
orig_typ = "exec" if signature in EXECUTABLE_SIGNATURES else None
506+
else:
507+
orig_typ, ifh = open_stream(orig)
489508
typ = archive_type(dest)
490509
if not typ:
491510
raise Exception("Archive type not supported for %s" % dest.name)
@@ -510,7 +529,20 @@ def repack_archive(
510529

511530
with rename_after_close(dest, "wb") as fh:
512531
ctx = ZstdCompressor()
513-
if orig_typ == "zip":
532+
if single_file:
533+
with ctx.stream_writer(fh) as compressor, tarfile.open(
534+
fileobj=compressor,
535+
mode="w:",
536+
) as tar:
537+
tarinfo = tarfile.TarInfo()
538+
tarinfo.name = filter(orig.name) if filter else orig.name
539+
st = orig.stat()
540+
tarinfo.size = st.st_size
541+
tarinfo.mtime = st.st_mtime
542+
tarinfo.mode = 0o0755 if orig_typ == "exec" else 0o0644
543+
tar.addfile(tarinfo, ifh)
544+
545+
elif orig_typ == "zip":
514546
assert typ == "tar"
515547
zip = zipfile.ZipFile(ifh)
516548
# Convert the zip stream to a tar on the fly.
@@ -824,8 +856,12 @@ def command_static_url(args):
824856
if gpg_sig_url:
825857
gpg_verify_path(dl_dest, gpg_key, gpg_signature)
826858

827-
if should_repack_archive(dl_dest, dest, args.strip_components, args.add_prefix):
828-
repack_archive(dl_dest, dest, args.strip_components, args.add_prefix)
859+
if args.single_file or should_repack_archive(
860+
dl_dest, dest, args.strip_components, args.add_prefix
861+
):
862+
repack_archive(
863+
dl_dest, dest, args.strip_components, args.add_prefix, args.single_file
864+
)
829865
elif dl_dest != dest:
830866
log(f"Renaming {dl_dest} to {dest}")
831867
dl_dest.rename(dest)
@@ -960,6 +996,11 @@ def main():
960996
dest="headers",
961997
help="Header to send as part of the request, can be passed " "multiple times",
962998
)
999+
url.add_argument(
1000+
"--single-file",
1001+
action="store_true",
1002+
help="The downloaded file is not an archive and should be put inside one",
1003+
)
9631004
url.add_argument("url", help="URL to fetch")
9641005
url.add_argument("dest", help="Destination path")
9651006

0 commit comments

Comments
 (0)