gabriel / muse public
test_plumbing_name_rev.py python
185 lines 6.1 KB
96dd15b1 feat(plumbing): add symbolic-ref, for-each-ref, name-rev, check-ref-for… Gabriel Cardona <gabriel@tellurstori.com> 2d ago
1 """Tests for muse plumbing name-rev."""
2
3 from __future__ import annotations
4
5 import datetime
6 import hashlib
7 import json
8 import pathlib
9
10 import pytest
11 from typer.testing import CliRunner
12
13 from muse.cli.app import cli
14 from muse.core.store import CommitRecord, SnapshotRecord, write_commit, write_snapshot
15
16 runner = CliRunner()
17
18
19 def _sha(tag: str) -> str:
20 return hashlib.sha256(tag.encode()).hexdigest()
21
22
23 def _init_repo(path: pathlib.Path) -> pathlib.Path:
24 muse = path / ".muse"
25 (muse / "commits").mkdir(parents=True)
26 (muse / "snapshots").mkdir(parents=True)
27 (muse / "objects").mkdir(parents=True)
28 (muse / "refs" / "heads").mkdir(parents=True)
29 (muse / "HEAD").write_text("ref: refs/heads/main", encoding="utf-8")
30 (muse / "repo.json").write_text(
31 json.dumps({"repo_id": "test-repo", "domain": "midi"}), encoding="utf-8"
32 )
33 return path
34
35
36 def _env(repo: pathlib.Path) -> dict[str, str]:
37 return {"MUSE_REPO_ROOT": str(repo)}
38
39
40 def _snap(repo: pathlib.Path, tag: str) -> str:
41 sid = _sha(tag + ":snap")
42 write_snapshot(
43 repo,
44 SnapshotRecord(
45 snapshot_id=sid,
46 manifest={},
47 created_at=datetime.datetime(2026, 1, 1, tzinfo=datetime.timezone.utc),
48 ),
49 )
50 return sid
51
52
53 def _commit(
54 repo: pathlib.Path,
55 tag: str,
56 branch: str = "main",
57 parent: str | None = None,
58 ) -> str:
59 sid = _snap(repo, tag)
60 cid = _sha(tag)
61 write_commit(
62 repo,
63 CommitRecord(
64 commit_id=cid,
65 repo_id="test-repo",
66 branch=branch,
67 snapshot_id=sid,
68 message=tag,
69 committed_at=datetime.datetime(2026, 1, 1, tzinfo=datetime.timezone.utc),
70 author="tester",
71 parent_commit_id=parent,
72 parent2_commit_id=None,
73 ),
74 )
75 ref_path = repo / ".muse" / "refs" / "heads" / branch
76 ref_path.parent.mkdir(parents=True, exist_ok=True)
77 ref_path.write_text(cid, encoding="utf-8")
78 return cid
79
80
81 class TestNameRev:
82 def test_tip_commit_is_branch_zero(self, tmp_path: pathlib.Path) -> None:
83 _init_repo(tmp_path)
84 cid = _commit(tmp_path, "c1")
85 result = runner.invoke(cli, ["plumbing", "name-rev", cid], env=_env(tmp_path))
86 assert result.exit_code == 0
87 data = json.loads(result.output)
88 r = data["results"][0]
89 assert r["commit_id"] == cid
90 assert r["undefined"] is False
91 assert r["distance"] == 0
92
93 def test_parent_commit_distance_1(self, tmp_path: pathlib.Path) -> None:
94 _init_repo(tmp_path)
95 c1 = _commit(tmp_path, "c1", parent=None)
96 c2 = _commit(tmp_path, "c2", parent=c1)
97 result = runner.invoke(cli, ["plumbing", "name-rev", c1], env=_env(tmp_path))
98 assert result.exit_code == 0
99 data = json.loads(result.output)
100 r = data["results"][0]
101 assert r["distance"] == 1
102 assert r["name"] is not None
103 assert "~1" in r["name"]
104
105 def test_multiple_commit_ids(self, tmp_path: pathlib.Path) -> None:
106 _init_repo(tmp_path)
107 c1 = _commit(tmp_path, "c1", parent=None)
108 c2 = _commit(tmp_path, "c2", parent=c1)
109 result = runner.invoke(cli, ["plumbing", "name-rev", c1, c2], env=_env(tmp_path))
110 assert result.exit_code == 0
111 data = json.loads(result.output)
112 assert len(data["results"]) == 2
113 ids = {r["commit_id"] for r in data["results"]}
114 assert c1 in ids
115 assert c2 in ids
116
117 def test_unknown_commit_is_undefined(self, tmp_path: pathlib.Path) -> None:
118 _init_repo(tmp_path)
119 _commit(tmp_path, "c1")
120 fake_id = "a" * 64
121 result = runner.invoke(cli, ["plumbing", "name-rev", fake_id], env=_env(tmp_path))
122 assert result.exit_code == 0
123 data = json.loads(result.output)
124 r = data["results"][0]
125 assert r["undefined"] is True
126 assert r["name"] is None
127
128 def test_text_format(self, tmp_path: pathlib.Path) -> None:
129 _init_repo(tmp_path)
130 cid = _commit(tmp_path, "c1")
131 result = runner.invoke(
132 cli, ["plumbing", "name-rev", "--format", "text", cid], env=_env(tmp_path)
133 )
134 assert result.exit_code == 0
135 assert cid in result.output
136
137 def test_name_only_flag(self, tmp_path: pathlib.Path) -> None:
138 _init_repo(tmp_path)
139 cid = _commit(tmp_path, "c1")
140 result = runner.invoke(
141 cli,
142 ["plumbing", "name-rev", "--format", "text", "--name-only", cid],
143 env=_env(tmp_path),
144 )
145 assert result.exit_code == 0
146 assert cid not in result.output
147 assert result.output.strip()
148
149 def test_custom_undefined_string(self, tmp_path: pathlib.Path) -> None:
150 _init_repo(tmp_path)
151 _commit(tmp_path, "c1")
152 fake_id = "b" * 64
153 result = runner.invoke(
154 cli,
155 ["plumbing", "name-rev", "--format", "text", "--undefined", "UNKNOWN", fake_id],
156 env=_env(tmp_path),
157 )
158 assert result.exit_code == 0
159 assert "UNKNOWN" in result.output
160
161 def test_no_args_errors(self, tmp_path: pathlib.Path) -> None:
162 _init_repo(tmp_path)
163 result = runner.invoke(cli, ["plumbing", "name-rev"], env=_env(tmp_path))
164 assert result.exit_code != 0
165
166 def test_invalid_format_errors(self, tmp_path: pathlib.Path) -> None:
167 _init_repo(tmp_path)
168 cid = _commit(tmp_path, "c1")
169 result = runner.invoke(
170 cli, ["plumbing", "name-rev", "--format", "xml", cid], env=_env(tmp_path)
171 )
172 assert result.exit_code != 0
173
174 def test_depth_two_commit(self, tmp_path: pathlib.Path) -> None:
175 """Grandparent commit should be named branch~2."""
176 _init_repo(tmp_path)
177 c1 = _commit(tmp_path, "grandparent", parent=None)
178 c2 = _commit(tmp_path, "parent", parent=c1)
179 _commit(tmp_path, "tip", parent=c2)
180 result = runner.invoke(cli, ["plumbing", "name-rev", c1], env=_env(tmp_path))
181 assert result.exit_code == 0
182 data = json.loads(result.output)
183 r = data["results"][0]
184 assert r["distance"] == 2
185 assert "~2" in r["name"]