diff --git a/README.md b/README.md index ba7e58f..625e2bc 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,6 @@ updateproject backend # one part newproject ~/projects/my-thing --parts backend,frontend,caddy --backend python --frontend svelte --serve bun --defaults ``` -One part alone is rendered at the root of the project; two parts live in `backend/` and `frontend/`. After rendering, `make env` creates `.env` and every `docker-compose.override.yml` from their examples. Templates are cloned from `https://git.kotikot.com/templates` unless `TEMPLATES_DIR` points at a directory with local checkouts; `TEMPLATES_REF=HEAD` renders their working trees instead of the latest tag. +One part alone is rendered at the root of the project; two parts live in `backend/` and `frontend/`. After rendering, `make env` creates `.env` and every `docker-compose.override.yml` from their examples. `updateproject` needs a clean working tree and commits each part's update separately, so the next part starts from a clean tree again; conflicts stay in those commits for you to resolve. Templates are cloned from `https://git.kotikot.com/templates` unless `TEMPLATES_DIR` points at a directory with local checkouts; `TEMPLATES_REF=HEAD` renders their working trees instead of the latest tag. Requires `uv`; `bun`, `docker` and `pre-commit` are used by the generated projects. diff --git a/templates.py b/templates.py index 2673a47..63fda66 100644 --- a/templates.py +++ b/templates.py @@ -90,15 +90,26 @@ def new(args: argparse.Namespace) -> None: subprocess.run(["make", "env"], cwd=dest, check=True) +def git_dirty() -> bool: + result = subprocess.run(["git", "status", "--porcelain"], capture_output=True, text=True, check=False) + return bool(result.stdout.strip()) + + def update(args: argparse.Namespace) -> None: answers = sorted(Path(".copier").glob("*.yml")) if args.parts: answers = [Path(".copier") / f"{p}.yml" for p in args.parts] if not answers: sys.exit("no .copier/*.yml here") + if git_dirty(): + sys.exit("working tree is dirty, commit or stash first") for file in answers: run_update(".", answers_file=str(file), unsafe=True, overwrite=True, skip_answered=not args.ask, defaults=args.defaults, vcs_ref=REF) + if git_dirty(): + subprocess.run(["git", "add", "-A"], check=True) + subprocess.run(["git", "commit", "-qm", f"Update {file.stem} template"], check=True) + print(f"committed {file.stem} update") def main() -> None: