Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
at devShellTools-shell 152 lines 4.9 kB view raw
1#!/usr/bin/env nix-shell 2#! nix-shell -i python -p "python3.withPackages (ps: with ps; [ps.requests ])" 3 4import os 5import hashlib 6import base64 7import json 8 9import requests 10 11 12class Version: 13 def __init__(self, name: str): 14 self.name: str = name 15 self.hash: str | None = None 16 self.build_number: int | None = None 17 18 @property 19 def full_name(self): 20 v_name = f"{self.name}-{self.build_number}" 21 22 # this will probably never happen because the download of a build with NoneType in URL would fail 23 if not self.name or not self.build_number: 24 print(f"Warning: version '{v_name}' contains NoneType!") 25 26 return v_name 27 28 29class VersionManager: 30 def __init__(self, base_url: str = "https://api.papermc.io/v2/projects/paper"): 31 self.versions: list[Version] = [] 32 self.base_url: str = base_url 33 34 def fetch_versions(self, not_before_minor_version: int = 18): 35 """ 36 Fetch all versions after given minor release 37 """ 38 39 response = requests.get(self.base_url) 40 41 try: 42 response.raise_for_status() 43 44 except requests.exceptions.HTTPError as e: 45 print(e) 46 return 47 48 # we only want versions that are no pre-releases 49 release_versions = filter( 50 lambda v_name: 'pre' not in v_name, response.json()["versions"]) 51 52 for version_name in release_versions: 53 54 # split version string, convert to list ot int 55 version_split = version_name.split(".") 56 version_split = list(map(int, version_split)) 57 58 # check if version is higher than 1.<not_before_sub_version> 59 if (version_split[0] > 1) or (version_split[0] == 1 and version_split[1] >= not_before_minor_version): 60 self.versions.append(Version(version_name)) 61 62 def fetch_latest_version_builds(self): 63 """ 64 Set latest build number to each version 65 """ 66 67 for version in self.versions: 68 url = f"{self.base_url}/versions/{version.name}" 69 response = requests.get(url) 70 71 # check that we've got a good response 72 try: 73 response.raise_for_status() 74 75 except requests.exceptions.HTTPError as e: 76 print(e) 77 return 78 79 # the highest build in response.json()['builds']: 80 latest_build = response.json()['builds'][-1] 81 version.build_number = latest_build 82 83 def generate_version_hashes(self): 84 """ 85 Generate and set the hashes for all registered versions (versions will are downloaded to memory) 86 """ 87 88 for version in self.versions: 89 url = f"{self.base_url}/versions/{version.name}/builds/{version.build_number}/downloads/paper-{version.full_name}.jar" 90 version.hash = self.download_and_generate_sha256_hash(url) 91 92 def versions_to_json(self): 93 return json.dumps( 94 {version.name: {'hash': version.hash, 'version': version.full_name} 95 for version in self.versions}, 96 indent=4 97 ) 98 99 def find_version_json() -> str: 100 """ 101 Find the versions.json file in the same directory as this script 102 """ 103 return os.path.join(os.path.dirname(os.path.realpath(__file__)), "versions.json") 104 105 def write_versions(self, file_name: str = find_version_json()): 106 """ write all processed versions to json """ 107 # save json to versions.json 108 with open(file_name, 'w') as f: 109 f.write(self.versions_to_json() + "\n") 110 111 @staticmethod 112 def download_and_generate_sha256_hash(url: str) -> str | None: 113 """ 114 Fetch the tarball from the given URL. 115 Then generate a sha256 hash of the tarball. 116 """ 117 118 try: 119 # Download the file from the URL 120 response = requests.get(url) 121 response.raise_for_status() 122 123 except requests.exceptions.RequestException as e: 124 print(f"Error: {e}") 125 return None 126 127 # Create a new SHA-256 hash object 128 sha256_hash = hashlib.sha256() 129 130 # Update the hash object with chunks of the downloaded content 131 for byte_block in response.iter_content(4096): 132 sha256_hash.update(byte_block) 133 134 # Get the hexadecimal representation of the hash 135 hash_value = sha256_hash.digest() 136 137 # Encode the hash value in base64 138 base64_hash = base64.b64encode(hash_value).decode('utf-8') 139 140 # Format it as "sha256-{base64_hash}" 141 sri_representation = f"sha256-{base64_hash}" 142 143 return sri_representation 144 145 146if __name__ == '__main__': 147 version_manager = VersionManager() 148 149 version_manager.fetch_versions() 150 version_manager.fetch_latest_version_builds() 151 version_manager.generate_version_hashes() 152 version_manager.write_versions()