Merge remote-tracking branch 'origin/master' into review/pr496-fix

This commit is contained in:
Matthew Stanley
2026-10-04 11:03:07 -07:00
7 changed files with 0 additions and 262 deletions
@@ -21,7 +21,6 @@ from .gitops import (
push,
push_modules,
push_psxrecomp,
_git,
repo_status,
run_release_workflow,
switch_branch,
@@ -239,65 +238,6 @@ def bulk_migrate_bundled(
return map_repos(repos, one, jobs=jobs, on_repo=on_repo)
def _load_update_cmake():
"""Import tools/update_cmake.py from the framework running this tool, so
projects pinned to an older psxrecomp still get the current blocks."""
import importlib.util
path = Path(__file__).resolve().parents[2] / "update_cmake.py"
spec = importlib.util.spec_from_file_location("psx_update_cmake", path)
if spec is None or spec.loader is None or not path.is_file():
raise FileNotFoundError(f"update_cmake.py not found at {path}")
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)
return mod
def bulk_update_cmake(
repos: list[tuple[str, Path]],
*,
commit: bool = True,
push_remote: bool = False,
dry_run: bool = False,
jobs: int = 1,
on_repo: OnRepoResults | None = None,
) -> list[CmdResult]:
"""Sync each repo's CMakeLists.txt with the scaffold template's managed
blocks (tools/update_cmake.py), committing only CMakeLists.txt."""
um = _load_update_cmake()
def one(label: str, root: Path) -> list[CmdResult]:
path = root / "CMakeLists.txt"
if not path.is_file():
return [CmdResult(False, f"{label}: no CMakeLists.txt")]
try:
old = path.read_text(encoding="utf-8")
new = um.sync(old)
except (OSError, SystemExit) as exc:
return [CmdResult(False, f"{label}: {exc}")]
if new == old:
return [CmdResult(True, f"{label}: CMakeLists.txt up to date")]
if dry_run:
return [CmdResult(True, f"{label}: would update CMakeLists.txt")]
path.write_text(new, encoding="utf-8", newline="")
if not commit:
return [CmdResult(True, f"{label}: updated CMakeLists.txt (uncommitted)")]
msg = "CMake: sync managed blocks (update_cmake)"
code, out, err = _git(root, "add", "--", "CMakeLists.txt")
if code == 0:
code, out, err = _git(root, "commit", "-m", msg, "--", "CMakeLists.txt")
if code != 0:
return [CmdResult(False, f"{label}: updated but commit failed", err or out)]
if push_remote:
r = push(root)
if not r.ok:
return [CmdResult(False, f"{label}: committed, push failed", r.detail)]
return [CmdResult(True, f"{label}: updated, committed, pushed")]
return [CmdResult(True, f"{label}: updated + committed")]
return map_repos(repos, one, jobs=jobs, on_repo=on_repo)
def bulk_pull(
repos: list[tuple[str, Path]],
*,
@@ -1337,35 +1337,6 @@ def cmd_git_bulk_migrate_bundled(args: argparse.Namespace) -> int:
return 1 if failed else 0
def cmd_git_bulk_update_cmake(args: argparse.Namespace) -> int:
from project_studio.bulkops import bulk_update_cmake
from project_studio.repo_index import load_index
repos = _bulk_repos_or_die(args)
if repos is None:
return 2
jobs = int(getattr(args, "jobs", 0) or 0) or int(getattr(load_index(), "bulk_jobs", 1) or 1)
def on_repo(label: str, results: list) -> None:
for r in results:
print(f" [{'OK' if r.ok else 'FAIL'}] {r.message}", flush=True)
if r.detail:
for ln in r.detail.splitlines():
print(f" {ln}", flush=True)
results = bulk_update_cmake(
repos,
commit=not bool(getattr(args, "no_commit", False)),
push_remote=bool(getattr(args, "push", False)),
dry_run=bool(getattr(args, "dry_run", False)),
jobs=jobs,
on_repo=on_repo,
)
failed = sum(1 for r in results if not r.ok)
print(f"bulk update-cmake: {len(results) - failed} ok, {failed} failed", flush=True)
return 1 if failed else 0
def cmd_git_migrate_bundled(args: argparse.Namespace) -> int:
from project_studio.migrate_bundled import BundledMigrateOptions, migrate_to_bundled_release
@@ -2329,17 +2300,6 @@ def build_parser() -> argparse.ArgumentParser:
p_gbmb.add_argument("--jobs", type=int, default=0, help="Parallel repos (default: index setting)")
p_gbmb.set_defaults(func=cmd_git_bulk_migrate_bundled)
p_gbuc = git_sub.add_parser(
"bulk-update-cmake",
help="Sync selected repos' CMakeLists.txt with the scaffold template "
"(tools/update_cmake.py); commits CMakeLists.txt only",
)
add_bulk_select(p_gbuc)
p_gbuc.add_argument("--no-commit", action="store_true", help="Edit CMakeLists.txt but do not commit")
p_gbuc.add_argument("--push", action="store_true", help="Push after committing")
p_gbuc.add_argument("--jobs", type=int, default=0, help="Parallel repos (default: index setting)")
p_gbuc.set_defaults(func=cmd_git_bulk_update_cmake)
p_gmb = git_sub.add_parser(
"migrate-bundled",
help="Move one game repo onto bundled releases",
@@ -2241,13 +2241,6 @@ class ProjectStudioApp:
height=34,
command=self._bulk_install_ci,
).pack(side="left", padx=8)
ctk.CTkButton(
relb,
text="Update CMake",
width=120,
height=34,
command=self._bulk_update_cmake,
).pack(side="left")
ctk.CTkLabel(
relb,
text="Dispatches release.yml per selected game repo (gh). "
@@ -4547,36 +4540,6 @@ class ProjectStudioApp:
done_warn_prefix="Release dispatch finished with failures.",
)
def _bulk_update_cmake(self) -> None:
from .bulkops import bulk_update_cmake
repos = self._bulk_require_selection()
if repos is None:
return
dry = self._git_dry()
if not dry:
names = "\n".join(f"* {lab}" for lab, _ in repos)
if not messagebox.askyesno(
"Project Studio",
f"Sync CMakeLists.txt with the psxrecomp template and commit it "
f"(CMakeLists.txt only, not pushed) for {len(repos)} repo(s)?\n\n{names}",
parent=self.root,
):
return
def run(*, jobs: int, on_repo) -> list:
return bulk_update_cmake(
repos, commit=True, push_remote=False, dry_run=dry, jobs=jobs, on_repo=on_repo
)
self._bulk_run_bg(
f"Bulk update CMake ({len(repos)} repos)",
run,
refresh_git=True,
done_info="Update CMake finished — see activity log.",
done_warn_prefix="Update CMake finished with failures.",
)
def _bulk_install_ci(self) -> None:
from .bulkops import bulk_install_ci
@@ -49,16 +49,6 @@ psxrecomp_add_game_runtime(psx-runtime
@CODEGEN_SETUP_ARG@
)
# >>> psxrecomp:recomp-net-headers (managed by tools/update_cmake.{sh,ps1})
# runtime/src/main.cpp includes recomp_net/host_relay.h unconditionally (a
# plain-C types header). With PSX_NETPLAY off nothing adds recomp-net's include
# dir, so expose it whenever the submodule is checked out.
if(EXISTS "${PSXRECOMP_ROOT}/lib/recomp-net/include/recomp_net/host_relay.h")
target_include_directories(psx-runtime PRIVATE
"${PSXRECOMP_ROOT}/lib/recomp-net/include")
endif()
# <<< psxrecomp:recomp-net-headers
# Stage runtime configs next to the exe for direct build/ launches. Only copy
# files that exist — never fail POST_BUILD when game_options.toml is absent.
foreach(_PSX_RUNTIME_CONFIG game.toml game_options.toml)
-14
View File
@@ -1,14 +0,0 @@
# update_cmake.ps1 — sync a game project's CMakeLists.txt with the scaffold
# template's managed blocks (implementation: tools/update_cmake.py).
# Usage: update_cmake.ps1 [--project DIR] [--check] [--dry-run]
$ErrorActionPreference = 'Stop'
$Root = Split-Path -Parent $PSScriptRoot
$Py = $env:PYTHON
if (-not $Py) {
foreach ($c in 'python3', 'python', 'py') {
if (Get-Command $c -ErrorAction SilentlyContinue) { $Py = $c; break }
}
}
if (-not $Py) { Write-Error 'update_cmake: python not found on PATH'; exit 1 }
& $Py (Join-Path $Root 'tools/update_cmake.py') @args
exit $LASTEXITCODE
-89
View File
@@ -1,89 +0,0 @@
#!/usr/bin/env python3
"""Idempotently sync a game project's CMakeLists.txt with the scaffold template.
The managed block lives in tools/new_project_layout/templates/CMakeLists.txt.in
between `# >>> psxrecomp:<name>` / `# <<< psxrecomp:<name>` markers (single
source of truth). For each block this inserts it after the project's
psxrecomp_add_game_runtime(...) call, or replaces it in place if the markers are
already present. Run via tools/update_cmake.sh or tools/update_cmake.ps1.
update_cmake.py [--project DIR] [--check] [--dry-run]
--check exit 1 if the project is out of date (writes nothing; for CI)
--dry-run print the unified diff, write nothing
"""
import argparse, difflib, re, sys
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
TEMPLATE = ROOT / "tools/new_project_layout/templates/CMakeLists.txt.in"
BLOCK_RE = re.compile(
r"^# >>> psxrecomp:(?P<n>[\w-]+).*?\n.*?^# <<< psxrecomp:(?P=n)[ \t]*\n",
re.M | re.S)
def template_blocks():
return {m["n"]: m.group(0) for m in BLOCK_RE.finditer(TEMPLATE.read_text(encoding="utf-8"))}
def add_runtime_end(text):
"""Index just past the closing ')' of psxrecomp_add_game_runtime(...)."""
m = re.search(r"^\s*psxrecomp_add_game_runtime\s*\(", text, re.M)
if not m:
return None
depth, i, in_str = 0, m.end() - 1, False
while i < len(text):
c = text[i]
if c == '"' and text[i - 1] != "\\":
in_str = not in_str
elif not in_str:
if c == "#":
i = text.find("\n", i)
if i < 0:
return None
continue
depth += c == "("
depth -= c == ")"
if depth == 0:
nl = text.find("\n", i)
return len(text) if nl < 0 else nl + 1
i += 1
return None
def sync(text):
for name, block in template_blocks().items():
m = re.search(r"^# >>> psxrecomp:%s.*?\n.*?^# <<< psxrecomp:%s[ \t]*\n" % (re.escape(name), re.escape(name)), text, re.M | re.S)
if m:
text = text[:m.start()] + block + text[m.end():]
continue
end = add_runtime_end(text)
if end is None:
sys.exit("update_cmake: no psxrecomp_add_game_runtime(...) call found")
text = text[:end] + "\n" + block + text[end:]
return text
def main():
ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
ap.add_argument("--project", default=".", help="game project dir (default: cwd)")
ap.add_argument("--check", action="store_true")
ap.add_argument("--dry-run", action="store_true")
a = ap.parse_args()
path = Path(a.project).resolve() / "CMakeLists.txt"
if not path.is_file():
sys.exit(f"update_cmake: {path} not found")
old = path.read_text(encoding="utf-8")
new = sync(old)
if new == old:
print("update_cmake: up to date")
return 0
if a.check or a.dry_run:
sys.stdout.writelines(difflib.unified_diff(old.splitlines(True), new.splitlines(True), "CMakeLists.txt", "CMakeLists.txt (updated)"))
return 1 if a.check else 0
path.write_text(new, encoding="utf-8", newline="")
print(f"update_cmake: updated {path}")
return 0
if __name__ == "__main__":
sys.exit(main())
-12
View File
@@ -1,12 +0,0 @@
#!/usr/bin/env bash
# update_cmake.sh — sync a game project's CMakeLists.txt with the scaffold
# template's managed blocks (implementation: tools/update_cmake.py).
# Usage: update_cmake.sh [--project DIR] [--check] [--dry-run]
set -eu
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
PY="${PYTHON:-}"
if [ -z "$PY" ]; then
for c in python3 python; do command -v "$c" >/dev/null 2>&1 && { PY="$c"; break; }; done
fi
[ -n "$PY" ] || { echo "update_cmake: python not found on PATH" >&2; exit 1; }
exec "$PY" "$ROOT/tools/update_cmake.py" "$@"