From 87d6f6554ba3f5e6396e485657a23d0d50bdba1f Mon Sep 17 00:00:00 2001 From: vanphuc Date: Sat, 1 Nov 2025 00:35:13 +0800 Subject: [PATCH 1/7] Add the ff-undo exercise --- ff_undo/.gitmastery-exercise.json | 18 ++++++++++ ff_undo/README.md | 18 ++++++++++ ff_undo/__init__.py | 0 ff_undo/download.py | 36 +++++++++++++++++++ ff_undo/tests/__init__.py | 0 ff_undo/tests/test_verify.py | 42 ++++++++++++++++++++++ ff_undo/verify.py | 59 +++++++++++++++++++++++++++++++ 7 files changed, 173 insertions(+) create mode 100644 ff_undo/.gitmastery-exercise.json create mode 100644 ff_undo/README.md create mode 100644 ff_undo/__init__.py create mode 100644 ff_undo/download.py create mode 100644 ff_undo/tests/__init__.py create mode 100644 ff_undo/tests/test_verify.py create mode 100644 ff_undo/verify.py diff --git a/ff_undo/.gitmastery-exercise.json b/ff_undo/.gitmastery-exercise.json new file mode 100644 index 0000000..53fddb6 --- /dev/null +++ b/ff_undo/.gitmastery-exercise.json @@ -0,0 +1,18 @@ +{ + "exercise_name": "ff-undo", + "tags": [ + "git-branch", + "git-merge", + "git-reset" + ], + "requires_git": true, + "requires_github": false, + "base_files": {}, + "exercise_repo": { + "repo_type": "local", + "repo_name": "play-characters", + "repo_title": null, + "create_fork": null, + "init": true + } +} \ No newline at end of file diff --git a/ff_undo/README.md b/ff_undo/README.md new file mode 100644 index 0000000..2c23c95 --- /dev/null +++ b/ff_undo/README.md @@ -0,0 +1,18 @@ +# ff-undo + + + +## Task + + + +## Hints + + + diff --git a/ff_undo/__init__.py b/ff_undo/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ff_undo/download.py b/ff_undo/download.py new file mode 100644 index 0000000..0f4db87 --- /dev/null +++ b/ff_undo/download.py @@ -0,0 +1,36 @@ +from exercise_utils.cli import run_command +from exercise_utils.gitmastery import create_start_tag + +__resources__ = {} + + +def setup(verbose: bool = False): + # Marks the start of setup (Git-Mastery internal logging) + create_start_tag(verbose) + + # Create initial files and commits + run_command('echo "Scientist" > rick.txt', verbose) + run_command('git add .', verbose) + run_command('git commit -m "Add Rick"', verbose) + + run_command('echo "Boy" > morty.txt', verbose) + run_command('git add .', verbose) + run_command('git commit -m "Add Morty"', verbose) + + # Create and switch to branch 'others' + run_command('git switch -c others', verbose) + run_command('echo "No job" > birdperson.txt', verbose) + run_command('git add .', verbose) + run_command('git commit -m "Add Birdperson"', verbose) + + run_command('echo "Cyborg" >> birdperson.txt', verbose) + run_command('git add .', verbose) + run_command('git commit -m "Add Cyborg to birdperson.txt"', verbose) + + run_command('echo "Spy" > tammy.txt', verbose) + run_command('git add .', verbose) + run_command('git commit -m "Add Tammy"', verbose) + + # Merge back into main + run_command('git switch main', verbose) + run_command('git merge others -m "Introduce others"', verbose) \ No newline at end of file diff --git a/ff_undo/tests/__init__.py b/ff_undo/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ff_undo/tests/test_verify.py b/ff_undo/tests/test_verify.py new file mode 100644 index 0000000..30dc776 --- /dev/null +++ b/ff_undo/tests/test_verify.py @@ -0,0 +1,42 @@ +from git_autograder import GitAutograderTestLoader, assert_output +from git_autograder.status import GitAutograderStatus +from ..verify import ( + MERGE_NOT_UNDONE, + MAIN_COMMITS_INCORRECT, + OTHERS_COMMITS_INCORRECT, + OTHERS_BRANCH_MISSING, + verify +) + +REPOSITORY_NAME = "ff-undo" + +loader = GitAutograderTestLoader(__file__, REPOSITORY_NAME, verify) + +def test_correct_solution(): + """Main has only Rick + Morty, others still exists with Birdperson, Cyborg, Tammy""" + with loader.load("specs/base.yml") as output: + assert_output(output, GitAutograderStatus.SUCCESSFUL) + + +def test_merge_not_undone(): + """Student did not undo merge (main still contains merge commit)""" + with loader.load("specs/merge_not_undone.yml") as output: + assert_output(output, GitAutograderStatus.UNSUCCESSFUL, [MERGE_NOT_UNDONE]) + + +def test_branch_missing(): + """Student deleted 'others' branch""" + with loader.load("specs/branch_missing.yml") as output: + assert_output(output, GitAutograderStatus.UNSUCCESSFUL, [OTHERS_BRANCH_MISSING]) + + +def test_main_commits_incorrect(): + """Student modified or removed main commits""" + with loader.load("specs/main_commits_incorrect.yml") as output: + assert_output(output, GitAutograderStatus.UNSUCCESSFUL, [MAIN_COMMITS_INCORRECT]) + + +def test_others_commits_incorrect(): + """Student changed commits on others branch""" + with loader.load("specs/others_commits_incorrect.yml") as output: + assert_output(output, GitAutograderStatus.UNSUCCESSFUL, [OTHERS_COMMITS_INCORRECT]) diff --git a/ff_undo/verify.py b/ff_undo/verify.py new file mode 100644 index 0000000..e11bc8e --- /dev/null +++ b/ff_undo/verify.py @@ -0,0 +1,59 @@ +from git_autograder import ( + GitAutograderOutput, + GitAutograderExercise, + GitAutograderStatus, +) + +MERGE_NOT_UNDONE = ( + "The merge commit 'Introduce others' is still present on the main branch. " + "You need to undo the merge so that only Rick and Morty remain on main." +) +MAIN_COMMITS_INCORRECT = ( + "The main branch does not contain the expected commits " + "The main branch does not contain both commits 'Add Rick' and 'Add Morty'." +) +OTHERS_COMMITS_INCORRECT = ( + "The others branch does not contain the expected commits " + "'Add Birdperson', 'Add Cyborg to birdperson.txt', and 'Add Tammy'." +) +OTHERS_BRANCH_MISSING = ( + "The branch 'others' no longer exists. You should not delete it, only undo the merge on main." +) + +def verify(exercise: GitAutograderExercise) -> GitAutograderOutput: + + # Check if branch others exists + if not exercise.repo.branches.has_branch("others"): + raise exercise.wrong_answer([OTHERS_BRANCH_MISSING]) + + # Take all commit messages on main + commit_messages_in_main = [c.message.strip() for c in exercise.repo.repo.iter_commits("main")] + + # Take all commit messages on others + commit_messages_in_others = [c.message.strip() for c in exercise.repo.repo.iter_commits("others")] + + # Check that the merge commit is not present on main + if any("Introduce others" in msg for msg in commit_messages_in_main): + raise exercise.wrong_answer([MERGE_NOT_UNDONE]) + + # Check that commits in main are only the initial 2 commits + has_rick = any("Add Rick" in msg for msg in commit_messages_in_main) + has_morty = any("Add Morty" in msg for msg in commit_messages_in_main) + if len(commit_messages_in_main) != 2 or not (has_rick and has_morty): + raise exercise.wrong_answer([MAIN_COMMITS_INCORRECT]) + + # Check that the merge commit is not present on others + if any("Introduce others" in msg for msg in commit_messages_in_others): + raise exercise.wrong_answer([MERGE_NOT_UNDONE]) + + # Check that commits in others are only the initial 3 commits + has_birdperson = any("Add Birdperson" in msg for msg in commit_messages_in_others) + has_cyborg = any("Add Cyborg to birdperson.txt" in msg for msg in commit_messages_in_others) + has_tammy = any("Add Tammy" in msg for msg in commit_messages_in_others) + if len(commit_messages_in_others) != 3 or not (has_birdperson and has_cyborg and has_tammy): + raise exercise.wrong_answer([OTHERS_COMMITS_INCORRECT]) + + return exercise.to_output( + ["You have successfully undone the merge of branch 'others'."], + GitAutograderStatus.SUCCESSFUL, + ) From 966108ebfe445d5d422f219cae7fdfefbdec899a Mon Sep 17 00:00:00 2001 From: vanphuc Date: Sat, 1 Nov 2025 00:40:34 +0800 Subject: [PATCH 2/7] Add yml file for test_verify --- ff_undo/tests/specs/base.yml | 22 ++++++++++++++++ ff_undo/tests/specs/branch_missing.yml | 10 ++++++++ .../tests/specs/main_commits_incorrect.yml | 18 +++++++++++++ ff_undo/tests/specs/merge_not_undone.yml | 25 +++++++++++++++++++ .../tests/specs/others_commits_incorrect.yml | 19 ++++++++++++++ 5 files changed, 94 insertions(+) create mode 100644 ff_undo/tests/specs/base.yml create mode 100644 ff_undo/tests/specs/branch_missing.yml create mode 100644 ff_undo/tests/specs/main_commits_incorrect.yml create mode 100644 ff_undo/tests/specs/merge_not_undone.yml create mode 100644 ff_undo/tests/specs/others_commits_incorrect.yml diff --git a/ff_undo/tests/specs/base.yml b/ff_undo/tests/specs/base.yml new file mode 100644 index 0000000..a73079c --- /dev/null +++ b/ff_undo/tests/specs/base.yml @@ -0,0 +1,22 @@ +initialization: + steps: + - type: commit + id: start + empty: true + message: Empty commit + - type: commit + message: "Add Rick" + - type: commit + message: "Add Morty" + - type: branch + branch-name: others + - type: checkout + branch-name: others + - type: commit + message: "Add Birdperson" + - type: commit + message: "Add Cyborg to birdperson.txt" + - type: commit + message: "Add Tammy" + + diff --git a/ff_undo/tests/specs/branch_missing.yml b/ff_undo/tests/specs/branch_missing.yml new file mode 100644 index 0000000..8fe1a43 --- /dev/null +++ b/ff_undo/tests/specs/branch_missing.yml @@ -0,0 +1,10 @@ +initialization: + steps: + - type: commit + id: start + empty: true + message: Empty commit + - type: commit + message: "Add Rick" + - type: commit + message: "Add Morty" diff --git a/ff_undo/tests/specs/main_commits_incorrect.yml b/ff_undo/tests/specs/main_commits_incorrect.yml new file mode 100644 index 0000000..510c4ab --- /dev/null +++ b/ff_undo/tests/specs/main_commits_incorrect.yml @@ -0,0 +1,18 @@ +initialization: + steps: + - type: commit + id: start + empty: true + message: Empty commit + - type: commit + message: "Add Morty" + - type: branch + branch-name: others + - type: checkout + branch-name: others + - type: commit + message: "Add Birdperson" + - type: commit + message: "Add Cyborg to birdperson.txt" + - type: commit + message: "Add Tammy" diff --git a/ff_undo/tests/specs/merge_not_undone.yml b/ff_undo/tests/specs/merge_not_undone.yml new file mode 100644 index 0000000..e812179 --- /dev/null +++ b/ff_undo/tests/specs/merge_not_undone.yml @@ -0,0 +1,25 @@ +initialization: + steps: + - type: commit + id: start + empty: true + message: Empty commit + - type: commit + message: "Add Rick" + - type: commit + message: "Add Morty" + - type: branch + branch-name: others + - type: checkout + branch-name: others + - type: commit + message: "Add Birdperson" + - type: commit + message: "Add Cyborg to birdperson.txt" + - type: commit + message: "Add Tammy" + - type: checkout + branch-name: main + - type: merge + branch-name: others + message: "Introduce others" diff --git a/ff_undo/tests/specs/others_commits_incorrect.yml b/ff_undo/tests/specs/others_commits_incorrect.yml new file mode 100644 index 0000000..b0acc2a --- /dev/null +++ b/ff_undo/tests/specs/others_commits_incorrect.yml @@ -0,0 +1,19 @@ +initialization: + steps: + - type: commit + id: start + empty: true + message: Empty commit + - type: commit + message: "Add Rick" + - type: commit + message: "Add Morty" + - type: branch + branch-name: others + - type: checkout + branch-name: others + - type: commit + message: "Add Birdperson" + - type: commit + message: "Add Tammy" + From dace21b646955fde5f37fe5cb7b5dff313b113e3 Mon Sep 17 00:00:00 2001 From: vanphuc Date: Sat, 1 Nov 2025 01:27:28 +0800 Subject: [PATCH 3/7] Add README file and also fix the verify to check the mistake --- ff_undo/README.md | 42 ++++++++++++++++++------ ff_undo/tests/specs/base.yml | 3 +- ff_undo/tests/specs/merge_not_undone.yml | 1 + ff_undo/tests/test_verify.py | 5 --- ff_undo/verify.py | 17 +++++----- 5 files changed, 43 insertions(+), 25 deletions(-) diff --git a/ff_undo/README.md b/ff_undo/README.md index 2c23c95..289ff6e 100644 --- a/ff_undo/README.md +++ b/ff_undo/README.md @@ -1,18 +1,40 @@ # ff-undo - +This exercise focuses on **undoing a merge in Git**. You will practice how to revert unwanted merge commits while keeping branches and commits intact. ## Task - +You have a repository with two branches: + +- `main` branch, which initially contains commits: + - `Add Rick` + - `Add Morty` +- `others` branch, which contains commits: + - `Add Birdperson` + - `Add Cyborg to birdperson.txt` + - `Add Tammy` + +A merge with fast forward from `others` into `main` has been done incorrectly. Your task is: + +1. **Undo the merge on `main`**, so that only `Add Rick` and `Add Morty` remain on `main`. +2. Ensure the `others` branch still exists with all its commits intact. +3. Do not delete any commits; only undo the merge on `main`. ## Hints - - +
+Hint 1: Check your branches + +Use `git branch` to see the current branches and verify `main` and `others` exist. +
+ +
+Hint 2: View commit history + +Use `git log --oneline` on `main` to identify the merge commit that needs to be undone. +
+ +
+Hint 3: Undo the merge + +You can undo a merge using: `git reset --hard ` diff --git a/ff_undo/tests/specs/base.yml b/ff_undo/tests/specs/base.yml index a73079c..b77c9fe 100644 --- a/ff_undo/tests/specs/base.yml +++ b/ff_undo/tests/specs/base.yml @@ -18,5 +18,6 @@ initialization: message: "Add Cyborg to birdperson.txt" - type: commit message: "Add Tammy" - + - type: checkout + branch-name: main diff --git a/ff_undo/tests/specs/merge_not_undone.yml b/ff_undo/tests/specs/merge_not_undone.yml index e812179..0a77d8a 100644 --- a/ff_undo/tests/specs/merge_not_undone.yml +++ b/ff_undo/tests/specs/merge_not_undone.yml @@ -22,4 +22,5 @@ initialization: branch-name: main - type: merge branch-name: others + no-ff: false message: "Introduce others" diff --git a/ff_undo/tests/test_verify.py b/ff_undo/tests/test_verify.py index 30dc776..097bd76 100644 --- a/ff_undo/tests/test_verify.py +++ b/ff_undo/tests/test_verify.py @@ -13,30 +13,25 @@ loader = GitAutograderTestLoader(__file__, REPOSITORY_NAME, verify) def test_correct_solution(): - """Main has only Rick + Morty, others still exists with Birdperson, Cyborg, Tammy""" with loader.load("specs/base.yml") as output: assert_output(output, GitAutograderStatus.SUCCESSFUL) def test_merge_not_undone(): - """Student did not undo merge (main still contains merge commit)""" with loader.load("specs/merge_not_undone.yml") as output: assert_output(output, GitAutograderStatus.UNSUCCESSFUL, [MERGE_NOT_UNDONE]) def test_branch_missing(): - """Student deleted 'others' branch""" with loader.load("specs/branch_missing.yml") as output: assert_output(output, GitAutograderStatus.UNSUCCESSFUL, [OTHERS_BRANCH_MISSING]) def test_main_commits_incorrect(): - """Student modified or removed main commits""" with loader.load("specs/main_commits_incorrect.yml") as output: assert_output(output, GitAutograderStatus.UNSUCCESSFUL, [MAIN_COMMITS_INCORRECT]) def test_others_commits_incorrect(): - """Student changed commits on others branch""" with loader.load("specs/others_commits_incorrect.yml") as output: assert_output(output, GitAutograderStatus.UNSUCCESSFUL, [OTHERS_COMMITS_INCORRECT]) diff --git a/ff_undo/verify.py b/ff_undo/verify.py index e11bc8e..a5baec9 100644 --- a/ff_undo/verify.py +++ b/ff_undo/verify.py @@ -5,8 +5,8 @@ ) MERGE_NOT_UNDONE = ( - "The merge commit 'Introduce others' is still present on the main branch. " - "You need to undo the merge so that only Rick and Morty remain on main." + "The merge commit 'Introduce others' is still present. " + "You need to undo the merge." ) MAIN_COMMITS_INCORRECT = ( "The main branch does not contain the expected commits " @@ -33,24 +33,23 @@ def verify(exercise: GitAutograderExercise) -> GitAutograderOutput: commit_messages_in_others = [c.message.strip() for c in exercise.repo.repo.iter_commits("others")] # Check that the merge commit is not present on main - if any("Introduce others" in msg for msg in commit_messages_in_main): + has_birdperson_in_main = any("Add Birdperson" in msg for msg in commit_messages_in_main) + has_cyborg_in_main = any("Add Cyborg to birdperson.txt" in msg for msg in commit_messages_in_main) + has_tammy_in_main = any("Add Tammy" in msg for msg in commit_messages_in_main) + if has_birdperson_in_main or has_birdperson_in_main or has_tammy_in_main: raise exercise.wrong_answer([MERGE_NOT_UNDONE]) # Check that commits in main are only the initial 2 commits has_rick = any("Add Rick" in msg for msg in commit_messages_in_main) has_morty = any("Add Morty" in msg for msg in commit_messages_in_main) - if len(commit_messages_in_main) != 2 or not (has_rick and has_morty): + if len(commit_messages_in_main) != 3 or not (has_rick and has_morty): raise exercise.wrong_answer([MAIN_COMMITS_INCORRECT]) - # Check that the merge commit is not present on others - if any("Introduce others" in msg for msg in commit_messages_in_others): - raise exercise.wrong_answer([MERGE_NOT_UNDONE]) - # Check that commits in others are only the initial 3 commits has_birdperson = any("Add Birdperson" in msg for msg in commit_messages_in_others) has_cyborg = any("Add Cyborg to birdperson.txt" in msg for msg in commit_messages_in_others) has_tammy = any("Add Tammy" in msg for msg in commit_messages_in_others) - if len(commit_messages_in_others) != 3 or not (has_birdperson and has_cyborg and has_tammy): + if len(commit_messages_in_others) != 6 or not (has_birdperson and has_cyborg and has_tammy): raise exercise.wrong_answer([OTHERS_COMMITS_INCORRECT]) return exercise.to_output( From 7abe28c5836d626a6e778d5a89c6a9f9a2d63041 Mon Sep 17 00:00:00 2001 From: vanphuc Date: Sat, 1 Nov 2025 09:28:53 +0800 Subject: [PATCH 4/7] Change the notification for not undo merge --- ff_undo/verify.py | 1 - 1 file changed, 1 deletion(-) diff --git a/ff_undo/verify.py b/ff_undo/verify.py index a5baec9..42faac8 100644 --- a/ff_undo/verify.py +++ b/ff_undo/verify.py @@ -5,7 +5,6 @@ ) MERGE_NOT_UNDONE = ( - "The merge commit 'Introduce others' is still present. " "You need to undo the merge." ) MAIN_COMMITS_INCORRECT = ( From fe2f02def987df5d7c07781b0d377d389611a6ac Mon Sep 17 00:00:00 2001 From: vanphuc Date: Wed, 12 Nov 2025 11:29:34 +0800 Subject: [PATCH 5/7] Final ver --- .DS_Store | Bin 0 -> 10244 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..7d13c4a0c0d7640007dde7c6e6a8382050b59b58 GIT binary patch literal 10244 zcmeHMU2hvj6uq06dYv?`D}q!B5G(P*Lt>JqRf%|U^YKs#c&HIP05a=(w9MIoO@ZEV8q<(E)Wel4jseGjW56-s7;p?+M+UHFbMaTTb!W$b zW56*mXMpF200-MvZl~JH)Pa+10bnb5ECtut2M8v}Z7a7^Z3T)t_3pvTpPa_IU3l{Vdx)d?hZI~9tx}g1r8GhR0_$|GW0FnzXYp8;|zF;WvEurBX?Eb{%%Vila%VvA(a; zER54=D1f*Z!R6bpoo41pYPn=2zDN9Uu*>D+xI@%+6eAH z*txi<`R{!A@u!bFC&|-Py+A)uynM2yHGMxnGpnV1oVJH)qEhC8vA4k)>*5H^#iFJT zlolb!vFJ^amFcBlfhsENJ)oFtt-tXjAH957sK`qcdtEGiPRImiMiC z>kBn?@a>A#p3um`{=9%a0y;yBtXkG@4|V{2LWzm3d|+X#;Nl40V?kN^;V8Z5g>hAb zFZb!>GR0M1S@k!l4}XQ&n58q|Mu<`&x&iu@Qs0bEM)Hq^7JYc@9*uxS?ks;E!$tqM zQEMOda+FfPw5TM@8S2u{EJkHK7i+1~XY`2n>5#slHXWL6daO3no7I#GD^Qc=&EvM{ zy(Xi!kGN);;#hgcu(ijkEh6jaMGU=Z&5pn%^Vt)2tsaSPi`ZMGSk6s|OdOjri#kno ziufi_x2^XwZL>bh(XVs4$+;{W8KTf4`Ud>C?ItV7j8oKB^t~mSf1PKZ`4u?gyn|sA z&06#71+CR&%&b*!3wdo+_B_EWhklhqaa}TS}sHY(qRsydA3Ytx2tcSQO87HE@=LP*; zjbBi|sIiEzU(tTa{9w%NS7QI`H-zoojo{whUHyizyTdp4|Hd1_m3_3{6smJBOVlc3 zy2$)mzJ9V|I#4RlZKdOi*A9dCccHKlDq*c({!TG_YhgW?D9OVbW7Jy7b$e=#7#Y>Y zxG_3DCt*s~9smFU literal 0 HcmV?d00001 From f627ddc66156ab3beb7a674c3aa656bccc793d11 Mon Sep 17 00:00:00 2001 From: vanphuc Date: Thu, 20 Nov 2025 21:29:42 +0800 Subject: [PATCH 6/7] Use the git cli command instead of run command --- ff_undo/README.md | 1 + ff_undo/download.py | 55 ++++++++++--------- ff_undo/tests/specs/base.yml | 3 +- ff_undo/tests/specs/branch_missing.yml | 2 +- .../tests/specs/main_commits_incorrect.yml | 2 +- ff_undo/tests/specs/merge_not_undone.yml | 2 +- .../tests/specs/others_commits_incorrect.yml | 1 - ff_undo/verify.py | 33 ++++++----- 8 files changed, 53 insertions(+), 46 deletions(-) diff --git a/ff_undo/README.md b/ff_undo/README.md index 289ff6e..3eabfbc 100644 --- a/ff_undo/README.md +++ b/ff_undo/README.md @@ -38,3 +38,4 @@ Use `git log --oneline` on `main` to identify the merge commit that needs to be Hint 3: Undo the merge You can undo a merge using: `git reset --hard ` +
\ No newline at end of file diff --git a/ff_undo/download.py b/ff_undo/download.py index 0f4db87..686c15b 100644 --- a/ff_undo/download.py +++ b/ff_undo/download.py @@ -1,36 +1,39 @@ -from exercise_utils.cli import run_command -from exercise_utils.gitmastery import create_start_tag - -__resources__ = {} - +from exercise_utils.git import ( + add, + commit, + checkout, + merge_with_message, +) +from exercise_utils.file import ( + create_or_update_file, + append_to_file, +) def setup(verbose: bool = False): - # Marks the start of setup (Git-Mastery internal logging) - create_start_tag(verbose) - # Create initial files and commits - run_command('echo "Scientist" > rick.txt', verbose) - run_command('git add .', verbose) - run_command('git commit -m "Add Rick"', verbose) + create_or_update_file("rick.txt", "Scientist\n") + add(["rick.txt"], verbose) + commit("Add Rick", verbose) - run_command('echo "Boy" > morty.txt', verbose) - run_command('git add .', verbose) - run_command('git commit -m "Add Morty"', verbose) + create_or_update_file("morty.txt", "Boy\n") + add(["morty.txt"], verbose) + commit("Add Morty", verbose) # Create and switch to branch 'others' - run_command('git switch -c others', verbose) - run_command('echo "No job" > birdperson.txt', verbose) - run_command('git add .', verbose) - run_command('git commit -m "Add Birdperson"', verbose) + checkout("others", create_branch=True, verbose=verbose) + + create_or_update_file("birdperson.txt", "No job\n") + add(["birdperson.txt"], verbose) + commit("Add Birdperson", verbose) - run_command('echo "Cyborg" >> birdperson.txt', verbose) - run_command('git add .', verbose) - run_command('git commit -m "Add Cyborg to birdperson.txt"', verbose) + append_to_file("birdperson.txt", "Cyborg\n") + add(["birdperson.txt"], verbose) + commit("Add Cyborg to birdperson.txt", verbose) - run_command('echo "Spy" > tammy.txt', verbose) - run_command('git add .', verbose) - run_command('git commit -m "Add Tammy"', verbose) + create_or_update_file("tammy.txt", "Spy\n") + add(["tammy.txt"], verbose) + commit("Add Tammy", verbose) # Merge back into main - run_command('git switch main', verbose) - run_command('git merge others -m "Introduce others"', verbose) \ No newline at end of file + checkout("main", create_branch=False, verbose=verbose) + merge_with_message("others", ff=True, message="Introduce others", verbose=verbose) \ No newline at end of file diff --git a/ff_undo/tests/specs/base.yml b/ff_undo/tests/specs/base.yml index b77c9fe..afff1b0 100644 --- a/ff_undo/tests/specs/base.yml +++ b/ff_undo/tests/specs/base.yml @@ -19,5 +19,4 @@ initialization: - type: commit message: "Add Tammy" - type: checkout - branch-name: main - + branch-name: main \ No newline at end of file diff --git a/ff_undo/tests/specs/branch_missing.yml b/ff_undo/tests/specs/branch_missing.yml index 8fe1a43..4d666dc 100644 --- a/ff_undo/tests/specs/branch_missing.yml +++ b/ff_undo/tests/specs/branch_missing.yml @@ -7,4 +7,4 @@ initialization: - type: commit message: "Add Rick" - type: commit - message: "Add Morty" + message: "Add Morty" \ No newline at end of file diff --git a/ff_undo/tests/specs/main_commits_incorrect.yml b/ff_undo/tests/specs/main_commits_incorrect.yml index 510c4ab..aedd28c 100644 --- a/ff_undo/tests/specs/main_commits_incorrect.yml +++ b/ff_undo/tests/specs/main_commits_incorrect.yml @@ -15,4 +15,4 @@ initialization: - type: commit message: "Add Cyborg to birdperson.txt" - type: commit - message: "Add Tammy" + message: "Add Tammy" \ No newline at end of file diff --git a/ff_undo/tests/specs/merge_not_undone.yml b/ff_undo/tests/specs/merge_not_undone.yml index 0a77d8a..85ee3e3 100644 --- a/ff_undo/tests/specs/merge_not_undone.yml +++ b/ff_undo/tests/specs/merge_not_undone.yml @@ -23,4 +23,4 @@ initialization: - type: merge branch-name: others no-ff: false - message: "Introduce others" + message: "Introduce others" \ No newline at end of file diff --git a/ff_undo/tests/specs/others_commits_incorrect.yml b/ff_undo/tests/specs/others_commits_incorrect.yml index b0acc2a..60cd4b9 100644 --- a/ff_undo/tests/specs/others_commits_incorrect.yml +++ b/ff_undo/tests/specs/others_commits_incorrect.yml @@ -16,4 +16,3 @@ initialization: message: "Add Birdperson" - type: commit message: "Add Tammy" - diff --git a/ff_undo/verify.py b/ff_undo/verify.py index 42faac8..fe568a8 100644 --- a/ff_undo/verify.py +++ b/ff_undo/verify.py @@ -4,6 +4,12 @@ GitAutograderStatus, ) +ADD_RICK = "Add Rick" +ADD_MORTY = "Add Morty" +ADD_BIRDPERSON = "Add Birdperson" +ADD_CYBORG = "Add Cyborg to birdperson.txt" +ADD_TAMMY = "Add Tammy" + MERGE_NOT_UNDONE = ( "You need to undo the merge." ) @@ -20,35 +26,34 @@ ) def verify(exercise: GitAutograderExercise) -> GitAutograderOutput: + # Get branches + main_branch = exercise.repo.branches.branch("main") + others_branch = exercise.repo.branches.branch_or_none("others") # Check if branch others exists - if not exercise.repo.branches.has_branch("others"): + if others_branch is None: raise exercise.wrong_answer([OTHERS_BRANCH_MISSING]) # Take all commit messages on main - commit_messages_in_main = [c.message.strip() for c in exercise.repo.repo.iter_commits("main")] + commit_messages_in_main = [c.commit.message.strip() for c in main_branch.commits] # Take all commit messages on others - commit_messages_in_others = [c.message.strip() for c in exercise.repo.repo.iter_commits("others")] + commit_messages_in_others = [c.commit.message.strip() for c in others_branch.commits] # Check that the merge commit is not present on main - has_birdperson_in_main = any("Add Birdperson" in msg for msg in commit_messages_in_main) - has_cyborg_in_main = any("Add Cyborg to birdperson.txt" in msg for msg in commit_messages_in_main) - has_tammy_in_main = any("Add Tammy" in msg for msg in commit_messages_in_main) - if has_birdperson_in_main or has_birdperson_in_main or has_tammy_in_main: + if any(msg in commit_messages_in_main for msg in [ADD_BIRDPERSON, ADD_CYBORG, ADD_TAMMY]): raise exercise.wrong_answer([MERGE_NOT_UNDONE]) # Check that commits in main are only the initial 2 commits - has_rick = any("Add Rick" in msg for msg in commit_messages_in_main) - has_morty = any("Add Morty" in msg for msg in commit_messages_in_main) - if len(commit_messages_in_main) != 3 or not (has_rick and has_morty): + if len(commit_messages_in_main) != 3 or not all( + msg in commit_messages_in_main for msg in [ADD_RICK, ADD_MORTY] + ): raise exercise.wrong_answer([MAIN_COMMITS_INCORRECT]) # Check that commits in others are only the initial 3 commits - has_birdperson = any("Add Birdperson" in msg for msg in commit_messages_in_others) - has_cyborg = any("Add Cyborg to birdperson.txt" in msg for msg in commit_messages_in_others) - has_tammy = any("Add Tammy" in msg for msg in commit_messages_in_others) - if len(commit_messages_in_others) != 6 or not (has_birdperson and has_cyborg and has_tammy): + if len(commit_messages_in_others) != 6 or not all( + msg in commit_messages_in_others for msg in [ADD_BIRDPERSON, ADD_CYBORG, ADD_TAMMY] + ): raise exercise.wrong_answer([OTHERS_COMMITS_INCORRECT]) return exercise.to_output( From 66b21317d3b08b250a9b095f67b6b17276012f37 Mon Sep 17 00:00:00 2001 From: vanphuc Date: Thu, 20 Nov 2025 21:33:41 +0800 Subject: [PATCH 7/7] Fix the test cases --- ff_undo/tests/specs/base.yml | 3 --- ff_undo/tests/specs/branch_missing.yml | 3 --- ff_undo/tests/specs/main_commits_incorrect.yml | 3 --- ff_undo/tests/specs/merge_not_undone.yml | 3 --- ff_undo/tests/specs/others_commits_incorrect.yml | 3 --- ff_undo/verify.py | 4 ++-- 6 files changed, 2 insertions(+), 17 deletions(-) diff --git a/ff_undo/tests/specs/base.yml b/ff_undo/tests/specs/base.yml index afff1b0..23847df 100644 --- a/ff_undo/tests/specs/base.yml +++ b/ff_undo/tests/specs/base.yml @@ -2,9 +2,6 @@ initialization: steps: - type: commit id: start - empty: true - message: Empty commit - - type: commit message: "Add Rick" - type: commit message: "Add Morty" diff --git a/ff_undo/tests/specs/branch_missing.yml b/ff_undo/tests/specs/branch_missing.yml index 4d666dc..dcc9aaa 100644 --- a/ff_undo/tests/specs/branch_missing.yml +++ b/ff_undo/tests/specs/branch_missing.yml @@ -2,9 +2,6 @@ initialization: steps: - type: commit id: start - empty: true - message: Empty commit - - type: commit message: "Add Rick" - type: commit message: "Add Morty" \ No newline at end of file diff --git a/ff_undo/tests/specs/main_commits_incorrect.yml b/ff_undo/tests/specs/main_commits_incorrect.yml index aedd28c..0a6e399 100644 --- a/ff_undo/tests/specs/main_commits_incorrect.yml +++ b/ff_undo/tests/specs/main_commits_incorrect.yml @@ -2,9 +2,6 @@ initialization: steps: - type: commit id: start - empty: true - message: Empty commit - - type: commit message: "Add Morty" - type: branch branch-name: others diff --git a/ff_undo/tests/specs/merge_not_undone.yml b/ff_undo/tests/specs/merge_not_undone.yml index 85ee3e3..3778fe4 100644 --- a/ff_undo/tests/specs/merge_not_undone.yml +++ b/ff_undo/tests/specs/merge_not_undone.yml @@ -2,9 +2,6 @@ initialization: steps: - type: commit id: start - empty: true - message: Empty commit - - type: commit message: "Add Rick" - type: commit message: "Add Morty" diff --git a/ff_undo/tests/specs/others_commits_incorrect.yml b/ff_undo/tests/specs/others_commits_incorrect.yml index 60cd4b9..59fa6c6 100644 --- a/ff_undo/tests/specs/others_commits_incorrect.yml +++ b/ff_undo/tests/specs/others_commits_incorrect.yml @@ -2,9 +2,6 @@ initialization: steps: - type: commit id: start - empty: true - message: Empty commit - - type: commit message: "Add Rick" - type: commit message: "Add Morty" diff --git a/ff_undo/verify.py b/ff_undo/verify.py index fe568a8..83c73f8 100644 --- a/ff_undo/verify.py +++ b/ff_undo/verify.py @@ -45,13 +45,13 @@ def verify(exercise: GitAutograderExercise) -> GitAutograderOutput: raise exercise.wrong_answer([MERGE_NOT_UNDONE]) # Check that commits in main are only the initial 2 commits - if len(commit_messages_in_main) != 3 or not all( + if len(commit_messages_in_main) != 2 or not all( msg in commit_messages_in_main for msg in [ADD_RICK, ADD_MORTY] ): raise exercise.wrong_answer([MAIN_COMMITS_INCORRECT]) # Check that commits in others are only the initial 3 commits - if len(commit_messages_in_others) != 6 or not all( + if len(commit_messages_in_others) != 5 or not all( msg in commit_messages_in_others for msg in [ADD_BIRDPERSON, ADD_CYBORG, ADD_TAMMY] ): raise exercise.wrong_answer([OTHERS_COMMITS_INCORRECT])