gabriel / muse public
test_log_collect_all_commits.py python
131 lines 4.5 KB
Raw
sha256:51ce277f663e01a43eaffbe77509b1de7ac2d4251b55d23306304bcdeb92c90d feat(pack): delta-encode snapshots in MPackBundle wire format Sonnet 4.6 minor ⚠ breaking 122 days ago
1 """TDD — log._collect_all_commits must use iter_ancestors, not inline deque BFS.
2
3 LC1 Structural — _collect_all_commits uses iter_ancestors; no inline deque BFS
4 LC2 Behavioural — collects all commits reachable from start_ids
5 LC3 Behavioural — truncated flag fires at max_commits cap
6 """
7 from __future__ import annotations
8
9 import datetime
10 import inspect
11 import json
12 import pathlib
13
14 import pytest
15
16 from muse._version import __version__
17 from muse.core.object_store import write_object
18 from muse.core.snapshot import compute_commit_id, compute_snapshot_id
19 from muse.core.store import CommitRecord, SnapshotRecord, write_commit, write_snapshot
20 from muse.core.types import blob_id
21 from muse.core.paths import muse_dir
22
23
24 def _repo(tmp_path: pathlib.Path, monkeypatch: pytest.MonkeyPatch) -> pathlib.Path:
25 dot_muse = muse_dir(tmp_path)
26 for d in ("commits", "snapshots", "objects", "refs/heads", "remotes"):
27 (dot_muse / d).mkdir(parents=True, exist_ok=True)
28 (dot_muse / "HEAD").write_text("ref: refs/heads/main\n")
29 (dot_muse / "repo.json").write_text(
30 json.dumps({"repo_id": "test-repo", "schema_version": __version__, "domain": "code"})
31 )
32 monkeypatch.setenv("MUSE_REPO_ROOT", str(tmp_path))
33 monkeypatch.chdir(tmp_path)
34 return tmp_path
35
36
37 def _make_commit(
38 root: pathlib.Path,
39 parent_id: str | None = None,
40 *,
41 message: str = "test",
42 ) -> CommitRecord:
43 oid = blob_id(b"data-" + message.encode())
44 write_object(root, oid, b"data-" + message.encode())
45 manifest = {"f.py": oid}
46 snap_id = compute_snapshot_id(manifest)
47 write_snapshot(root, SnapshotRecord(snapshot_id=snap_id, manifest=manifest))
48 ts = datetime.datetime(2026, 1, 1, tzinfo=datetime.timezone.utc)
49 cid = compute_commit_id(
50 parent_ids=[parent_id] if parent_id else [],
51 snapshot_id=snap_id,
52 message=message,
53 committed_at_iso=ts.isoformat(),
54 )
55 rec = CommitRecord(
56 repo_id="test-repo",
57 commit_id=cid,
58 branch="main",
59 snapshot_id=snap_id,
60 message=message,
61 committed_at=ts,
62 parent_commit_id=parent_id,
63 )
64 write_commit(root, rec)
65 return rec
66
67
68 # ---------------------------------------------------------------------------
69 # LC1 Structural
70 # ---------------------------------------------------------------------------
71
72 def test_lc1_collect_all_commits_uses_iter_ancestors() -> None:
73 """_collect_all_commits must delegate to iter_ancestors; no inline deque."""
74 from muse.cli.commands import log as log_mod
75
76 src = inspect.getsource(log_mod._collect_all_commits)
77
78 assert "iter_ancestors" in src, (
79 "_collect_all_commits must delegate to iter_ancestors. "
80 "Replace the inline deque BFS."
81 )
82 assert "deque" not in src, (
83 "_collect_all_commits still has an inline deque. Replace with iter_ancestors."
84 )
85
86
87 # ---------------------------------------------------------------------------
88 # LC2 Behavioural — collects all reachable commits
89 # ---------------------------------------------------------------------------
90
91 def test_lc2_collect_all_commits_returns_all(
92 tmp_path: pathlib.Path,
93 monkeypatch: pytest.MonkeyPatch,
94 ) -> None:
95 """Returns a CommitIndex containing every reachable commit."""
96 from muse.cli.commands.log import _collect_all_commits # type: ignore[attr-defined]
97
98 root = _repo(tmp_path, monkeypatch)
99 c1 = _make_commit(root, message="c1")
100 c2 = _make_commit(root, c1.commit_id, message="c2")
101 c3 = _make_commit(root, c2.commit_id, message="c3")
102
103 index, truncated = _collect_all_commits(root, [c3.commit_id])
104
105 assert truncated is False
106 assert c1.commit_id in index
107 assert c2.commit_id in index
108 assert c3.commit_id in index
109
110
111 # ---------------------------------------------------------------------------
112 # LC3 Behavioural — truncated flag
113 # ---------------------------------------------------------------------------
114
115 def test_lc3_collect_all_commits_truncated_flag(
116 tmp_path: pathlib.Path,
117 monkeypatch: pytest.MonkeyPatch,
118 ) -> None:
119 """truncated=True when max_commits is reached before exhausting the DAG."""
120 from muse.cli.commands.log import _collect_all_commits # type: ignore[attr-defined]
121
122 root = _repo(tmp_path, monkeypatch)
123 parent_id: str | None = None
124 for i in range(5):
125 c = _make_commit(root, parent_id, message=f"c{i}")
126 parent_id = c.commit_id
127
128 index, truncated = _collect_all_commits(root, [parent_id], max_commits=2) # type: ignore[arg-type]
129
130 assert truncated is True
131 assert len(index) == 2
File History 1 commit
sha256:51ce277f663e01a43eaffbe77509b1de7ac2d4251b55d23306304bcdeb92c90d feat(pack): delta-encode snapshots in MPackBundle wire format Sonnet 4.6 minor 122 days ago