| 
									
										
										
										
											2017-06-15 22:08:51 -05:00
										 |  |  | #!/usr/bin/env python3 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import argparse | 
					
						
							|  |  |  | import os | 
					
						
							|  |  |  | import pathlib | 
					
						
							| 
									
										
										
										
											2021-09-20 15:33:00 +01:00
										 |  |  | import sys | 
					
						
							|  |  |  | import time | 
					
						
							| 
									
										
										
										
											2017-06-15 22:08:51 -05:00
										 |  |  | import zipfile | 
					
						
							|  |  |  | from urllib.request import urlretrieve | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def fetch_zip(commit_hash, zip_dir, *, org='python', binary=False, verbose): | 
					
						
							|  |  |  |     repo = f'cpython-{"bin" if binary else "source"}-deps' | 
					
						
							|  |  |  |     url = f'https://github.com/{org}/{repo}/archive/{commit_hash}.zip' | 
					
						
							|  |  |  |     reporthook = None | 
					
						
							|  |  |  |     if verbose: | 
					
						
							|  |  |  |         reporthook = print | 
					
						
							|  |  |  |     zip_dir.mkdir(parents=True, exist_ok=True) | 
					
						
							|  |  |  |     filename, headers = urlretrieve( | 
					
						
							|  |  |  |         url, | 
					
						
							|  |  |  |         zip_dir / f'{commit_hash}.zip', | 
					
						
							|  |  |  |         reporthook=reporthook, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     return filename | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def extract_zip(externals_dir, zip_path): | 
					
						
							|  |  |  |     with zipfile.ZipFile(os.fspath(zip_path)) as zf: | 
					
						
							|  |  |  |         zf.extractall(os.fspath(externals_dir)) | 
					
						
							|  |  |  |         return externals_dir / zf.namelist()[0].split('/')[0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def parse_args(): | 
					
						
							|  |  |  |     p = argparse.ArgumentParser() | 
					
						
							|  |  |  |     p.add_argument('-v', '--verbose', action='store_true') | 
					
						
							|  |  |  |     p.add_argument('-b', '--binary', action='store_true', | 
					
						
							|  |  |  |                    help='Is the dependency in the binary repo?') | 
					
						
							|  |  |  |     p.add_argument('-O', '--organization', | 
					
						
							|  |  |  |                    help='Organization owning the deps repos', default='python') | 
					
						
							|  |  |  |     p.add_argument('-e', '--externals-dir', type=pathlib.Path, | 
					
						
							|  |  |  |                    help='Directory in which to store dependencies', | 
					
						
							|  |  |  |                    default=pathlib.Path(__file__).parent.parent / 'externals') | 
					
						
							|  |  |  |     p.add_argument('tag', | 
					
						
							|  |  |  |                    help='tag of the dependency') | 
					
						
							|  |  |  |     return p.parse_args() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def main(): | 
					
						
							|  |  |  |     args = parse_args() | 
					
						
							|  |  |  |     zip_path = fetch_zip( | 
					
						
							|  |  |  |         args.tag, | 
					
						
							|  |  |  |         args.externals_dir / 'zips', | 
					
						
							|  |  |  |         org=args.organization, | 
					
						
							|  |  |  |         binary=args.binary, | 
					
						
							|  |  |  |         verbose=args.verbose, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     final_name = args.externals_dir / args.tag | 
					
						
							| 
									
										
										
										
											2021-09-20 15:33:00 +01:00
										 |  |  |     extracted = extract_zip(args.externals_dir, zip_path) | 
					
						
							|  |  |  |     for wait in [1, 2, 3, 5, 8, 0]: | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             extracted.replace(final_name) | 
					
						
							|  |  |  |             break | 
					
						
							|  |  |  |         except PermissionError as ex: | 
					
						
							|  |  |  |             retry = f" Retrying in {wait}s..." if wait else "" | 
					
						
							|  |  |  |             print(f"Encountered permission error '{ex}'.{retry}", file=sys.stderr) | 
					
						
							|  |  |  |             time.sleep(wait) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         print( | 
					
						
							|  |  |  |             f"ERROR: Failed to extract {final_name}.", | 
					
						
							|  |  |  |             "You may need to restart your build", | 
					
						
							|  |  |  |             file=sys.stderr, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         sys.exit(1) | 
					
						
							| 
									
										
										
										
											2017-06-15 22:08:51 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == '__main__': | 
					
						
							|  |  |  |     main() |