test_git_only.py
python
sha256:a78e7e5a8740e03315f325d19edeb3aa1b306b3337d04abbaa9a9e0f3bbeb7a1
docs: MuseHub-first before ISR #74 — staging solidify NEXT
Human
1 day ago
| 1 | """Unit tests for git-only adapter fail-closed branches.""" |
| 2 | |
| 3 | from __future__ import annotations |
| 4 | |
| 5 | from adapters.errors import ReadError, WriteError |
| 6 | from tests.support import adapter_for, fail, make_runner, ok |
| 7 | |
| 8 | |
| 9 | def test_status_success(git_only_config, repo_root) -> None: |
| 10 | runner = make_runner( |
| 11 | { |
| 12 | "git rev-parse": ok("feat/test"), |
| 13 | "git status": ok(""), |
| 14 | } |
| 15 | ) |
| 16 | adapter = adapter_for(git_only_config, repo_root, runner) |
| 17 | result = adapter.status() |
| 18 | assert result.regime == "git-only" |
| 19 | assert result.branch == "feat/test" |
| 20 | assert result.dirty is False |
| 21 | |
| 22 | |
| 23 | def test_status_fails_closed_on_git_error(git_only_config, repo_root) -> None: |
| 24 | runner = make_runner({"git rev-parse": fail("fatal: not a git repo")}) |
| 25 | adapter = adapter_for(git_only_config, repo_root, runner) |
| 26 | result = adapter.status() |
| 27 | assert isinstance(result, ReadError) |
| 28 | assert "git rev-parse" in result.command |
| 29 | |
| 30 | |
| 31 | def test_read_head_missing_ref(git_only_config, repo_root) -> None: |
| 32 | runner = make_runner({"git rev-parse": fail("bad ref", 128)}) |
| 33 | adapter = adapter_for(git_only_config, repo_root, runner) |
| 34 | result = adapter.read_head("origin/main") |
| 35 | assert isinstance(result, ReadError) |
| 36 | |
| 37 | |
| 38 | def test_read_head_rejects_muse_ref(git_only_config, repo_root) -> None: |
| 39 | adapter = adapter_for(git_only_config, repo_root, make_runner({})) |
| 40 | result = adapter.read_head("muse:main") |
| 41 | assert isinstance(result, ReadError) |
| 42 | assert "forbidden" in result.message |
| 43 | |
| 44 | |
| 45 | def test_read_canonical_anchor(git_only_config, repo_root) -> None: |
| 46 | runner = make_runner({"git rev-parse": ok("abc123def456")}) |
| 47 | adapter = adapter_for(git_only_config, repo_root, runner) |
| 48 | result = adapter.read_canonical_anchor() |
| 49 | assert result.anchor_sha == "abc123def456" |
| 50 | assert result.source == "origin/main" |
| 51 | |
| 52 | |
| 53 | def test_realign_noop(git_only_config, repo_root) -> None: |
| 54 | adapter = adapter_for(git_only_config, repo_root, make_runner({})) |
| 55 | result = adapter.realign(dry_run=True, max_commits=50) |
| 56 | assert result.applied is False |
| 57 | assert result.reason == "single-history" |
| 58 | |
| 59 | |
| 60 | def test_commit_feature_refuses_main(git_only_config, repo_root) -> None: |
| 61 | adapter = adapter_for(git_only_config, repo_root, make_runner({})) |
| 62 | result = adapter.commit_feature(branch="main", message="x", paths=["docs/a.md"]) |
| 63 | assert isinstance(result, WriteError) |
| 64 | assert "protected" in result.message |
| 65 | |
| 66 | |
| 67 | def test_commit_feature_unsafe_path(git_only_config, repo_root) -> None: |
| 68 | adapter = adapter_for(git_only_config, repo_root, make_runner({})) |
| 69 | result = adapter.commit_feature( |
| 70 | branch="feat/x", |
| 71 | message="x", |
| 72 | paths=["../escape"], |
| 73 | ) |
| 74 | assert isinstance(result, ReadError) |
| 75 | assert "unsafe path" in result.message |
| 76 | |
| 77 | |
| 78 | def test_mirror_noop(git_only_config, repo_root) -> None: |
| 79 | adapter = adapter_for(git_only_config, repo_root, make_runner({})) |
| 80 | result = adapter.mirror(dry_run=True) |
| 81 | assert result.pushed is False |
| 82 | assert result.reason == "single-history" |
File History
2 commits
sha256:a78e7e5a8740e03315f325d19edeb3aa1b306b3337d04abbaa9a9e0f3bbeb7a1
docs: MuseHub-first before ISR #74 — staging solidify NEXT
Human
1 day ago
sha256:4671b7f787ddbe63ced31c895b688c77ab495653b65a730b423329f26b3c1439
feat: K1-P1 complete — agent provenance, build-verification…
Sonnet 4.6
patch
53 days ago