|
1 | | -from typing import List |
| 1 | +from git import TagObject |
2 | 2 | from git_autograder.core import GitAutograderExercise, GitAutograderStatus |
3 | 3 |
|
4 | | -MSG_NO_TAG = "Tag 'v1.0.0' was not found." |
5 | | -MSG_NOT_AT_HEAD = "Tag 'v1.0.0' does not point to HEAD." |
| 4 | +FIRST_TAG = "first-pilot" |
| 5 | +SECOND_TAG = "v1.0" |
| 6 | +SECOND_TAG_MSG = "first full duty roster" |
| 7 | +MARCH_MSG_FRAGMENT = "Update roster for March" |
6 | 8 |
|
7 | 9 | def verify(exercise: GitAutograderExercise): |
8 | | - """ |
9 | | - Pass condition: |
10 | | - 1) exist 1.0.0 tag |
11 | | - 2) the tag is pointing to current head |
12 | | - """ |
13 | 10 | repo = exercise.repo.repo |
14 | | - target = next((t for t in repo.tags if t.name == "v1.0.0"), None) |
15 | 11 |
|
16 | | - messages: List[str] = [] |
17 | | - status = GitAutograderStatus.SUCCESSFUL |
| 12 | + root_sha = next(repo.iter_commits(rev="HEAD", reverse=True)).hexsha |
18 | 13 |
|
19 | | - if target is None: |
20 | | - messages.append(MSG_NO_TAG) |
21 | | - status = GitAutograderStatus.FAILED |
22 | | - elif target.commit.hexsha != repo.head.commit.hexsha: |
23 | | - messages.append(MSG_NOT_AT_HEAD) |
24 | | - status = GitAutograderStatus.FAILED |
| 14 | + march_commit = None |
| 15 | + for c in repo.iter_commits("HEAD"): |
| 16 | + if MARCH_MSG_FRAGMENT in c.message: |
| 17 | + march_commit = c |
| 18 | + break |
25 | 19 |
|
26 | | - return exercise.to_output(messages, status) |
| 20 | + comments = [] |
| 21 | + |
| 22 | + t_first = next((t for t in repo.tags if t.name == FIRST_TAG), None) |
| 23 | + if not t_first: |
| 24 | + comments.append(f"Missing lightweight tag `{FIRST_TAG}`.") |
| 25 | + else: |
| 26 | + if t_first.commit.hexsha != root_sha: |
| 27 | + comments.append( |
| 28 | + f"`{FIRST_TAG}` should point to first commit {root_sha[:7]}, " |
| 29 | + f"but points to {t_first.commit.hexsha[:7]} instead." |
| 30 | + ) |
| 31 | + if isinstance(getattr(t_first, "tag", None), TagObject): |
| 32 | + comments.append(f"`{FIRST_TAG}` must be a lightweight tag (not annotated).") |
| 33 | + |
| 34 | + t_v1 = next((t for t in repo.tags if t.name == SECOND_TAG), None) |
| 35 | + if not t_v1: |
| 36 | + comments.append(f"Missing annotated tag `{SECOND_TAG}`.") |
| 37 | + else: |
| 38 | + if not isinstance(getattr(t_v1, "tag", None), TagObject): |
| 39 | + comments.append(f"`{SECOND_TAG}` must be an annotated tag.") |
| 40 | + else: |
| 41 | + msg = (t_v1.tag.message or "").strip() |
| 42 | + if msg != SECOND_TAG_MSG: |
| 43 | + comments.append(f"`{SECOND_TAG}` message must be exactly `{SECOND_TAG_MSG}`.") |
| 44 | + if not march_commit: |
| 45 | + comments.append(f"Could not find the commit containing '{MARCH_MSG_FRAGMENT}'.") |
| 46 | + else: |
| 47 | + if t_v1.commit.hexsha != march_commit.hexsha: |
| 48 | + comments.append( |
| 49 | + f"`{SECOND_TAG}` should point to March commit {march_commit.hexsha[:7]}, " |
| 50 | + f"but points to {t_v1.commit.hexsha[:7]} instead." |
| 51 | + ) |
| 52 | + |
| 53 | + status = GitAutograderStatus.SUCCESSFUL if not comments else GitAutograderStatus.FAILED |
| 54 | + return exercise.to_output(comments, status) |
0 commit comments