at 23.11-beta 130 lines 3.5 kB view raw
1#!/usr/bin/env nix-shell 2#!nix-shell -i python3 -p "python3.withPackages (ps: [ ps.beautifulsoup4 ps.lxml ])" 3import json 4import os 5import pathlib 6import subprocess 7import sys 8import urllib.request 9from dataclasses import dataclass 10from enum import Enum 11 12from bs4 import BeautifulSoup, NavigableString, Tag 13 14HERE = pathlib.Path(__file__).parent 15ROOT = HERE.parent.parent.parent.parent 16VERSIONS_FILE = HERE / "kernels-org.json" 17 18 19class KernelNature(Enum): 20 MAINLINE = 1 21 STABLE = 2 22 LONGTERM = 3 23 24 25@dataclass 26class KernelRelease: 27 nature: KernelNature 28 version: str 29 branch: str 30 date: str 31 link: str 32 eol: bool = False 33 34 35def parse_release(release: Tag) -> KernelRelease | None: 36 columns: list[Tag] = list(release.find_all("td")) 37 try: 38 nature = KernelNature[columns[0].get_text().rstrip(":").upper()] 39 except KeyError: 40 return None 41 42 version = columns[1].get_text().rstrip(" [EOL]") 43 date = columns[2].get_text() 44 link = columns[3].find("a") 45 if link is not None and isinstance(link, Tag): 46 link = link.attrs.get("href") 47 assert link is not None, f"link for kernel {version} is non-existent" 48 eol = bool(release.find(class_="eolkernel")) 49 50 return KernelRelease( 51 nature=nature, 52 branch=get_branch(version), 53 version=version, 54 date=date, 55 link=link, 56 eol=eol, 57 ) 58 59 60def get_branch(version: str): 61 # This is a testing kernel. 62 if "rc" in version: 63 return "testing" 64 else: 65 major, minor, *_ = version.split(".") 66 return f"{major}.{minor}" 67 68 69def get_hash(kernel: KernelRelease): 70 if kernel.branch == "testing": 71 args = ["--unpack"] 72 else: 73 args = [] 74 75 hash = ( 76 subprocess.check_output(["nix-prefetch-url", kernel.link] + args) 77 .decode() 78 .strip() 79 ) 80 return f"sha256:{hash}" 81 82 83def commit(message): 84 return subprocess.check_call(["git", "commit", "-m", message, VERSIONS_FILE]) 85 86 87def main(): 88 kernel_org = urllib.request.urlopen("https://kernel.org/") 89 soup = BeautifulSoup(kernel_org.read().decode(), "lxml") 90 release_table = soup.find(id="releases") 91 if not release_table or isinstance(release_table, NavigableString): 92 print(release_table, file=sys.stderr) 93 print("Failed to find the release table on https://kernel.org", file=sys.stderr) 94 sys.exit(1) 95 96 releases = release_table.find_all("tr") 97 parsed_releases = filter(None, [parse_release(release) for release in releases]) 98 all_kernels = json.load(VERSIONS_FILE.open()) 99 100 for kernel in parsed_releases: 101 branch = get_branch(kernel.version) 102 nixpkgs_branch = branch.replace(".", "_") 103 104 old_version = all_kernels.get(branch, {}).get("version") 105 if old_version == kernel.version: 106 print(f"linux_{nixpkgs_branch}: {kernel.version} is latest, skipping...") 107 continue 108 109 if old_version is None: 110 message = f"linux_{nixpkgs_branch}: init at {kernel.version}" 111 else: 112 message = f"linux_{nixpkgs_branch}: {old_version} -> {kernel.version}" 113 114 print(message, file=sys.stderr) 115 116 all_kernels[branch] = { 117 "version": kernel.version, 118 "hash": get_hash(kernel), 119 } 120 121 with VERSIONS_FILE.open("w") as fd: 122 json.dump(all_kernels, fd, indent=4) 123 fd.write("\n") # makes editorconfig happy 124 125 if os.environ.get("COMMIT") == "1": 126 commit(message) 127 128 129if __name__ == "__main__": 130 main()