From 3ea3c708156af6527bd3efc557473defeb4efffc Mon Sep 17 00:00:00 2001 From: Alexander01998 Date: Fri, 20 Dec 2024 14:52:36 +0100 Subject: [PATCH] Refactor add_mod_port script --- .gitignore | 3 ++ scripts/add_mod_port.py | 105 ++++++++-------------------------------- scripts/util.py | 86 ++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+), 85 deletions(-) create mode 100644 scripts/util.py diff --git a/.gitignore b/.gitignore index 3f8096b..c1848a4 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,6 @@ public/ # .hugo_build.lock file *.lock + +# Python bytecode +*.pyc diff --git a/scripts/add_mod_port.py b/scripts/add_mod_port.py index 5428384..12e3ce8 100644 --- a/scripts/add_mod_port.py +++ b/scripts/add_mod_port.py @@ -1,12 +1,7 @@ -import json -import os import requests +import util from argparse import ArgumentParser -from io import StringIO -from ruamel.yaml import YAML - -yaml = YAML() -yaml.preserve_quotes = True +from pathlib import Path manifest_url = "https://piston-meta.mojang.com/mc/game/version_manifest_v2.json" manifest = requests.get(manifest_url).json() @@ -17,73 +12,22 @@ } -def read_front_matter(path): - """Read YAML front matter from a Jekyll/Hugo post.""" - with open(path, "r", encoding="utf-8") as file: - content = file.read() - - # Split on the first two "---" markers - parts = content.split("---", 2) - if len(parts) < 3: - raise ValueError(f"Invalid front matter format in {path}") - - # Parse the YAML between the markers - return yaml.load(parts[1]) - - -def write_front_matter(path, front_matter): - """Write YAML front matter to a Jekyll/Hugo post while preserving content.""" - with open(path, "r", encoding="utf-8") as file: - content = file.read() - - # Split the original content - parts = content.split("---", 2) - if len(parts) < 3: - raise ValueError(f"Invalid front matter format in {path}") - - # Create new content with updated front matter - output = StringIO() - yaml.dump(front_matter, output) - new_content = f"---\n{output.getvalue()}---{parts[2]}" - - # Write the updated content - with open(path, "w", encoding="utf-8") as file: - file.write(new_content) - - -def find_mod_update_post(mod, version): - """Find the mod update post for a specific version.""" - posts_folder = os.path.join("content", mod) - for root, _, files in os.walk(posts_folder): - for file in files: - version_slug = version.replace(".", "-") - if version_slug not in file: - continue - - post_path = os.path.join(root, file) - front_matter = read_front_matter(post_path) - if front_matter.get("modversion") == version: - return front_matter, post_path - - raise ValueError(f"Could not find post for mod {mod} version {version}") - - def update_mod_post(mod, modloader, mod_version, mc_version): """Add a new Minecraft version to a mod update post.""" - mc_version_type = version_info[mc_version]["type"] - front_matter, post_path = find_mod_update_post(mod, mod_version) + post = util.find_mod_update_post(mod, mod_version) + front_matter = post.front_matter - if mc_version_type == "snapshot": + if version_info[mc_version]["type"] == "snapshot": if "snapshots" not in front_matter: front_matter["snapshots"] = [] if mc_version not in front_matter["snapshots"]: - front_matter["snapshots"].insert(0, mc_version) + front_matter["snapshots"].append(mc_version) front_matter["snapshots"].sort( key=lambda v: version_info[v]["releaseTime"], reverse=True, ) elif mc_version not in front_matter["mcversions"]: - front_matter["mcversions"].insert(0, mc_version) + front_matter["mcversions"].append(mc_version) front_matter["mcversions"].sort( key=lambda v: version_info[v]["releaseTime"], reverse=True, @@ -93,20 +37,19 @@ def update_mod_post(mod, modloader, mod_version, mc_version): if "neoforge" not in front_matter: front_matter["neoforge"] = [] if mc_version not in front_matter["neoforge"]: - front_matter["neoforge"].insert(0, mc_version) + front_matter["neoforge"].append(mc_version) front_matter["neoforge"].sort( key=lambda v: version_info[v]["releaseTime"], reverse=True, ) - write_front_matter(post_path, front_matter) + util.write_front_matter(post.path, front_matter) def update_fabric_api_data(mod, mod_version, mc_version, fapi_version): """Add a new entry to the Fabric API data file for a mod.""" - data_file = os.path.join("data", "fabric_api", f"{mod}.json") - with open(data_file, "r") as f: - data = json.load(f) + data_file = Path("data") / "fabric_api" / f"{mod}.json" + data = util.read_json_file(data_file) # Add mod_version -> mc_version -> fabric_api mapping unless it is already there if mod_version not in data: @@ -127,15 +70,13 @@ def update_fabric_api_data(mod, mod_version, mc_version, fapi_version): ) } - with open(data_file, "w") as f: - json.dump(data, f, indent=2) + util.write_json_file(data_file, data) def update_curseforge_data(mod, modloader, mod_version, mc_version, file_id): """Add a new entry to the CurseForge data file for a mod.""" - data_file = os.path.join("data", "curseforge", f"{mod}", f"{modloader}.json") - with open(data_file, "r") as f: - data = json.load(f) + data_file = Path("data") / "curseforge" / f"{mod}" / f"{modloader}.json" + data = util.read_json_file(data_file) # Add mod_version -> mc_version mapping unless it is already there if mod_version not in data: @@ -156,20 +97,15 @@ def update_curseforge_data(mod, modloader, mod_version, mc_version, file_id): ) } - with open(data_file, "w") as f: - json.dump(data, f, indent=2) + util.write_json_file(data_file, data) def add_download_category(mod, new_mcversion, old_mcversion): """Add a new download category when a mod is ported to a new Minecraft version.""" - old_page_path = os.path.join( - "content", mod, f"minecraft-{old_mcversion.replace('.', '-')}.html" - ) - new_page_path = os.path.join( - "content", mod, f"minecraft-{new_mcversion.replace('.', '-')}.html" - ) + old_page_path = Path("content") / mod / f"minecraft-{old_mcversion.replace('.', '-')}.html" + new_page_path = Path("content") / mod / f"minecraft-{new_mcversion.replace('.', '-')}.html" - front_matter = read_front_matter(old_page_path) + front_matter = util.read_post(old_page_path).front_matter title = front_matter["title"] description = front_matter["description"] @@ -177,9 +113,8 @@ def add_download_category(mod, new_mcversion, old_mcversion): front_matter["description"] = description.replace(old_mcversion, new_mcversion) front_matter["mcversion"] = new_mcversion - with open(new_page_path, "w", encoding="utf-8") as f: - f.writelines(["---", "---", "\n"]) - write_front_matter(new_page_path, front_matter) + new_page_path.write_text("---\n---\n", encoding="utf-8", newline="\n") + util.write_front_matter(new_page_path, front_matter) def main(mod, modloader, mod_version, mc_version, fapi_version, file_id): diff --git a/scripts/util.py b/scripts/util.py new file mode 100644 index 0000000..6e468fe --- /dev/null +++ b/scripts/util.py @@ -0,0 +1,86 @@ +import json +import os +from dataclasses import dataclass +from io import StringIO +from pathlib import Path +from ruamel.yaml import YAML +from ruamel.yaml.comments import CommentedMap, CommentedSeq + +yaml = YAML() +yaml.preserve_quotes = True + + +@dataclass +class JekyllPost: + front_matter: CommentedMap + content: str + path: Path + + +def read_post(path: Path) -> JekyllPost: + """Read front matter and content from a Jekyll/Hugo post.""" + content = path.read_text(encoding="utf-8") + parts = content.split("---", 2) + if len(parts) < 3: + raise ValueError(f"Invalid front matter format in {path}") + + return JekyllPost(yaml.load(parts[1]), parts[2].strip(), path) + + +def write_front_matter(path: Path, front_matter: CommentedMap): + """Write YAML front matter to a Jekyll/Hugo post while preserving content.""" + content = path.read_text(encoding="utf-8") + parts = content.split("---", 2) + if len(parts) < 3: + raise ValueError(f"Invalid front matter format in {path}") + + output = StringIO() + yaml.dump(front_matter, output) + new_content = f"---\n{output.getvalue()}---{parts[2]}" + path.write_text(new_content, encoding="utf-8", newline="\n") + + +def find_mod_update_post(mod: str, version: str) -> JekyllPost: + """Find the mod update post for a specific version.""" + posts_folder = Path("content") / mod + version_slug = version.replace(".", "-") + for post_path in posts_folder.rglob(f"*-{version_slug}.md"): + if not post_path.is_file(): + continue + + post = read_post(post_path) + if post.front_matter.get("modversion") == version: + return post + + raise ValueError(f"Could not find post for mod {mod} version {version}") + + +def read_yaml_file(path: Path) -> CommentedMap | CommentedSeq: + """Read a YAML data file.""" + return yaml.load(path.read_text(encoding="utf-8")) + + +def write_yaml_file(path: Path, data: CommentedMap | CommentedSeq): + """Write a YAML data file.""" + output = StringIO() + yaml.dump(data, output) + path.write_text(output.getvalue(), encoding="utf-8", newline="\n") + + +def read_json_file(path: Path) -> dict: + """Read a JSON data file.""" + return json.loads(path.read_text(encoding="utf-8")) + + +def write_json_file(path: Path, data: dict): + """Write a JSON data file.""" + path.write_text(json.dumps(data, indent=2), encoding="utf-8", newline="\n") + + +def set_github_output(key: str, value: str): + """Set a key-value pair in the GitHub Actions output.""" + if "GITHUB_OUTPUT" not in os.environ: + print(f"Not running on GHA, would have set output: {key}={value}") + return + with open(os.environ["GITHUB_OUTPUT"], "a") as env: + print(f"{key}={value}", file=env)