2022-05-27 19:45:30 +02:00
|
|
|
#!/usr/bin/env python3
|
2023-01-21 16:03:46 +01:00
|
|
|
"""
|
|
|
|
Download extensions for the current mediawiki version, and update the conf files.
|
|
|
|
"""
|
2022-05-27 19:45:30 +02:00
|
|
|
|
2023-09-15 16:55:06 +02:00
|
|
|
from typing import List, Optional, Any
|
2022-05-27 19:45:30 +02:00
|
|
|
import hashlib
|
|
|
|
import urllib
|
2023-09-04 16:22:45 +02:00
|
|
|
import datetime
|
2022-05-27 19:45:30 +02:00
|
|
|
from html.parser import HTMLParser
|
2023-01-21 16:03:46 +01:00
|
|
|
import tomlkit
|
2022-05-27 19:45:30 +02:00
|
|
|
from packaging import version
|
|
|
|
import requests
|
|
|
|
|
2023-01-21 16:03:46 +01:00
|
|
|
GITHUB_API_URL = "https://api.github.com/repos"
|
|
|
|
|
2023-09-15 16:55:06 +02:00
|
|
|
GITHUB_API_TOKEN = False
|
|
|
|
|
2023-09-04 16:22:45 +02:00
|
|
|
# Update this after updating mediawiki version.
|
|
|
|
ACCEPTABLE_BRANCHES = [
|
|
|
|
"REL1_40",
|
|
|
|
"REL1_39",
|
|
|
|
]
|
|
|
|
|
2022-05-27 19:45:30 +02:00
|
|
|
|
2023-09-15 16:55:06 +02:00
|
|
|
def github_get(path: str, *args, **kwargs) -> Any:
|
|
|
|
headers = kwargs.get("headers", {})
|
|
|
|
if GITHUB_API_TOKEN:
|
|
|
|
headers["Authorization"] = f"Bearer {GITHUB_API_TOKEN}"
|
|
|
|
|
|
|
|
kwargs["headers"] = headers
|
|
|
|
result = requests.get(
|
|
|
|
f"{GITHUB_API_URL}/{path}",
|
|
|
|
timeout=10,
|
|
|
|
*args,
|
|
|
|
**kwargs
|
|
|
|
)
|
|
|
|
if result.status_code == requests.codes["forbidden"]:
|
|
|
|
raise RuntimeError(result.json().get("message"), result.json().get("documentation_url"))
|
|
|
|
|
|
|
|
return result.json()
|
|
|
|
|
|
|
|
|
2022-05-27 19:45:30 +02:00
|
|
|
def sha256sum_of_url(url: str) -> str:
|
|
|
|
"""Compute checksum without saving the file"""
|
|
|
|
checksum = hashlib.sha256()
|
2023-01-21 16:03:46 +01:00
|
|
|
for chunk in requests.get(url, stream=True, timeout=10).iter_content():
|
2022-05-27 19:45:30 +02:00
|
|
|
checksum.update(chunk)
|
|
|
|
return checksum.hexdigest()
|
|
|
|
|
|
|
|
|
2023-01-21 16:03:46 +01:00
|
|
|
def find_valid_version(all_versions: List[str], max_version: version.Version) -> Optional[str]:
|
|
|
|
"""Find the valid extensions for the current mediawiki version"""
|
2022-05-27 19:45:30 +02:00
|
|
|
def version_of(ext):
|
2022-12-25 12:56:30 +01:00
|
|
|
try:
|
2023-01-21 16:03:46 +01:00
|
|
|
return version.parse(ext.replace("_", ".").replace("REL", ""))
|
2022-12-25 12:56:30 +01:00
|
|
|
except version.InvalidVersion:
|
2023-01-21 16:03:46 +01:00
|
|
|
# print(f"Invalid version (this might be normal): {ext}")
|
2022-12-25 12:56:30 +01:00
|
|
|
return version.parse("0.0")
|
2022-05-27 19:45:30 +02:00
|
|
|
|
2023-01-21 16:03:46 +01:00
|
|
|
def compatible(ext_version: str) -> bool:
|
|
|
|
return version_of(ext_version) <= max_version
|
|
|
|
|
|
|
|
compatible_versions = filter(compatible, all_versions)
|
|
|
|
|
|
|
|
if compatible_versions:
|
|
|
|
return max(compatible_versions, key=version_of)
|
|
|
|
|
|
|
|
if "master" in all_versions:
|
|
|
|
return "master"
|
|
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
def get_repo(url: str) -> str:
|
|
|
|
return "/".join(url.split("://")[1].split("/")[1:3])
|
|
|
|
|
|
|
|
|
|
|
|
def get_branches(repo: str) -> List[str]:
|
2023-09-15 16:55:06 +02:00
|
|
|
branches = github_get(f"{repo}/branches")
|
2023-01-21 16:03:46 +01:00
|
|
|
names = [branch["name"] for branch in branches]
|
|
|
|
return names
|
|
|
|
|
|
|
|
|
|
|
|
def get_last_commit_of(repo: str, branch: str) -> str:
|
2023-09-15 16:55:06 +02:00
|
|
|
commit = github_get(f"{repo}/commits/{branch}")
|
2023-01-21 16:03:46 +01:00
|
|
|
return commit["sha"]
|
2022-05-27 19:45:30 +02:00
|
|
|
|
|
|
|
|
2023-09-04 16:22:45 +02:00
|
|
|
def timestamp_of_commit(repo: str, sha: str) -> int:
|
2023-09-15 16:55:06 +02:00
|
|
|
commit = github_get(f"{repo}/commits/{sha}")
|
2023-09-04 16:22:45 +02:00
|
|
|
try:
|
|
|
|
date = commit["commit"]["author"]["date"]
|
|
|
|
except :
|
|
|
|
print(date)
|
|
|
|
raise
|
|
|
|
return datetime.datetime.strptime(date, "%Y-%m-%dT%H:%M:%SZ")
|
|
|
|
|
|
|
|
|
2022-05-27 19:45:30 +02:00
|
|
|
def main():
|
|
|
|
print('Updating extensions source files...')
|
2023-01-21 16:03:46 +01:00
|
|
|
with open("manifest.toml", "r", encoding="utf-8") as file:
|
|
|
|
manifest = tomlkit.loads(file.read())
|
|
|
|
mediawiki_version = version.Version(manifest["version"].value.split("~")[0])
|
|
|
|
|
|
|
|
for name, descr in manifest["resources"]["sources"].items():
|
|
|
|
if "extension" not in descr["url"]:
|
|
|
|
# not an extension
|
|
|
|
continue
|
|
|
|
print(f'Updating source file for {name}')
|
|
|
|
repo = get_repo(descr["url"])
|
|
|
|
branches = get_branches(repo)
|
2023-09-04 16:22:45 +02:00
|
|
|
commits = [
|
|
|
|
get_last_commit_of(repo, branch)
|
|
|
|
for branch in branches
|
|
|
|
if branch in ACCEPTABLE_BRANCHES
|
|
|
|
]
|
|
|
|
|
|
|
|
if not commits:
|
2023-01-21 16:03:46 +01:00
|
|
|
print("Could not find any valid branch")
|
|
|
|
continue
|
2022-05-27 19:45:30 +02:00
|
|
|
|
2023-09-04 16:22:45 +02:00
|
|
|
# Sort by commit date…
|
|
|
|
commits = sorted(commits, key=lambda x, r=repo: timestamp_of_commit(r, x), reverse=True)
|
2022-05-27 19:45:30 +02:00
|
|
|
|
2023-09-04 16:22:45 +02:00
|
|
|
commit = commits[0]
|
2023-01-21 16:03:46 +01:00
|
|
|
url = f"https://github.com/{repo}/archive/{commit}.tar.gz"
|
|
|
|
|
|
|
|
manifest["resources"]["sources"][name]["url"] = url
|
|
|
|
manifest["resources"]["sources"][name]["sha256"] = sha256sum_of_url(url)
|
|
|
|
|
|
|
|
with open("manifest.toml", "w", encoding="utf-8") as manifest_file:
|
|
|
|
manifest_file.write(tomlkit.dumps(manifest))
|
2022-05-27 19:45:30 +02:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|