test_branch_merged_commit_id.py
python
sha256:c287f599c5429903a139eadf3c5db5d930520e57cb0c3c575d9570e953c3b2d6
chore: bump version to 0.2.0.dev2 — nightly.2
Sonnet 4.6
patch
12 days ago
| 1 | """Regression tests for muse branch #21. |
| 2 | |
| 3 | ``muse branch --merged``/``--no-merged`` crashed with a ``ValueError`` from |
| 4 | ``validate_branch_name`` when given a ``sha256:``-prefixed commit ID instead |
| 5 | of a branch name — the argument was passed unconditionally to |
| 6 | ``get_head_commit_id``, which validates its input as a branch name. A commit |
| 7 | ID is a legitimate argument for both flags (e.g. checking against the tip of |
| 8 | a remote-tracking ref by ID rather than by local branch name). |
| 9 | """ |
| 10 | |
| 11 | from __future__ import annotations |
| 12 | |
| 13 | import json |
| 14 | import os |
| 15 | import pathlib |
| 16 | |
| 17 | from tests.cli_test_helper import CliRunner |
| 18 | |
| 19 | runner = CliRunner() |
| 20 | |
| 21 | |
| 22 | def _invoke(repo: pathlib.Path, args: list[str]): |
| 23 | saved = os.getcwd() |
| 24 | try: |
| 25 | os.chdir(repo) |
| 26 | return runner.invoke(None, args) |
| 27 | finally: |
| 28 | os.chdir(saved) |
| 29 | |
| 30 | |
| 31 | def _commit(repo: pathlib.Path, *extra: str): |
| 32 | _invoke(repo, ["code", "add", "."]) |
| 33 | return _invoke(repo, ["commit", *extra]) |
| 34 | |
| 35 | |
| 36 | def _head_commit_id(repo: pathlib.Path) -> str: |
| 37 | result = _invoke(repo, ["rev-parse", "HEAD", "--json"]) |
| 38 | return json.loads(result.output.strip().splitlines()[-1])["commit_id"] |
| 39 | |
| 40 | |
| 41 | def _init_repo(tmp_path: pathlib.Path) -> pathlib.Path: |
| 42 | saved = os.getcwd() |
| 43 | try: |
| 44 | os.chdir(tmp_path) |
| 45 | runner.invoke(None, ["init"]) |
| 46 | finally: |
| 47 | os.chdir(saved) |
| 48 | (tmp_path / "a.py").write_text("x = 1\n") |
| 49 | _commit(tmp_path, "-m", "initial") |
| 50 | return tmp_path |
| 51 | |
| 52 | |
| 53 | class TestBranchMergedAcceptsCommitId: |
| 54 | def test_merged_accepts_sha256_commit_id(self, tmp_path: pathlib.Path) -> None: |
| 55 | """--merged <sha256:...> must not crash — MRG_01.""" |
| 56 | repo = _init_repo(tmp_path) |
| 57 | tip = _head_commit_id(repo) |
| 58 | |
| 59 | result = _invoke(repo, ["branch", "--merged", tip, "--json"]) |
| 60 | |
| 61 | assert result.exit_code == 0, result.output |
| 62 | branches = json.loads(result.output.strip().splitlines()[-1]) |
| 63 | names = {b["name"] for b in branches} |
| 64 | assert "main" in names |
| 65 | |
| 66 | def test_no_merged_accepts_sha256_commit_id(self, tmp_path: pathlib.Path) -> None: |
| 67 | """--no-merged <sha256:...> must not crash — MRG_02.""" |
| 68 | repo = _init_repo(tmp_path) |
| 69 | tip = _head_commit_id(repo) |
| 70 | |
| 71 | result = _invoke(repo, ["branch", "--no-merged", tip, "--json"]) |
| 72 | |
| 73 | assert result.exit_code == 0, result.output |
| 74 | # main is merged into its own tip, so it must be excluded. |
| 75 | branches = json.loads(result.output.strip().splitlines()[-1]) |
| 76 | names = {b["name"] for b in branches} |
| 77 | assert "main" not in names |
| 78 | |
| 79 | def test_merged_still_accepts_branch_name(self, tmp_path: pathlib.Path) -> None: |
| 80 | """Existing branch-name behaviour is unchanged — MRG_03.""" |
| 81 | repo = _init_repo(tmp_path) |
| 82 | |
| 83 | result = _invoke(repo, ["branch", "--merged", "main", "--json"]) |
| 84 | |
| 85 | assert result.exit_code == 0, result.output |
| 86 | branches = json.loads(result.output.strip().splitlines()[-1]) |
| 87 | names = {b["name"] for b in branches} |
| 88 | assert "main" in names |
| 89 | |
| 90 | def test_merged_with_diverged_branch_by_commit_id( |
| 91 | self, tmp_path: pathlib.Path |
| 92 | ) -> None: |
| 93 | """A branch not yet merged into the given commit ID is excluded — MRG_04.""" |
| 94 | repo = _init_repo(tmp_path) |
| 95 | base_tip = _head_commit_id(repo) |
| 96 | |
| 97 | _invoke(repo, ["checkout", "-b", "feat/unmerged"]) |
| 98 | (repo / "b.py").write_text("y = 2\n") |
| 99 | _commit(repo, "-m", "unmerged work") |
| 100 | |
| 101 | result = _invoke(repo, ["branch", "--merged", base_tip, "--json"]) |
| 102 | |
| 103 | assert result.exit_code == 0, result.output |
| 104 | branches = json.loads(result.output.strip().splitlines()[-1]) |
| 105 | names = {b["name"] for b in branches} |
| 106 | assert "feat/unmerged" not in names |
| 107 | assert "main" in names |
File History
1 commit
sha256:c287f599c5429903a139eadf3c5db5d930520e57cb0c3c575d9570e953c3b2d6
chore: bump version to 0.2.0.dev2 — nightly.2
Sonnet 4.6
patch
12 days ago