From 7aaf409ac9257f1bd8ffd6642e7e38359db6c947 Mon Sep 17 00:00:00 2001 From: desmondwong1215 Date: Thu, 19 Mar 2026 10:07:19 +0800 Subject: [PATCH 1/6] Update exercise_config --- app/configs/exercise_config.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/configs/exercise_config.py b/app/configs/exercise_config.py index b478e57..75238a3 100644 --- a/app/configs/exercise_config.py +++ b/app/configs/exercise_config.py @@ -18,6 +18,8 @@ class ExerciseRepoConfig: create_fork: Optional[bool] fork_all_branches: Optional[bool] init: Optional[bool] + pr_number: Optional[int] + pr_repo_full_name: Optional[str] exercise_name: str tags: List[str] @@ -75,6 +77,8 @@ def read(cls: Type[Self], path: Path, cds: int) -> Self: create_fork=exercise_repo["create_fork"], fork_all_branches=exercise_repo.get("fork_all_branches", None), init=exercise_repo["init"], + pr_number=exercise_repo.get("pr_number", None), + pr_repo_full_name=exercise_repo.get("pr_repo_full_name", None), ), downloaded_at=None, ) From 43687428651f3b261b5393b242d9200027feef82 Mon Sep 17 00:00:00 2001 From: desmondwong1215 Date: Thu, 19 Mar 2026 10:07:43 +0800 Subject: [PATCH 2/6] Enable closing pr during resetting --- app/commands/progress/reset.py | 7 ++++++- app/utils/github_cli.py | 38 ++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/app/commands/progress/reset.py b/app/commands/progress/reset.py index 748c2a0..f367895 100644 --- a/app/commands/progress/reset.py +++ b/app/commands/progress/reset.py @@ -26,7 +26,7 @@ warn, ) from app.utils.git import add_all, commit, push -from app.utils.github_cli import delete_repo, get_prs, get_username, pull_request +from app.utils.github_cli import close_pr, delete_repo, get_prs, get_username, pull_request from app.utils.gitmastery import ExercisesRepo @@ -56,6 +56,11 @@ def reset() -> None: os.chdir(exercise_config.path) info("Resetting the exercise folder") if is_remote_type and exercise_config.exercise_repo.create_fork: + pr_repo_full_name = exercise_config.exercise_repo.pr_repo_full_name + if pr_repo_full_name: + close_pr(pr_repo_full_name) + exercise_config.exercise_repo.pr_number = None + exercise_config.exercise_repo.pr_repo_full_name = None # Remove the fork first exercise_fork_name = ( f"{username}-gitmastery-{exercise_config.exercise_repo.repo_title}" diff --git a/app/utils/github_cli.py b/app/utils/github_cli.py index feb0be1..877550d 100644 --- a/app/utils/github_cli.py +++ b/app/utils/github_cli.py @@ -198,3 +198,41 @@ def get_user_prs(repo: str, owner: str) -> List[str]: prs = result.stdout.splitlines() return prs return [] + + +def close_pr(repo: str) -> None: + username = get_username() + + result = run( + [ + "gh", + "pr", + "list", + "--repo", + repo, + "--author", + username, + "--state", + "open", + "--json", + "number", + "--jq", + ".[].number", + ], + env={"GH_PAGER": "cat"}, + ) + + if not result.is_success(): + return + + for pr_number in result.stdout.splitlines(): + run( + [ + "gh", + "pr", + "close", + pr_number, + "--repo", + repo, + ], + ) \ No newline at end of file From ea4cf33d1941091ddd3c4fae2914436e37c3863a Mon Sep 17 00:00:00 2001 From: desmondwong1215 Date: Thu, 19 Mar 2026 10:07:59 +0800 Subject: [PATCH 3/6] Enable closing pr during re-downloading --- app/commands/download.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/commands/download.py b/app/commands/download.py index 6a07769..12f3905 100644 --- a/app/commands/download.py +++ b/app/commands/download.py @@ -24,6 +24,7 @@ from app.utils.git import add_all, commit, empty_commit, init from app.utils.github_cli import ( clone_with_custom_name, + close_pr, delete_repo, fork, get_username, @@ -49,6 +50,11 @@ def _download_exercise( if os.path.isdir(exercise): warn(f"You already have {exercise}, removing it to download again") + old_config = ExerciseConfig.read(Path(exercise), 0) + if old_config.exercise_repo.repo_type == "remote" and old_config.exercise_repo.create_fork: + pr_repo_full_name = old_config.exercise_repo.pr_repo_full_name + if pr_repo_full_name: + close_pr(pr_repo_full_name) rmtree(exercise) os.makedirs(exercise) From cf9e3d4ffdbea5f4b45e84de1e6965fb383500b4 Mon Sep 17 00:00:00 2001 From: desmondwong1215 Date: Wed, 25 Mar 2026 08:58:32 +0800 Subject: [PATCH 4/6] Add info message for closing pr --- app/commands/download.py | 1 + app/commands/progress/reset.py | 1 + 2 files changed, 2 insertions(+) diff --git a/app/commands/download.py b/app/commands/download.py index 12f3905..cd74aeb 100644 --- a/app/commands/download.py +++ b/app/commands/download.py @@ -54,6 +54,7 @@ def _download_exercise( if old_config.exercise_repo.repo_type == "remote" and old_config.exercise_repo.create_fork: pr_repo_full_name = old_config.exercise_repo.pr_repo_full_name if pr_repo_full_name: + info(f"Closing open PRs in {pr_repo_full_name} if exists...") close_pr(pr_repo_full_name) rmtree(exercise) diff --git a/app/commands/progress/reset.py b/app/commands/progress/reset.py index f367895..2d2d151 100644 --- a/app/commands/progress/reset.py +++ b/app/commands/progress/reset.py @@ -58,6 +58,7 @@ def reset() -> None: if is_remote_type and exercise_config.exercise_repo.create_fork: pr_repo_full_name = exercise_config.exercise_repo.pr_repo_full_name if pr_repo_full_name: + info(f"Closing open PRs in {pr_repo_full_name} if exists...") close_pr(pr_repo_full_name) exercise_config.exercise_repo.pr_number = None exercise_config.exercise_repo.pr_repo_full_name = None From 5de78e23351bc2abf97766720fb7db372855ec1a Mon Sep 17 00:00:00 2001 From: desmondwong1215 Date: Wed, 25 Mar 2026 09:03:20 +0800 Subject: [PATCH 5/6] Update info message for closing pr --- app/commands/download.py | 2 +- app/commands/progress/reset.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/commands/download.py b/app/commands/download.py index cd74aeb..afffa06 100644 --- a/app/commands/download.py +++ b/app/commands/download.py @@ -54,7 +54,7 @@ def _download_exercise( if old_config.exercise_repo.repo_type == "remote" and old_config.exercise_repo.create_fork: pr_repo_full_name = old_config.exercise_repo.pr_repo_full_name if pr_repo_full_name: - info(f"Closing open PRs in {pr_repo_full_name} if exists...") + info(f"Closing any open PRs in {pr_repo_full_name}...") close_pr(pr_repo_full_name) rmtree(exercise) diff --git a/app/commands/progress/reset.py b/app/commands/progress/reset.py index 2d2d151..7a00a49 100644 --- a/app/commands/progress/reset.py +++ b/app/commands/progress/reset.py @@ -58,7 +58,7 @@ def reset() -> None: if is_remote_type and exercise_config.exercise_repo.create_fork: pr_repo_full_name = exercise_config.exercise_repo.pr_repo_full_name if pr_repo_full_name: - info(f"Closing open PRs in {pr_repo_full_name} if exists...") + info(f"Closing any open PRs in {pr_repo_full_name}...") close_pr(pr_repo_full_name) exercise_config.exercise_repo.pr_number = None exercise_config.exercise_repo.pr_repo_full_name = None From 82b542278eaba1989e3f262d8fc1e5932cc5225f Mon Sep 17 00:00:00 2001 From: desmondwong1215 Date: Thu, 26 Mar 2026 07:43:38 +0800 Subject: [PATCH 6/6] Refactor code in download --- app/commands/download.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/app/commands/download.py b/app/commands/download.py index afffa06..854b700 100644 --- a/app/commands/download.py +++ b/app/commands/download.py @@ -48,14 +48,10 @@ def _download_exercise( f"Downloading {exercise} to {click.style(exercise + '/', bold=True, italic=True)}" ) + old_config: Optional[ExerciseConfig] = None if os.path.isdir(exercise): warn(f"You already have {exercise}, removing it to download again") old_config = ExerciseConfig.read(Path(exercise), 0) - if old_config.exercise_repo.repo_type == "remote" and old_config.exercise_repo.create_fork: - pr_repo_full_name = old_config.exercise_repo.pr_repo_full_name - if pr_repo_full_name: - info(f"Closing any open PRs in {pr_repo_full_name}...") - close_pr(pr_repo_full_name) rmtree(exercise) os.makedirs(exercise) @@ -101,6 +97,12 @@ def _download_exercise( warn("Setup Github and Github CLI before downloading this exercise") sys.exit(1) + if old_config and old_config.exercise_repo.repo_type == "remote" and old_config.exercise_repo.create_fork: + pr_repo_full_name = old_config.exercise_repo.pr_repo_full_name + if pr_repo_full_name: + info(f"Closing any open PRs in {pr_repo_full_name}...") + close_pr(pr_repo_full_name) + if len(config.base_files) > 0: info("Downloading base files...")