Skip to content

Commit

Permalink
refactor: add get_last_commit_on_branch_or_tag alongisde tests
Browse files Browse the repository at this point in the history
Signed-off-by: Dariusz Duda <[email protected]>
  • Loading branch information
dariuszd21 committed Dec 4, 2024
1 parent f7a4494 commit f3f5cd8
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 43 deletions.
88 changes: 46 additions & 42 deletions craft_application/git/_git_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,52 @@ def get_last_commit(self) -> Commit:
message=commit_message,
)

def get_last_commit_on_branch_or_tag(
self,
branch_or_tag: str,
*,
remote: str | None = None,
fetch: bool = False,
) -> Commit:
"""Find last commit corresponding to given branch or tag."""
if fetch and remote is not None:
self.fetch(remote=remote, tags=True)

Check warning on line 260 in craft_application/git/_git_repo.py

View check run for this annotation

Codecov / codecov/patch

craft_application/git/_git_repo.py#L260

Added line #L260 was not covered by tests
rev_list_output = [
self.git_binary(),
"rev-list",
"-n",
"1",
branch_or_tag,
]
try:
rev_parse_output = subprocess.check_output(
rev_list_output,
text=True,
stderr=subprocess.STDOUT,
)
except subprocess.CalledProcessError as error:
error_details = (
f"cannot find ref: {branch_or_tag!r}.\nCommand output:\n{error.stdout}"
)
raise GitError(error_details) from error

commit_sha = rev_parse_output.strip()
try:
commit_obj = self._repo.get(commit_sha)
except (pygit2.GitError, ValueError) as error:
raise GitError(
f"cannot find commit: {short_commit_sha(commit_sha)!r}"
) from error
else:
commit_message = cast(
str,
commit_obj.message, # pyright: ignore[reportOptionalMemberAccess,reportAttributeAccessIssue,reportUnknownMemberType]
)
return Commit(
sha=commit_sha,
message=commit_message,
)

def is_clean(self) -> bool:
"""Check if the repo is clean.
Expand Down Expand Up @@ -575,48 +621,6 @@ def remote_contains(
return True
return False

def last_commit_on_branch_or_tag(
self,
*,
remote: str,
branch_or_tag: str,
fetch: bool = False,
) -> Commit:
"""Find last commit corresponding to given branch or tag."""
if fetch:
self.fetch(remote=remote, tags=True)
rev_list_output = [
self.git_binary(),
"rev-list",
"-n",
"1",
branch_or_tag,
]
try:
rev_parse_output = subprocess.check_output(
rev_list_output,
text=True,
stderr=subprocess.STDOUT,
)
except subprocess.CalledProcessError as error:
error_details = (
f"Cannot find ref {branch_or_tag!r}.\nCommand output:\n{error.stdout}"
)
raise GitError(error_details) from error

commit_sha = rev_parse_output.strip()
commit_obj = self._repo.get(commit_sha)
if commit_obj is None:
raise GitError(f"Cannot find commit: {short_commit_sha(commit_sha)!r}")
commit_message = cast(
str,
commit_obj.message, # pyright: ignore[reportAttributeAccessIssue,reportUnknownMemberType]
)
return Commit(
sha=commit_sha,
message=commit_message,
)

def describe(
self,
*,
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/git/test_git.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def test_fetching_hello_repository(
ref = "ubuntu/noble"
git_repo.add_remote(test_remote, hello_repository_lp_url)
git_repo.fetch(remote=test_remote, ref=ref, depth=1)
last_commit_on_fetched_ref = git_repo.last_commit_on_branch_or_tag(
last_commit_on_fetched_ref = git_repo.get_last_commit_on_branch_or_tag(
remote=test_remote, branch_or_tag=f"{test_remote}/{ref}"
)
assert isinstance(
Expand Down
54 changes: 54 additions & 0 deletions tests/unit/git/test_git.py
Original file line number Diff line number Diff line change
Expand Up @@ -1289,3 +1289,57 @@ def test_craftgit_is_used_for_git_operations(
assert git_repo.git_binary() == expected_binary

which_mock.assert_called_once_with(CRAFTGIT_BINARY_NAME)


def test_last_commit_on_branch_or_tag_fails_if_commit_not_found(
empty_repository: Path,
fake_process: pytest_subprocess.FakeProcess,
expected_git_binary: str,
) -> None:
git_repo = GitRepo(empty_repository)
branch_or_tag = "test"
commit = "non-existent-commit"
fake_process.register(
[expected_git_binary, "rev-list", "-n", "1", branch_or_tag],
stdout=commit,
)
with pytest.raises(GitError) as git_error:
git_repo.get_last_commit_on_branch_or_tag(branch_or_tag)
assert (
git_error.value.details == f"cannot find commit: {short_commit_sha(commit)!r}"
)


def test_last_commit_on_branch_or_tag_fails_if_ref_not_found(
empty_repository: Path,
fake_process: pytest_subprocess.FakeProcess,
expected_git_binary: str,
) -> None:
git_repo = GitRepo(empty_repository)
branch_or_tag = "test"
fake_process.register(
[expected_git_binary, "rev-list", "-n", "1", branch_or_tag],
returncode=1,
stderr=f"fatal: ambiguous argument {branch_or_tag!r}",
)
with pytest.raises(GitError) as git_error:
git_repo.get_last_commit_on_branch_or_tag(branch_or_tag)
err_details = cast(str, git_error.value.details)
assert err_details.startswith(f"cannot find ref: {branch_or_tag!r}")
assert "fatal" in err_details


def test_get_last_commit_on_branch_or_tag(
repository_with_commit: RepositoryDefinition,
fake_process: pytest_subprocess.FakeProcess,
expected_git_binary: str,
) -> None:
git_repo = GitRepo(repository_with_commit.repository_path)
branch_or_tag = "test"
last_commit = git_repo.get_last_commit()
fake_process.register(
[expected_git_binary, "rev-list", "-n", "1", branch_or_tag],
stdout=last_commit.sha,
)
last_commit_on_branch = git_repo.get_last_commit_on_branch_or_tag(branch_or_tag)
assert last_commit_on_branch == last_commit

0 comments on commit f3f5cd8

Please sign in to comment.