mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 22:48:11 +00:00
Meta: Add file download and archive extraction tools to gn build
Use them to download and extract the TZDB files
This commit is contained in:
parent
05f56e09b5
commit
0e24bfb464
7 changed files with 367 additions and 2 deletions
100
Meta/gn/build/extract_archive_contents.py
Normal file
100
Meta/gn/build/extract_archive_contents.py
Normal file
|
@ -0,0 +1,100 @@
|
|||
#!/usr/bin/env python3
|
||||
r"""Extracts files from an archive for use in the build
|
||||
|
||||
It's intended to be used for files that are cached between runs.
|
||||
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import pathlib
|
||||
import tarfile
|
||||
import zipfile
|
||||
import sys
|
||||
|
||||
|
||||
def extract_member(file, destination, path):
|
||||
"""
|
||||
Extract a single file from a ZipFile or TarFile
|
||||
|
||||
:param ZipFile|TarFile file: Archive object to extract from
|
||||
:param Path destination: Location to write the file
|
||||
:param str path: Filename to extract from archive.
|
||||
"""
|
||||
destination_path = destination / path
|
||||
if destination_path.exists():
|
||||
return
|
||||
destination_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
if isinstance(file, tarfile.TarFile):
|
||||
with file.extractfile(path) as member:
|
||||
destination_path.write_text(member.read().decode('utf-8'))
|
||||
else:
|
||||
assert isinstance(file, zipfile.ZipFile)
|
||||
with file.open(path) as member:
|
||||
destination_path.write_text(member.read().decode('utf-8'))
|
||||
|
||||
|
||||
def extract_directory(file, destination, path):
|
||||
"""
|
||||
Extract a directory from a ZipFile or TarFile
|
||||
|
||||
:param ZipFile|TarFile file: Archive object to extract from
|
||||
:param Path destination: Location to write the files
|
||||
:param str path: Directory name to extract from archive.
|
||||
"""
|
||||
destination_path = destination / path
|
||||
if destination_path.exists():
|
||||
return
|
||||
destination_path.mkdir(parents=True, exist_ok=True)
|
||||
if not isinstance(file, zipfile.ZipFile):
|
||||
raise NotImplementedError
|
||||
# FIXME: This loops over the entire archive len(args.paths) times. Decrease complexity
|
||||
for entry in file.namelist():
|
||||
if entry.startswith(path):
|
||||
entry_destination = destination / entry
|
||||
if entry.endswith('/'):
|
||||
entry_destination.mkdir(exist_ok=True)
|
||||
continue
|
||||
with file.open(entry) as member:
|
||||
entry_destination.write_text(member.read().decode('utf-8'))
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
epilog=__doc__,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||
parser.add_argument('archive', help='input archive')
|
||||
parser.add_argument('paths', nargs='*', help='paths to extract from the archive')
|
||||
parser.add_argument('-s', "--stamp", required=False,
|
||||
help='stamp file name to create after operation is done')
|
||||
parser.add_argument('-d', "--destination", required=True,
|
||||
help='directory to write the extracted file to')
|
||||
args = parser.parse_args()
|
||||
|
||||
archive = pathlib.Path(args.archive)
|
||||
destination = pathlib.Path(args.destination)
|
||||
|
||||
def extract_paths(file, paths):
|
||||
for path in paths:
|
||||
if path.endswith('/'):
|
||||
extract_directory(file, destination, path)
|
||||
else:
|
||||
extract_member(file, destination, path)
|
||||
|
||||
if tarfile.is_tarfile(archive):
|
||||
with tarfile.open(archive) as f:
|
||||
extract_paths(f, args.paths)
|
||||
elif zipfile.is_zipfile(archive):
|
||||
with zipfile.ZipFile(archive) as f:
|
||||
extract_paths(f, args.paths)
|
||||
else:
|
||||
print(f"Unknown file type for {archive}, unable to extract {args.path}")
|
||||
return 1
|
||||
|
||||
if args.stamp:
|
||||
pathlib.Path(args.stamp).touch()
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
Loading…
Add table
Add a link
Reference in a new issue