Skip to content

Commit 087241b

Browse files
glandiumahal
authored andcommitted
Add support for downloading a single file and putting it in an archive
1 parent 5fb0641 commit 087241b

File tree

1 file changed

+49
-5
lines changed

1 file changed

+49
-5
lines changed

src/taskgraph/run-task/fetch-content

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -483,12 +483,34 @@ def should_repack_archive(
483483
return True
484484

485485

486+
EXECUTABLE_SIGNATURES = set([
487+
b"\xFE\xED\xFA\xCE", # mach-o 32-bits big endian
488+
b"\xCE\xFA\xED\xFE", # mach-o 32-bits little endian
489+
b"\xFE\xED\xFA\xCF", # mach-o 64-bits big endian
490+
b"\xCF\xFA\xED\xFE", # mach-o 64-bits little endian
491+
b"\xCA\xFE\xBA\xBE", # mach-o FAT binary
492+
b"\x7F\x45\x4C\x46", # Elf binary
493+
])
494+
495+
486496
def repack_archive(
487-
orig: pathlib.Path, dest: pathlib.Path, strip_components=0, prefix=""
497+
orig: pathlib.Path,
498+
dest: pathlib.Path,
499+
strip_components=0,
500+
prefix="",
501+
force_archive=False,
488502
):
489503
assert orig != dest
490504
log(f"Repacking {orig} as {dest}")
491-
orig_typ, ifh = open_stream(orig)
505+
try:
506+
orig_typ, ifh = open_stream(orig)
507+
except ArchiveTypeNotSupported:
508+
if force_archive:
509+
ifh = io.BufferedReader(orig.open(mode="rb"))
510+
signature = ifh.peek(4)[:4]
511+
orig_typ = "exec" if signature in EXECUTABLE_SIGNATURES else None
512+
else:
513+
raise
492514
typ = archive_type(dest)
493515
if not typ:
494516
raise Exception("Archive type not supported for %s" % dest.name)
@@ -513,7 +535,20 @@ def repack_archive(
513535

514536
with rename_after_close(dest, "wb") as fh:
515537
ctx = ZstdCompressor()
516-
if orig_typ == "zip":
538+
if orig_typ in ("exec", None):
539+
with ctx.stream_writer(fh) as compressor, tarfile.open(
540+
fileobj=compressor,
541+
mode="w:",
542+
) as tar:
543+
tarinfo = tarfile.TarInfo()
544+
tarinfo.name = filter(orig.name) if filter else orig.name
545+
st = orig.stat()
546+
tarinfo.size = st.st_size
547+
tarinfo.mtime = st.st_mtime
548+
tarinfo.mode = 0o0755 if orig_typ == "exec" else 0o0644
549+
tar.addfile(tarinfo, ifh)
550+
551+
elif orig_typ == "zip":
517552
assert typ == "tar"
518553
zip = zipfile.ZipFile(ifh)
519554
# Convert the zip stream to a tar on the fly.
@@ -827,8 +862,12 @@ def command_static_url(args):
827862
if gpg_sig_url:
828863
gpg_verify_path(dl_dest, gpg_key, gpg_signature)
829864

830-
if should_repack_archive(dl_dest, dest, args.strip_components, args.add_prefix):
831-
repack_archive(dl_dest, dest, args.strip_components, args.add_prefix)
865+
if args.force_archive or should_repack_archive(
866+
dl_dest, dest, args.strip_components, args.add_prefix
867+
):
868+
repack_archive(
869+
dl_dest, dest, args.strip_components, args.add_prefix, args.force_archive
870+
)
832871
elif dl_dest != dest:
833872
log(f"Renaming {dl_dest} to {dest}")
834873
dl_dest.rename(dest)
@@ -963,6 +1002,11 @@ def main():
9631002
dest="headers",
9641003
help="Header to send as part of the request, can be passed " "multiple times",
9651004
)
1005+
url.add_argument(
1006+
"--force-archive",
1007+
action="store_true",
1008+
help="Create an archive even when the downloaded file is not an archive",
1009+
)
9661010
url.add_argument("url", help="URL to fetch")
9671011
url.add_argument("dest", help="Destination path")
9681012

0 commit comments

Comments
 (0)