From f3adb79af743f574bf6acd0091e22d51b7b2e8dd Mon Sep 17 00:00:00 2001 From: Vikram Goyal Date: Sun, 26 Oct 2025 17:07:05 +0800 Subject: [PATCH 1/8] Implement hands on hp-update-remote --- hands_on/update_remote.py | 60 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 hands_on/update_remote.py diff --git a/hands_on/update_remote.py b/hands_on/update_remote.py new file mode 100644 index 0000000..b9b1784 --- /dev/null +++ b/hands_on/update_remote.py @@ -0,0 +1,60 @@ +import os +import subprocess + +from exercise_utils.cli import run_command +from exercise_utils.file import create_or_update_file, append_to_file +from exercise_utils.git import add, init, commit + +__requires_git__ = True +__requires_github__ = True + +REPO_NAME = "gitmastery-update-remote-things" + +def download(verbose: bool): + username = run_command(["gh", "api", "user", "-q", ".login"], verbose).strip() + os.makedirs("things") + os.chdir("things") + init(verbose) + create_or_update_file("fruits.txt", """ + apples + bananas + cherries + dragon fruits + """, + ) + add(["fruits.txt"], verbose) + append_to_file("fruits.txt", """ + figs + """, + ) + add(["fruits.txt"], verbose) + commit("Insert figs into fruits.txt", verbose) + create_or_update_file("colours.txt", """ + a file for colours + """, + ) + create_or_update_file("shapes.txt", """ + a file for shapes + """, + ) + add(["colours.txt", "shapes.txt"], verbose) + commit("Add colours.txt, shapes.txt", verbose) + repo_check = subprocess.run( + ["gh", "repo", "view", f"{username}/{REPO_NAME}"], + capture_output=True, + text=True + ) + + if repo_check.returncode == 0: + run_command(["gh", "repo", "delete", REPO_NAME, "--yes"], verbose) + + run_command(["gh", "repo", "create", REPO_NAME, "--public"], verbose) + run_command(["git", "remote", "add", "origin", f"https://github.com/{username}/{REPO_NAME}"], verbose) + + default_branch = run_command(["git", "branch", "--list", "main", "master"], verbose).strip() + if "main" in default_branch: + default_branch = "main" + else: + default_branch = "master" + + run_command(["git", "push", "-u", "origin", default_branch], verbose) \ No newline at end of file From 2730e8cd6c5f73a9b38d8d542ef12588eb73b9f5 Mon Sep 17 00:00:00 2001 From: Vikram Goyal Date: Mon, 27 Oct 2025 09:25:59 +0800 Subject: [PATCH 2/8] Fix repo naming --- hands_on/update_remote.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hands_on/update_remote.py b/hands_on/update_remote.py index b9b1784..0a3347b 100644 --- a/hands_on/update_remote.py +++ b/hands_on/update_remote.py @@ -8,7 +8,7 @@ __requires_git__ = True __requires_github__ = True -REPO_NAME = "gitmastery-update-remote-things" +REPO_NAME = "gitmastery-things" def download(verbose: bool): username = run_command(["gh", "api", "user", "-q", ".login"], verbose).strip() From 31b7d9dfd826d1f5c6255573b9b99fd4d6e8b132 Mon Sep 17 00:00:00 2001 From: "Jiahao, Woo" Date: Tue, 28 Oct 2025 22:21:58 +0000 Subject: [PATCH 3/8] [tooling] Fix test script for all OS --- README.md | 26 +------------------------- test.sh | 13 ++++++++++++- 2 files changed, 13 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 3839013..083da2e 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,3 @@ # exercises -## Git-Mastery exercise structure - -When you download an exercise, you will get the following folder structure: - - -## `.gitmastery-exercise.json` - -Configuration fields for each exercise: - -1. `exercise_name`: name of exercise -2. `tags`: list of tags for exercise -3. `requires_git`: downloading the exercise will check that Git is installed and that `git config` is already done -4. `requires_github`: downloading the exercise will check that Github and Github CLI is installed -5. `base_files`: provides the files to be included outside of the repository, along with `.gitmastery-exercise.json` and `README.md`, most often used for `answers.txt` -6. `exercise_repo`: configuration for what the exercise repository would look like - 1. `repo_type`: `local` (creates and initializes the folder as a Git repository) or `remote` (reference a repository on Github) - 2. `repo_name`: name of repository during cloning - 3. `repo_title`: (only read if `link` is present) link of repository on Github - 4. `create_fork`: (only read if `link` is present) flag to determine if we need to fork the repository to the student's machine, otherwise it just clones the repository - 5. `init`: (only read if `custom` is present) flag to determine if we will call `git init` on the exercise repository (useful if we don't want to start out with a Git repository) - - -## TODOs - -- [X] Add validation for exercise configuration (e.g. cannot fork + not require Github) - to run as CI +For more details, refer to the official developer documentation: https://git-mastery.github.io/developers diff --git a/test.sh b/test.sh index 20bf59b..513228c 100755 --- a/test.sh +++ b/test.sh @@ -1,5 +1,16 @@ #!/bin/bash +set -e -source venv/bin/activate +if [ -f "venv/bin/activate" ]; then + # Linux / macOS + source venv/bin/activate +elif [ -f "venv/Scripts/activate" ]; then + # Windows (Git Bash, Cygwin, or WSL) + source venv/Scripts/activate +else + echo "Error: Could not find Python virtual environment activation script." + echo "Please create one with: python -m venv venv" + exit 1 +fi python -m pytest $1/tests/test_verify.py -s -vv From 414eaa70a96038fa5c32aa2ad12d913650a9b936 Mon Sep 17 00:00:00 2001 From: jovnc <95868357+jovnc@users.noreply.github.com> Date: Sun, 26 Oct 2025 00:28:19 +0800 Subject: [PATCH 4/8] Implement hands on hp-list-commits --- hands_on/list_commits.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 hands_on/list_commits.py diff --git a/hands_on/list_commits.py b/hands_on/list_commits.py new file mode 100644 index 0000000..026dc18 --- /dev/null +++ b/hands_on/list_commits.py @@ -0,0 +1,22 @@ +import os + +from exercise_utils.file import append_to_file +from exercise_utils.git import add, commit, init + +__requires_git__ = True +__requires_github__ = False + + +def download(verbose: bool): + os.makedirs("things") + os.chdir("things") + + init(verbose) + + append_to_file( + "fruits.txt", + "apples\nbananas\ncherries\ndragon fruits\n" + ) + + add(["fruits.txt"], verbose) + commit("Add fruits.txt", verbose) \ No newline at end of file From b8e4a7cc1107ec27e3c22f025742dda583ecf6c7 Mon Sep 17 00:00:00 2001 From: jovnc <95868357+jovnc@users.noreply.github.com> Date: Sun, 26 Oct 2025 17:15:31 +0800 Subject: [PATCH 5/8] fix: Use create_or_update_file instead of append_to_file --- hands_on/list_commits.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/hands_on/list_commits.py b/hands_on/list_commits.py index 026dc18..422213f 100644 --- a/hands_on/list_commits.py +++ b/hands_on/list_commits.py @@ -1,6 +1,6 @@ import os -from exercise_utils.file import append_to_file +from exercise_utils.file import append_to_file, create_or_update_file from exercise_utils.git import add, commit, init __requires_git__ = True @@ -13,9 +13,14 @@ def download(verbose: bool): init(verbose) - append_to_file( + create_or_update_file( "fruits.txt", - "apples\nbananas\ncherries\ndragon fruits\n" + """ + apples + bananas + cherries + dragon fruits + """ ) add(["fruits.txt"], verbose) From a1320e8c992ddd0d180049de3746fe2d14df48a8 Mon Sep 17 00:00:00 2001 From: Vikram Goyal Date: Sun, 26 Oct 2025 14:58:11 +0800 Subject: [PATCH 6/8] Implement hands on hp-add-remote --- hands_on/add_remote.py | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 hands_on/add_remote.py diff --git a/hands_on/add_remote.py b/hands_on/add_remote.py new file mode 100644 index 0000000..ad7af2b --- /dev/null +++ b/hands_on/add_remote.py @@ -0,0 +1,40 @@ +import os + +from exercise_utils.git import add, init, commit +from exercise_utils.file import create_or_update_file, append_to_file + +__requires_git__ = True +__requires_github__ = False + + +def download(verbose: bool): + os.makedirs("things") + os.chdir("things") + init(verbose) + create_or_update_file( + "fruits.txt", + """ + apples + bananas + cherries + dragon fruits + figs + """, + ) + add(["fruits.txt"], verbose) + append_to_file("fruits.txt", """ + figs + """, + ) + add(["fruits.txt"], verbose) + commit("Insert figs into fruits.txt", verbose) + create_or_update_file("colours.txt", """ + a file for colours + """, + ) + create_or_update_file("shapes.txt", """ + a file for shapes + """, + ) + add(["colours.txt", "shapes.txt"], verbose) + commit("Add colours.txt, shapes.txt", verbose) From cad35b3349c549a264dbbf490ce72533363f4f2d Mon Sep 17 00:00:00 2001 From: Vikram Goyal Date: Thu, 30 Oct 2025 16:50:26 +0800 Subject: [PATCH 7/8] Change multiline to single line --- hands_on/add_remote.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/hands_on/add_remote.py b/hands_on/add_remote.py index ad7af2b..3c46a58 100644 --- a/hands_on/add_remote.py +++ b/hands_on/add_remote.py @@ -22,10 +22,7 @@ def download(verbose: bool): """, ) add(["fruits.txt"], verbose) - append_to_file("fruits.txt", """ - figs - """, - ) + append_to_file("fruits.txt", "figs") add(["fruits.txt"], verbose) commit("Insert figs into fruits.txt", verbose) create_or_update_file("colours.txt", """ From ede54a2d602e0e0ff30a61f159ca4e52d05ac55c Mon Sep 17 00:00:00 2001 From: Vikram Goyal Date: Mon, 10 Nov 2025 12:42:34 +0800 Subject: [PATCH 8/8] Remove unnecessary default branch checking --- hands_on/update_remote.py | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/hands_on/update_remote.py b/hands_on/update_remote.py index 0a3347b..9c53e86 100644 --- a/hands_on/update_remote.py +++ b/hands_on/update_remote.py @@ -23,10 +23,7 @@ def download(verbose: bool): """, ) add(["fruits.txt"], verbose) - append_to_file("fruits.txt", """ - figs - """, - ) + append_to_file("fruits.txt", "figs") add(["fruits.txt"], verbose) commit("Insert figs into fruits.txt", verbose) create_or_update_file("colours.txt", """ @@ -51,10 +48,4 @@ def download(verbose: bool): run_command(["gh", "repo", "create", REPO_NAME, "--public"], verbose) run_command(["git", "remote", "add", "origin", f"https://github.com/{username}/{REPO_NAME}"], verbose) - default_branch = run_command(["git", "branch", "--list", "main", "master"], verbose).strip() - if "main" in default_branch: - default_branch = "main" - else: - default_branch = "master" - - run_command(["git", "push", "-u", "origin", default_branch], verbose) \ No newline at end of file + run_command(["git", "push", "-u", "origin", "main"], verbose) \ No newline at end of file