try a python script in runner
This commit is contained in:
226
scripts/bundle.py
Executable file
226
scripts/bundle.py
Executable file
@@ -0,0 +1,226 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import xml.etree.ElementTree as ET
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
INKSCAPE_NS = "http://www.inkscape.org/namespace/inkscape/extension"
|
||||
ET.register_namespace("", INKSCAPE_NS)
|
||||
|
||||
REPOS = [
|
||||
{
|
||||
"name": "botbox3000",
|
||||
"url": "https://github.com/jondale/botbox3000.git",
|
||||
"branch": "main",
|
||||
"directory": "botbox3000",
|
||||
"inx_file": "boxbot.inx",
|
||||
"id": "org.knoxmakers.botbox",
|
||||
"submenu": ["Knox Makers", "Laser"],
|
||||
},
|
||||
{
|
||||
"name": "km-living-hinge",
|
||||
"url": "https://github.com/KnoxMakers/km-living-hinge.git",
|
||||
"branch": "main",
|
||||
"directory": "km-living-hinge",
|
||||
},
|
||||
{
|
||||
"name": "km-plot",
|
||||
"url": "https://git.knoxmakers.org/KnoxMakers/km-plot.git",
|
||||
"branch": "main",
|
||||
"directory": "km-plot",
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def run(cmd: list[str], cwd: str | None = None) -> str:
|
||||
result = subprocess.run(cmd, cwd=cwd, capture_output=True, text=True, check=True)
|
||||
return result.stdout.strip()
|
||||
|
||||
|
||||
def has_staged_changes(root: Path) -> bool:
|
||||
result = subprocess.run(
|
||||
["git", "diff", "--cached", "--quiet"],
|
||||
cwd=root,
|
||||
capture_output=True,
|
||||
)
|
||||
return result.returncode != 0
|
||||
|
||||
|
||||
def sync_repo(repo: dict, ext_dir: Path, tmp_dir: Path) -> None:
|
||||
name = repo["name"]
|
||||
url = repo["url"]
|
||||
branch = repo.get("branch", "main")
|
||||
directory = repo["directory"]
|
||||
|
||||
work = tmp_dir / name
|
||||
target = ext_dir / directory
|
||||
|
||||
print(f"==> Sync {name} from {url} ({branch}) -> extensions/{directory}")
|
||||
|
||||
subprocess.run(
|
||||
["git", "clone", "--depth", "1", "--branch", branch, url, str(work)],
|
||||
check=True,
|
||||
)
|
||||
|
||||
if target.exists():
|
||||
shutil.rmtree(target)
|
||||
shutil.copytree(work, target)
|
||||
|
||||
git_dir = target / ".git"
|
||||
if git_dir.exists():
|
||||
shutil.rmtree(git_dir)
|
||||
|
||||
commit = run(["git", "rev-parse", "HEAD"], cwd=str(work))
|
||||
(target / ".upstream_commit").write_text(commit + "\n")
|
||||
(target / ".upstream_url").write_text(url + "\n")
|
||||
(target / ".upstream_branch").write_text(branch + "\n")
|
||||
|
||||
|
||||
def set_extension_id(root: ET.Element, new_id: str) -> bool:
|
||||
ns = {"ink": INKSCAPE_NS}
|
||||
|
||||
id_elem = root.find("ink:id", ns)
|
||||
if id_elem is None:
|
||||
id_elem = root.find("id")
|
||||
|
||||
if id_elem is not None:
|
||||
if id_elem.text != new_id:
|
||||
id_elem.text = new_id
|
||||
return True
|
||||
return False
|
||||
|
||||
name_elem = root.find("ink:name", ns)
|
||||
if name_elem is None:
|
||||
name_elem = root.find("name")
|
||||
|
||||
id_elem = ET.Element("id")
|
||||
id_elem.text = new_id
|
||||
|
||||
if name_elem is not None:
|
||||
idx = list(root).index(name_elem)
|
||||
root.insert(idx + 1, id_elem)
|
||||
else:
|
||||
root.insert(0, id_elem)
|
||||
return True
|
||||
|
||||
|
||||
def set_effects_submenu(root: ET.Element, submenus: list[str]) -> bool:
|
||||
ns = {"ink": INKSCAPE_NS}
|
||||
|
||||
effect_elem = root.find(".//ink:effect", ns)
|
||||
if effect_elem is None:
|
||||
effect_elem = root.find(".//effect")
|
||||
|
||||
if effect_elem is None:
|
||||
return False
|
||||
|
||||
menu_elem = None
|
||||
for tag in ["effects-menu", "effectsmenu"]:
|
||||
menu_elem = effect_elem.find(tag)
|
||||
if menu_elem is not None:
|
||||
break
|
||||
menu_elem = effect_elem.find(f"ink:{tag}", ns)
|
||||
if menu_elem is not None:
|
||||
break
|
||||
|
||||
if menu_elem is None:
|
||||
return False
|
||||
|
||||
menu_elem.clear()
|
||||
menu_elem.tag = "effects-menu"
|
||||
|
||||
parent = menu_elem
|
||||
for i, submenu_name in enumerate(submenus):
|
||||
submenu = ET.SubElement(parent, "submenu")
|
||||
submenu.set("_name", submenu_name)
|
||||
if i < len(submenus) - 1:
|
||||
parent = submenu
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def patch_inx(inx_path: Path, extension_id: str | None, submenus: list[str] | None) -> bool:
|
||||
if not inx_path.exists():
|
||||
print(f"ERROR: expected file not found: {inx_path}")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"Patching {inx_path}")
|
||||
|
||||
tree = ET.parse(inx_path)
|
||||
root = tree.getroot()
|
||||
|
||||
modified = False
|
||||
|
||||
if extension_id is not None:
|
||||
if set_extension_id(root, extension_id):
|
||||
modified = True
|
||||
|
||||
if submenus is not None:
|
||||
if set_effects_submenu(root, submenus):
|
||||
modified = True
|
||||
|
||||
if modified:
|
||||
ET.indent(tree, space=" ")
|
||||
tree.write(inx_path, encoding="UTF-8", xml_declaration=True)
|
||||
|
||||
content = inx_path.read_text(encoding="utf-8")
|
||||
if not content.endswith("\n"):
|
||||
inx_path.write_text(content + "\n", encoding="utf-8")
|
||||
|
||||
return modified
|
||||
|
||||
|
||||
def process_repo(repo: dict, ext_dir: Path) -> None:
|
||||
inx_file = repo.get("inx_file")
|
||||
extension_id = repo.get("id")
|
||||
submenus = repo.get("submenu")
|
||||
|
||||
if inx_file and (extension_id or submenus):
|
||||
inx_path = ext_dir / repo["directory"] / inx_file
|
||||
patch_inx(inx_path, extension_id, submenus)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
root = Path(__file__).resolve().parent.parent
|
||||
ext_dir = root / "extensions"
|
||||
ext_dir.mkdir(exist_ok=True)
|
||||
|
||||
os.chdir(root)
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
tmp_dir = Path(tmp)
|
||||
|
||||
for repo in REPOS:
|
||||
sync_repo(repo, ext_dir, tmp_dir)
|
||||
|
||||
subprocess.run(["git", "add", "extensions"], check=True)
|
||||
|
||||
if not has_staged_changes(root):
|
||||
print("No bundle changes.")
|
||||
sys.exit(0)
|
||||
|
||||
subprocess.run(["git", "checkout", "extensions"], check=True)
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
tmp_dir = Path(tmp)
|
||||
|
||||
for repo in REPOS:
|
||||
sync_repo(repo, ext_dir, tmp_dir)
|
||||
process_repo(repo, ext_dir)
|
||||
|
||||
subprocess.run(["git", "add", "extensions"], check=True)
|
||||
|
||||
date_str = datetime.now(timezone.utc).strftime("%Y-%m-%d")
|
||||
subprocess.run(
|
||||
["git", "commit", "-m", f"bundle: update ({date_str})"],
|
||||
check=True,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user