|
|
cb73845 |
#!/usr/bin/python3
|
|
|
cb73845 |
"""Vendor PyCA cryptography's Rust crates
|
|
|
cb73845 |
"""
|
|
|
cb73845 |
import argparse
|
|
|
cb73845 |
import os
|
|
|
cb73845 |
import re
|
|
|
cb73845 |
import tarfile
|
|
|
cb73845 |
import tempfile
|
|
|
cb73845 |
import shutil
|
|
|
cb73845 |
import subprocess
|
|
|
cb73845 |
import sys
|
|
|
cb73845 |
|
|
|
cb73845 |
VENDOR_DIR = "vendor"
|
|
|
cb73845 |
CARGO_TOML = "src/rust/Cargo.toml"
|
|
|
cb73845 |
RE_VERSION = re.compile("Version:\s*(.*)")
|
|
|
cb73845 |
|
|
|
cb73845 |
parser = argparse.ArgumentParser(description="Vendor Rust packages")
|
|
|
cb73845 |
parser.add_argument(
|
|
|
cb73845 |
"--spec", default="python-cryptography.spec", help="cryptography source tar bundle"
|
|
|
cb73845 |
)
|
|
|
cb73845 |
|
|
|
cb73845 |
|
|
|
cb73845 |
def cargo(cmd, manifest):
|
|
|
cb73845 |
args = ["cargo", cmd, f"--manifest-path={manifest}"]
|
|
|
cb73845 |
return subprocess.check_call(
|
|
|
cb73845 |
args, stdout=subprocess.DEVNULL, stderr=sys.stderr, env={}
|
|
|
cb73845 |
)
|
|
|
cb73845 |
|
|
|
cb73845 |
|
|
|
fd22717 |
def tar_reset(tarinfo):
|
|
|
fd22717 |
"""Reset user, group, mtime, and mode to create reproducible tar"""
|
|
|
fd22717 |
tarinfo.uid = 0
|
|
|
fd22717 |
tarinfo.gid = 0
|
|
|
fd22717 |
tarinfo.uname = "root"
|
|
|
fd22717 |
tarinfo.gname = "root"
|
|
|
fd22717 |
tarinfo.mtime = 0
|
|
|
fd22717 |
if tarinfo.type == tarfile.DIRTYPE:
|
|
|
fd22717 |
tarinfo.mode = 0o755
|
|
|
fd22717 |
else:
|
|
|
fd22717 |
tarinfo.mode = 0o644
|
|
|
fd22717 |
if tarinfo.pax_headers:
|
|
|
fd22717 |
raise ValueError(tarinfo.name, tarinfo.pax_headers)
|
|
|
fd22717 |
return tarinfo
|
|
|
fd22717 |
|
|
|
fd22717 |
|
|
|
fd22717 |
def tar_reproducible(tar, basedir):
|
|
|
fd22717 |
"""Create reproducible tar file"""
|
|
|
fd22717 |
|
|
|
fd22717 |
content = [basedir]
|
|
|
fd22717 |
for root, dirs, files in os.walk(basedir):
|
|
|
fd22717 |
for directory in dirs:
|
|
|
fd22717 |
content.append(os.path.join(root, directory))
|
|
|
fd22717 |
for filename in files:
|
|
|
fd22717 |
content.append(os.path.join(root, filename))
|
|
|
fd22717 |
content.sort()
|
|
|
fd22717 |
|
|
|
fd22717 |
for fn in content:
|
|
|
fd22717 |
tar.add(fn, filter=tar_reset, recursive=False, arcname=fn)
|
|
|
fd22717 |
|
|
|
fd22717 |
|
|
|
cb73845 |
def main():
|
|
|
cb73845 |
args = parser.parse_args()
|
|
|
cb73845 |
spec = args.spec
|
|
|
cb73845 |
|
|
|
cb73845 |
# change cwd to work in bundle directory
|
|
|
cb73845 |
here = os.path.dirname(os.path.abspath(spec))
|
|
|
cb73845 |
os.chdir(here)
|
|
|
cb73845 |
|
|
|
cb73845 |
# extract version number from bundle name
|
|
|
cb73845 |
with open(spec) as f:
|
|
|
cb73845 |
for line in f:
|
|
|
cb73845 |
mo = RE_VERSION.search(line)
|
|
|
cb73845 |
if mo is not None:
|
|
|
cb73845 |
version = mo.group(1)
|
|
|
cb73845 |
break
|
|
|
cb73845 |
else:
|
|
|
cb73845 |
raise ValueError(f"Cannot find version in {spec}")
|
|
|
cb73845 |
|
|
|
cb73845 |
bundle_file = f"cryptography-{version}.tar.gz"
|
|
|
cb73845 |
vendor_file = f"cryptography-{version}-vendor.tar.bz2"
|
|
|
cb73845 |
|
|
|
cb73845 |
# remove existing vendor directory and file
|
|
|
cb73845 |
if os.path.isdir(VENDOR_DIR):
|
|
|
cb73845 |
shutil.rmtree(VENDOR_DIR)
|
|
|
cb73845 |
try:
|
|
|
cb73845 |
os.unlink(vendor_file)
|
|
|
cb73845 |
except FileNotFoundError:
|
|
|
cb73845 |
pass
|
|
|
cb73845 |
|
|
|
cb73845 |
print(f"Getting crates for {bundle_file}", file=sys.stderr)
|
|
|
cb73845 |
|
|
|
cb73845 |
# extract tar file in tempdir
|
|
|
cb73845 |
# fetch and vendor Rust crates
|
|
|
cb73845 |
with tempfile.TemporaryDirectory(dir=here) as tmp:
|
|
|
cb73845 |
with tarfile.open(bundle_file) as tar:
|
|
|
cb73845 |
tar.extractall(path=tmp)
|
|
|
cb73845 |
manifest = os.path.join(tmp, f"cryptography-{version}", CARGO_TOML)
|
|
|
cb73845 |
cargo("fetch", manifest)
|
|
|
cb73845 |
cargo("vendor", manifest)
|
|
|
cb73845 |
|
|
|
cb73845 |
print("\nCreating tar ball...", file=sys.stderr)
|
|
|
cb73845 |
with tarfile.open(vendor_file, "x:bz2") as tar:
|
|
|
fd22717 |
tar_reproducible(tar, VENDOR_DIR)
|
|
|
cb73845 |
|
|
|
cb73845 |
# remove vendor dir
|
|
|
cb73845 |
shutil.rmtree(VENDOR_DIR)
|
|
|
cb73845 |
|
|
|
cb73845 |
parser.exit(0, f"Created {vendor_file}\n")
|
|
|
cb73845 |
|
|
|
cb73845 |
|
|
|
cb73845 |
if __name__ == "__main__":
|
|
|
cb73845 |
main()
|