-
Notifications
You must be signed in to change notification settings - Fork 25
Implement exercise T4L2/tags-add #126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
71a164a
ab9a8b2
7d64663
aebf193
e1d6063
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| { | ||
| "exercise_name": "tags-add", | ||
| "tags": ["git-tag"], | ||
| "requires_git": true, | ||
| "requires_github": true, | ||
| "base_files": {}, | ||
| "exercise_repo": { | ||
| "repo_type": "remote", | ||
| "repo_name": "duty-roster", | ||
| "create_fork": false, | ||
| "repo_title": "gm-duty-roster", | ||
| "init": false | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| # tags-add | ||
|
|
||
| The `duty-roster` repo contains text files that track which people are assigned for duties on which days of the week. | ||
|
|
||
| ## Task | ||
|
|
||
| 1. Add a lightweight tag `first-pilot` to the first commit of the repo. | ||
|
|
||
| 2. Add the annotated tag `v1.0` to the commit that updates March duty roster. The tag should have the message `first full duty roster`. | ||
|
|
||
| ## Hints | ||
|
|
||
| <details> | ||
| <summary>💡 Hint 1</summary> | ||
|
|
||
| ```bash | ||
| # add lightweight tag | ||
| git tag first-pilot <FIRST_COMMIT_SHA> | ||
| ``` | ||
|
|
||
| </details> | ||
|
|
||
| <summary>💡 Hint 2</summary> | ||
|
|
||
| ```bash | ||
| # add annotated tag with message | ||
| git tag -a v1.0 -m "first full duty roster" <MARCH_COMMIT_SHA> | ||
| ``` | ||
|
|
||
| </details> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| def setup(verbose: bool = False): | ||
| pass | ||
|
Comment on lines
+1
to
+2
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can change this to def setup(verbose: bool = False): ... |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| initialization: | ||
| steps: | ||
| - type: commit | ||
| empty: true | ||
| message: Add January duty roster | ||
| id: start | ||
| - type: tag | ||
| tag-name: first-pilot | ||
| - type: commit | ||
| empty: true | ||
| message: Update duty roster for February | ||
| - type: commit | ||
| empty: true | ||
| message: Update roster for March | ||
| - type: tag | ||
| tag-name: v1.0 | ||
| tag-message: first full duty roster | ||
| - type: commit | ||
| empty: true | ||
| message: Update duty roster for April | ||
| - type: commit | ||
| empty: true | ||
| message: Update roster for May |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| initialization: | ||
| steps: | ||
| - type: commit | ||
| empty: true | ||
| message: Add January duty roster | ||
| id: start | ||
| - type: commit | ||
| empty: true | ||
| message: Update duty roster for February | ||
| - type: commit | ||
| empty: true | ||
| message: Update roster for March | ||
| - type: tag | ||
| tag-name: v1.0 | ||
woojiahao marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| tag-message: first full duty roster | ||
| - type: commit | ||
| empty: true | ||
| message: Update duty roster for April | ||
| - type: commit | ||
| empty: true | ||
| message: Update roster for May | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| initialization: | ||
| steps: | ||
| - type: commit | ||
| empty: true | ||
| message: Add January duty roster | ||
| id: start | ||
| - type: tag | ||
| tag-name: first-pilot | ||
| - type: commit | ||
| empty: true | ||
| message: Update duty roster for February | ||
| - type: commit | ||
| empty: true | ||
| message: Update roster for March | ||
| - type: commit | ||
| empty: true | ||
| message: Update duty roster for April | ||
| - type: commit | ||
| empty: true | ||
| message: Update roster for May |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| initialization: | ||
| steps: | ||
| - type: commit | ||
| empty: true | ||
| message: Add January duty roster | ||
| id: start | ||
| - type: commit | ||
| empty: true | ||
| message: Update duty roster for February | ||
| - type: tag | ||
| tag-name: first-pilot | ||
| - type: commit | ||
| empty: true | ||
| message: Update roster for March | ||
| - type: tag | ||
| tag-name: v1.0 | ||
| tag-message: first full duty roster | ||
| - type: commit | ||
| empty: true | ||
| message: Update duty roster for April | ||
| - type: commit | ||
| empty: true | ||
| message: Update roster for May |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| initialization: | ||
| steps: | ||
| - type: commit | ||
| empty: true | ||
| message: Add January duty roster | ||
| id: start | ||
| - type: tag | ||
| tag-name: first-pilot | ||
| - type: commit | ||
| empty: true | ||
| message: Update duty roster for February | ||
| - type: commit | ||
| empty: true | ||
| message: Update roster for March | ||
| - type: commit | ||
| empty: true | ||
| message: Update duty roster for April | ||
| - type: commit | ||
| empty: true | ||
| message: Update roster for May | ||
| - type: tag | ||
| tag-name: v1.0 | ||
| tag-message: first full duty roster |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| initialization: | ||
| steps: | ||
| - type: commit | ||
| empty: true | ||
| message: Add January duty roster | ||
| id: start | ||
| - type: tag | ||
| tag-name: first-pilot | ||
| - type: commit | ||
| empty: true | ||
| message: Update duty roster for February | ||
| - type: commit | ||
| empty: true | ||
| message: Update roster for March | ||
| - type: tag | ||
| tag-name: v1.0 | ||
| tag-message: wrong message | ||
| - type: commit | ||
| empty: true | ||
| message: Update duty roster for April | ||
| - type: commit | ||
| empty: true | ||
| message: Update roster for May |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| from git_autograder import GitAutograderStatus, GitAutograderTestLoader, assert_output | ||
|
|
||
| from ..verify import ( | ||
| verify, | ||
| FIRST_TAG_WRONG_COMMIT, | ||
| MISSING_FIRST_TAG, | ||
| MISSING_SECOND_TAG, | ||
| SECOND_TAG_WRONG_COMMIT, | ||
| SUCCESS_MESSAGE, | ||
| WRONG_SECOND_TAG_MESSAGE, | ||
| ) | ||
|
|
||
| REPOSITORY_NAME = "tags-add" | ||
|
|
||
| loader = GitAutograderTestLoader(__file__, REPOSITORY_NAME, verify) | ||
|
|
||
|
|
||
| def test_base(): | ||
| with loader.load("specs/base.yml", "start") as output: | ||
| assert_output(output, GitAutograderStatus.SUCCESSFUL, [SUCCESS_MESSAGE]) | ||
|
|
||
|
|
||
| def test_missing_first_pilot_tag(): | ||
| with loader.load("specs/missing_first_pilot_tag.yml", "start") as output: | ||
| assert_output(output, GitAutograderStatus.UNSUCCESSFUL, [MISSING_FIRST_TAG]) | ||
|
|
||
|
|
||
| def test_missing_v1_tag(): | ||
| with loader.load("specs/missing_v1_tag.yml", "start") as output: | ||
| assert_output(output, GitAutograderStatus.UNSUCCESSFUL, [MISSING_SECOND_TAG]) | ||
|
|
||
|
|
||
| def test_wrong_message_v1_tag(): | ||
| with loader.load("specs/wrong_message_v1_tag.yml", "start") as output: | ||
| assert_output(output, GitAutograderStatus.UNSUCCESSFUL, [WRONG_SECOND_TAG_MESSAGE]) | ||
|
|
||
|
|
||
| def test_wrong_commit_first_pilot_tag(): | ||
| with loader.load("specs/wrong_commit_first_pilot_tag.yml", "start") as output: | ||
| assert_output(output, GitAutograderStatus.UNSUCCESSFUL, [FIRST_TAG_WRONG_COMMIT]) | ||
|
|
||
|
|
||
| def test_wrong_commit_v1_tag(): | ||
| with loader.load("specs/wrong_commit_v1_tag.yml", "start") as output: | ||
| assert_output(output, GitAutograderStatus.UNSUCCESSFUL, [SECOND_TAG_WRONG_COMMIT]) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| from typing import List, Optional | ||
| from git_autograder import GitAutograderCommit, GitAutograderExercise, GitAutograderOutput, GitAutograderStatus | ||
|
|
||
| FIRST_TAG = "first-pilot" | ||
| SECOND_TAG = "v1.0" | ||
| SECOND_TAG_MSG = "first full duty roster" | ||
| MARCH_MSG_FRAGMENT = "Update roster for March" | ||
|
|
||
| MISSING_FIRST_TAG = f'Missing lightweight tag "{FIRST_TAG}".' | ||
| MISSING_SECOND_TAG = f'Missing annotated tag "{SECOND_TAG}".' | ||
| WRONG_SECOND_TAG_MESSAGE = f'"{SECOND_TAG}" message must be exactly "{SECOND_TAG_MSG}".' | ||
| FIRST_TAG_WRONG_COMMIT = f'"{FIRST_TAG}" should point to the first commit.' | ||
| SECOND_TAG_WRONG_COMMIT = f'"{SECOND_TAG}" should point to the commit that updates March duty roster.' | ||
| MISSING_FIRST_COMMIT = "Missing commit that adds January duty roster." | ||
| MISSING_MARCH_COMMIT = "Missing commit that updates March duty roster." | ||
| SUCCESS_MESSAGE = "Great work using git tag to annotate various commits in the repository!" | ||
|
|
||
|
|
||
| def get_commit_from_message(commits: List[GitAutograderCommit], message: str) -> Optional[GitAutograderCommit]: | ||
| """Find a commit with the given message from a list of commits.""" | ||
| for commit in commits: | ||
| if message.strip() == commit.commit.message.strip(): | ||
| return commit | ||
| return None | ||
|
|
||
|
|
||
| def verify(exercise: GitAutograderExercise) -> GitAutograderOutput: | ||
| # Verify lightweight tag "first-pilot" on the first commit | ||
| tags = exercise.repo.repo.tags | ||
| if FIRST_TAG not in tags: | ||
| raise exercise.wrong_answer([MISSING_FIRST_TAG]) | ||
|
|
||
| main_branch = exercise.repo.branches.branch("main") | ||
| main_branch_commits = main_branch.commits | ||
| if len(main_branch_commits) == 0: | ||
| raise exercise.wrong_answer([MISSING_FIRST_COMMIT]) | ||
|
|
||
| first_commit = main_branch_commits[-1] | ||
|
Comment on lines
+35
to
+38
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You seem to have combined the logic for checking for the presence of the first commit and ensuring the indexing does not throw an out-of-bounds error. I suppose this fits with the spirit of the exercise since we're looking for the absolute earliest commit. |
||
| first_pilot_tag_commit = tags[FIRST_TAG].commit | ||
| if first_pilot_tag_commit.hexsha != first_commit.hexsha: | ||
| raise exercise.wrong_answer([FIRST_TAG_WRONG_COMMIT]) | ||
|
|
||
| # Verify annotated tag "v1.0" on March commit with correct message | ||
| if SECOND_TAG not in tags: | ||
| raise exercise.wrong_answer([MISSING_SECOND_TAG]) | ||
|
|
||
| v1_tag = tags[SECOND_TAG] | ||
| if v1_tag is None: | ||
| raise exercise.wrong_answer([MISSING_SECOND_TAG]) | ||
|
Comment on lines
+47
to
+49
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you trying to ensure that the tag is an annotated tag? If so, you should be checking: v1_tag = tags[SECOND_TAG]
if v1_tag.tag is None:
raise exercise.wrong_answer([MISSING_SECOND_TAG])Also, I'd prefer if we had a separate error message for creating a lightweight tag instead of an annotated tag. |
||
|
|
||
| march_commit = get_commit_from_message(main_branch_commits, MARCH_MSG_FRAGMENT) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd prefer not to abstract the |
||
| if march_commit is None: | ||
| raise exercise.wrong_answer([MISSING_MARCH_COMMIT]) | ||
|
|
||
| v1_tag_commit = v1_tag.commit | ||
| if v1_tag_commit.hexsha != march_commit.hexsha: | ||
| raise exercise.wrong_answer([SECOND_TAG_WRONG_COMMIT]) | ||
|
|
||
| if v1_tag.tag.message.strip() != SECOND_TAG_MSG: | ||
| raise exercise.wrong_answer([WRONG_SECOND_TAG_MESSAGE]) | ||
|
|
||
| return exercise.to_output( | ||
| [SUCCESS_MESSAGE], | ||
| GitAutograderStatus.SUCCESSFUL, | ||
| ) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing opening
<details>tag.