Zachary Ware | 51599e2 | 2017-06-15 22:08:51 -0500 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
| 2 | |
| 3 | import argparse |
| 4 | import os |
| 5 | import pathlib |
Miss Islington (bot) | ee41d01 | 2021-09-20 07:58:29 -0700 | [diff] [blame] | 6 | import sys |
| 7 | import time |
Zachary Ware | 51599e2 | 2017-06-15 22:08:51 -0500 | [diff] [blame] | 8 | import zipfile |
| 9 | from urllib.request import urlretrieve |
| 10 | |
| 11 | |
| 12 | def fetch_zip(commit_hash, zip_dir, *, org='python', binary=False, verbose): |
| 13 | repo = f'cpython-{"bin" if binary else "source"}-deps' |
| 14 | url = f'https://github.com/{org}/{repo}/archive/{commit_hash}.zip' |
| 15 | reporthook = None |
| 16 | if verbose: |
| 17 | reporthook = print |
| 18 | zip_dir.mkdir(parents=True, exist_ok=True) |
| 19 | filename, headers = urlretrieve( |
| 20 | url, |
| 21 | zip_dir / f'{commit_hash}.zip', |
| 22 | reporthook=reporthook, |
| 23 | ) |
| 24 | return filename |
| 25 | |
| 26 | |
| 27 | def extract_zip(externals_dir, zip_path): |
| 28 | with zipfile.ZipFile(os.fspath(zip_path)) as zf: |
| 29 | zf.extractall(os.fspath(externals_dir)) |
| 30 | return externals_dir / zf.namelist()[0].split('/')[0] |
| 31 | |
| 32 | |
| 33 | def parse_args(): |
| 34 | p = argparse.ArgumentParser() |
| 35 | p.add_argument('-v', '--verbose', action='store_true') |
| 36 | p.add_argument('-b', '--binary', action='store_true', |
| 37 | help='Is the dependency in the binary repo?') |
| 38 | p.add_argument('-O', '--organization', |
| 39 | help='Organization owning the deps repos', default='python') |
| 40 | p.add_argument('-e', '--externals-dir', type=pathlib.Path, |
| 41 | help='Directory in which to store dependencies', |
| 42 | default=pathlib.Path(__file__).parent.parent / 'externals') |
| 43 | p.add_argument('tag', |
| 44 | help='tag of the dependency') |
| 45 | return p.parse_args() |
| 46 | |
| 47 | |
| 48 | def main(): |
| 49 | args = parse_args() |
| 50 | zip_path = fetch_zip( |
| 51 | args.tag, |
| 52 | args.externals_dir / 'zips', |
| 53 | org=args.organization, |
| 54 | binary=args.binary, |
| 55 | verbose=args.verbose, |
| 56 | ) |
| 57 | final_name = args.externals_dir / args.tag |
Miss Islington (bot) | ee41d01 | 2021-09-20 07:58:29 -0700 | [diff] [blame] | 58 | extracted = extract_zip(args.externals_dir, zip_path) |
| 59 | for wait in [1, 2, 3, 5, 8, 0]: |
| 60 | try: |
| 61 | extracted.replace(final_name) |
| 62 | break |
| 63 | except PermissionError as ex: |
| 64 | retry = f" Retrying in {wait}s..." if wait else "" |
| 65 | print(f"Encountered permission error '{ex}'.{retry}", file=sys.stderr) |
| 66 | time.sleep(wait) |
| 67 | else: |
| 68 | print( |
| 69 | f"ERROR: Failed to extract {final_name}.", |
| 70 | "You may need to restart your build", |
| 71 | file=sys.stderr, |
| 72 | ) |
| 73 | sys.exit(1) |
Zachary Ware | 51599e2 | 2017-06-15 22:08:51 -0500 | [diff] [blame] | 74 | |
| 75 | |
| 76 | if __name__ == '__main__': |
| 77 | main() |