mirror of
https://github.com/4jcraft/4jcraft.git
synced 2026-04-28 23:23:38 +00:00
131 lines
3.3 KiB
Python
131 lines
3.3 KiB
Python
#!/usr/bin/env python3
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import site
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
|
|
PATHS_TO_KEEP = [
|
|
"4J.Common",
|
|
"4J.Input",
|
|
"4J.Profile",
|
|
"4J.Render",
|
|
"4J.Storage",
|
|
"4jlibs",
|
|
]
|
|
|
|
|
|
def run(cmd: list[str], cwd: Path | None = None) -> None:
|
|
subprocess.run(cmd, cwd=cwd, check=True)
|
|
|
|
|
|
def require_clean_destination(dest: Path) -> None:
|
|
if dest.exists():
|
|
raise SystemExit(f"Destination already exists: {dest}")
|
|
|
|
|
|
def resolve_filter_repo_command() -> list[str]:
|
|
script_name = "git-filter-repo.exe" if sys.platform == "win32" else "git-filter-repo"
|
|
|
|
path_candidates = [
|
|
shutil.which("git-filter-repo"),
|
|
shutil.which(script_name),
|
|
]
|
|
|
|
user_script_dirs = [
|
|
Path(site.USER_BASE) / "Scripts",
|
|
Path(site.getusersitepackages()).parent / "Scripts",
|
|
]
|
|
|
|
for script_dir in user_script_dirs:
|
|
user_scripts = script_dir / script_name
|
|
path_candidates.append(str(user_scripts) if user_scripts.exists() else None)
|
|
|
|
for candidate in path_candidates:
|
|
if candidate:
|
|
return [candidate]
|
|
|
|
raise SystemExit(
|
|
"git-filter-repo is required. Install it first and rerun this script."
|
|
)
|
|
|
|
|
|
def clone_source(source: Path, dest: Path) -> None:
|
|
run(["git", "clone", "--no-local", str(source), str(dest)])
|
|
|
|
|
|
def filter_history(dest: Path) -> None:
|
|
cmd = resolve_filter_repo_command() + ["--force"]
|
|
for path in PATHS_TO_KEEP:
|
|
cmd.extend(["--path", path])
|
|
run(cmd, cwd=dest)
|
|
|
|
|
|
def rewrite_staged_layout(dest: Path) -> None:
|
|
staged_root = dest / "4jlibs"
|
|
meson_src = staged_root / "meson.build"
|
|
builddef_src = staged_root / "builddef"
|
|
|
|
if not meson_src.exists() or not builddef_src.exists():
|
|
raise SystemExit("Filtered tree is missing the staged 4jlibs Meson files.")
|
|
|
|
shutil.move(str(meson_src), str(dest / "meson.build"))
|
|
shutil.move(str(builddef_src), str(dest / "builddef"))
|
|
|
|
try:
|
|
staged_root.rmdir()
|
|
except OSError:
|
|
pass
|
|
|
|
builddef_meson = dest / "builddef" / "meson.build"
|
|
builddef_smoke = dest / "builddef" / "header_smoke.cpp"
|
|
|
|
builddef_meson.write_text(
|
|
builddef_meson.read_text(encoding="utf-8").replace("../../", "../"),
|
|
encoding="utf-8",
|
|
)
|
|
builddef_smoke.write_text(
|
|
builddef_smoke.read_text(encoding="utf-8").replace("../../", "../"),
|
|
encoding="utf-8",
|
|
)
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(
|
|
description=(
|
|
"Create a filtered 4jlibs bootstrap repo from the current 4jcraft tree."
|
|
)
|
|
)
|
|
parser.add_argument(
|
|
"destination",
|
|
type=Path,
|
|
help="Path to create the filtered 4jlibs clone in",
|
|
)
|
|
parser.add_argument(
|
|
"--source",
|
|
type=Path,
|
|
default=Path.cwd(),
|
|
help="Source 4jcraft repo to clone from (default: current working directory)",
|
|
)
|
|
args = parser.parse_args()
|
|
|
|
source = args.source.resolve()
|
|
destination = args.destination.resolve()
|
|
|
|
require_clean_destination(destination)
|
|
clone_source(source, destination)
|
|
filter_history(destination)
|
|
rewrite_staged_layout(destination)
|
|
|
|
print(f"Created filtered 4jlibs bootstrap repo at: {destination}")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|