Skip to content

Commit 974d2f0

Browse files
committed
feat: add several utility functions and bits of logic to ensure branches are synced before scripts run
1 parent f375134 commit 974d2f0

File tree

3 files changed

+39
-3
lines changed

3 files changed

+39
-3
lines changed

scripts/lint-from-demo.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import typer
66
from retrocookie.core import retrocookie
77

8+
from scripts.util import is_repo_clean_and_up_to_date
9+
from scripts.util import require_clean_and_up_to_date_repo
810
from util import git
911
from util import FolderOption
1012
from util import in_new_demo
@@ -32,7 +34,7 @@ def lint_from_demo(
3234
add_rust_extension=add_rust_extension,
3335
no_cache=no_cache
3436
) as demo_path:
35-
git("status", "--porcelain")
37+
require_clean_and_up_to_date_repo()
3638
git("checkout", "develop")
3739
git("branch", "-D", "temp/lint-from-demo", ignore_error=True)
3840
git("checkout", "-b", "temp/lint-from-demo", "develop")

scripts/update-demo.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import typer
77
from cookiecutter.utils import work_in
88

9+
from scripts.util import is_repo_clean_and_up_to_date
10+
from scripts.util import require_clean_and_up_to_date_repo
911
from util import get_demo_name
1012
from util import git
1113
from util import FolderOption
@@ -26,7 +28,7 @@ def update_demo(
2628
demo_path: Path = demos_cache_folder / demo_name
2729
typer.secho(f"Updating demo project at {demo_path=}.", fg="yellow")
2830
with work_in(demo_path):
29-
git("status", "--porcelain")
31+
require_clean_and_up_to_date_repo()
3032
cruft.update(
3133
project_dir=demo_path,
3234
template_path=REPO_FOLDER,

scripts/util.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import cruft
1818
import typer
1919
from cookiecutter.utils import work_in
20-
from pygments.lexers import q
2120
from typer.models import OptionInfo
2221

2322

@@ -65,6 +64,39 @@ def run_command(command: str, *args: str, ignore_error: bool = False) -> Optiona
6564
uv: partial[subprocess.CompletedProcess] = partial(run_command, "uv")
6665

6766

67+
def require_clean_and_up_to_date_repo() -> None:
68+
"""Checks if the repo is clean and up to date with any important branches."""
69+
if not is_repo_clean_and_up_to_date():
70+
typer.secho("The repo is either not clean or is not up to date.", fg="red")
71+
raise typer.Exit(code=1)
72+
73+
74+
def is_repo_clean_and_up_to_date() -> bool:
75+
"""Checks if the repo is clean and up to date with any important branches."""
76+
try:
77+
git("fetch")
78+
git("status", "--porcelain")
79+
if not is_branch_synced_with_remote("develop"):
80+
raise ValueError("develop is not synced with origin/develop")
81+
if not is_branch_synced_with_remote("main"):
82+
raise ValueError("main is not synced with origin/main")
83+
if not is_ancestor("main", "develop"):
84+
raise ValueError("main is not an ancestor of develop")
85+
return True
86+
except subprocess.CalledProcessError:
87+
return False
88+
89+
90+
def is_branch_synced_with_remote(branch: str) -> bool:
91+
"""Checks if the branch is synced with its remote."""
92+
return is_ancestor(branch, f"origin/{branch}") and is_ancestor(f"origin/{branch}", branch)
93+
94+
95+
def is_ancestor(ancestor: str, descendent: str) -> bool:
96+
"""Checks if the branch is synced with its remote."""
97+
return git("merge-base", "--is-ancestor", ancestor, descendent).returncode == 0
98+
99+
68100
@contextmanager
69101
def in_new_demo(
70102
demos_cache_folder: Path,

0 commit comments

Comments
 (0)