1 #!/usr/bin/env nix-shell
2 #!nix-shell -i python3 -p "python3.withPackages (ps: [ ps.beautifulsoup4 ps.lxml ps.packaging ])"
3 from functools
import cached_property
4 from itertools
import groupby
11 from dataclasses
import dataclass
14 from bs4
import BeautifulSoup
, NavigableString
, Tag
15 from packaging
.version
import parse
as parse_version
, Version
18 HERE
= pathlib
.Path(__file__
).parent
19 ROOT
= HERE
.parent
.parent
.parent
.parent
20 VERSIONS_FILE
= HERE
/ "kernels-org.json"
23 class KernelNature(Enum
):
38 def parsed_version(self
) -> Version
:
39 return parse_version(self
.version
)
42 def branch(self
) -> str:
43 version
= self
.parsed_version
44 # This is a testing kernel.
45 if version
.is_prerelease
:
48 return f
"{version.major}.{version.minor}"
51 def parse_release(release
: Tag
) -> KernelRelease |
None:
52 columns
: list[Tag
] = list(release
.find_all("td"))
54 nature
= KernelNature
[columns
[0].get_text().rstrip(":").upper()]
59 version
= columns
[1].get_text().rstrip(" [EOL]")
60 date
= columns
[2].get_text()
61 link
= columns
[3].find("a")
62 if link
is not None and isinstance(link
, Tag
):
63 link
= link
.attrs
.get("href")
64 assert link
is not None, f
"link for kernel {version} is non-existent"
65 eol
= bool(release
.find(class_
="eolkernel"))
76 def get_hash(kernel
: KernelRelease
):
77 if kernel
.branch
== "testing":
83 subprocess
.check_output(["nix-prefetch-url", kernel
.link
] + args
)
87 return f
"sha256:{hash}"
90 def get_oldest_branch(kernels
) -> Version
:
91 return min(parse_version(v
) for v
in kernels
.keys() if v
!= "testing")
94 def predates_oldest_branch(oldest
: Version
, to_compare
: str) -> bool:
95 if to_compare
== "testing":
98 return parse_version(to_compare
) < oldest
102 return subprocess
.check_call(["git", "commit", "-m", message
, VERSIONS_FILE
])
106 kernel_org
= urllib
.request
.urlopen("https://kernel.org/")
107 soup
= BeautifulSoup(kernel_org
.read().decode(), "lxml")
108 release_table
= soup
.find(id="releases")
109 if not release_table
or isinstance(release_table
, NavigableString
):
110 print(release_table
, file=sys
.stderr
)
111 print("Failed to find the release table on https://kernel.org", file=sys
.stderr
)
114 releases
= release_table
.find_all("tr")
116 parsed
for release
in releases
117 if (parsed
:= parse_release(release
)) is not None
119 all_kernels
= json
.load(VERSIONS_FILE
.open())
120 oldest_branch
= get_oldest_branch(all_kernels
)
122 for (branch
, kernels
) in groupby(parsed_releases
, lambda kernel
: kernel
.branch
):
123 kernel
= max(kernels
, key
=lambda kernel
: kernel
.parsed_version
)
124 nixpkgs_branch
= branch
.replace(".", "_")
126 old_version
= all_kernels
.get(branch
, {}).get("version")
127 if old_version
== kernel
.version
:
128 print(f
"linux_{nixpkgs_branch}: {kernel.version} is latest, skipping...")
131 if predates_oldest_branch(oldest_branch
, kernel
.branch
):
133 f
"{kernel.branch} is too old and not supported anymore, skipping...",
138 if old_version
is None:
141 f
"{kernel.branch} is EOL, not adding...",
146 message
= f
"linux_{nixpkgs_branch}: init at {kernel.version}"
148 message
= f
"linux_{nixpkgs_branch}: {old_version} -> {kernel.version}"
150 print(message
, file=sys
.stderr
)
152 all_kernels
[branch
] = {
153 "version": kernel
.version
,
154 "hash": get_hash(kernel
),
157 with VERSIONS_FILE
.open("w") as fd
:
158 json
.dump(all_kernels
, fd
, indent
=4)
159 fd
.write("\n") # makes editorconfig happy
161 if os
.environ
.get("COMMIT") == "1":
165 if __name__
== "__main__":