gabriel / muse public
feat patch task/ref-reading-primitives #1 / 1
AI Agent gabriel · 160 days ago · Apr 18, 2026 · Diff

feat: extract canonical ref-reading primitives into muse/core/refs.py

Add read_ref(path) -> str | None and iter_branch_refs(repo_root) -> Iterator[tuple[str, str]] as the canonical primitives for all ref-file I/O in Muse, following the same TDD approach used for object_store.py and graph.py.

- muse/core/refs.py: new module with read_ref and iter_branch_refs - tests/test_core_refs.py: 19 tests covering both primitives - muse/core/store.py: get_head_commit_id, get_all_branch_heads, _resolve_branch_commit_id, and resolve_commit_ref delegate to read_ref / iter_branch_refs - 21 command files and 3 core files updated to use the primitives instead of raw .read_text().strip() patterns - show_ref and for_each_ref gain hierarchical branch support (rglob) since iter_branch_refs uses rglob internally - doc_history and doc_extractor replace manual HEAD parsing with read_current_branch() from store.py

sha256:33363e54e38fc57024a3873f2f4c13db6e994b7947480ccf905cba4a8588f4d5 sha
+64 ~34 symbols
sha256:5d67ceed45fc07fc689a6aadffd4a79fd583a6a8d78042a700cfaa648134a9f0 snapshot
+64
symbols added
~34
symbols modified
0
dead code introduced
Semantic Changes 98 symbols
~ muse/core/refs.py .py 5 symbols added
+ Iterator import import Iterator L35–35
+ annotations import import annotations L32–32
+ pathlib import import pathlib L34–34
+ iter_branch_refs function function iter_branch_refs L83–134
+ read_ref function function read_ref L43–75
~ tests/test_core_refs.py .py 32 symbols added
+ TestIterBranchRefs class class TestIterBranchRefs L113–209
+ test_branch_name_is_relative_posix_path method method test_branch_name_is_relative_posix_path L194–202
+ test_empty_heads_dir_yields_nothing method method test_empty_heads_dir_yields_nothing L119–122
+ test_hierarchical_branch_name_uses_posix_slash method method test_hierarchical_branch_name_uses_posix_slash L161–169
+ test_missing_heads_dir_yields_nothing method method test_missing_heads_dir_yields_nothing L114–117
+ test_multiple_branches_yields_all method method test_multiple_branches_yields_all L133–139
+ test_returns_iterator_not_list method method test_returns_iterator_not_list L187–192
+ test_single_branch_yields_name_and_commit_id method method test_single_branch_yields_name_and_commit_id L124–131
+ test_skips_empty_ref_files method method test_skips_empty_ref_files L171–178
+ test_skips_empty_subdirectories method method test_skips_empty_subdirectories L151–159
+ test_skips_symlinks method method test_skips_symlinks L141–149
+ test_uses_generator_not_list_comprehension method method test_uses_generator_not_list_comprehension L204–209
+ test_yields_non_empty_commit_ids method method test_yields_non_empty_commit_ids L180–185
+ TestReadRef class class TestReadRef L68–105
+ test_returns_commit_id_for_well_formed_ref method method test_returns_commit_id_for_well_formed_ref L69–72
+ test_returns_none_for_empty_file method method test_returns_none_for_empty_file L77–80
+ test_returns_none_for_missing_file method method test_returns_none_for_missing_file L74–75
+ test_returns_none_for_whitespace_only method method test_returns_none_for_whitespace_only L82–85
+ test_returns_none_on_permission_error method method test_returns_none_on_permission_error L97–105
+ test_strips_trailing_newline_only method method test_strips_trailing_newline_only L92–95
+ test_strips_whitespace_and_newlines method method test_strips_whitespace_and_newlines L87–90
+ _FAKE_CID variable variable _FAKE_CID L58–58
+ _FAKE_CID2 variable variable _FAKE_CID2 L59–59
+ _FAKE_CID3 variable variable _FAKE_CID3 L60–60
+ _make_repo function function _make_repo L41–47
+ _write_branch_ref function function _write_branch_ref L50–55
+ annotations import import annotations L26–26
+ iter_branch_refs import import iter_branch_refs L33–33
+ json import import json L28–28
+ pathlib import import pathlib L29–29
+ pytest import import pytest L31–31
+ read_ref import import read_ref L33–33
~ muse/cli/commands/branch.py .py 1 symbol added, 1 symbol modified
+ read_ref import import read_ref L65–65
~ run
~ muse/cli/commands/checkout.py .py 1 symbol added, 1 symbol modified
+ read_ref import import read_ref L75–75
~ muse/cli/commands/core_blame.py .py 1 symbol added, 1 symbol modified
+ read_ref import import read_ref L37–37
~ run
~ muse/cli/commands/count_objects.py .py 1 symbol added, 1 symbol modified
+ iter_branch_refs import import iter_branch_refs L72–72
~ muse/cli/commands/for_each_ref.py .py 1 symbol added, 1 symbol modified
+ iter_branch_refs import import iter_branch_refs L94–94
~ muse/cli/commands/format_patch.py .py 1 symbol added, 1 symbol modified
+ read_ref import import read_ref L124–124
~ muse/cli/commands/index_rebuild.py .py 1 symbol added, 1 symbol modified
+ read_ref import import read_ref L85–85
~ muse/cli/commands/log.py .py 1 symbol added, 1 symbol modified
+ iter_branch_refs import import iter_branch_refs L118–118
~ muse/cli/commands/ls_tree.py .py 1 symbol added, 1 symbol modified
+ read_ref import import read_ref L107–107
~ muse/cli/commands/merge_tree.py .py 1 symbol added, 1 symbol modified
+ read_ref import import read_ref L102–102
~ muse/cli/commands/migrate.py .py 1 symbol added, 1 symbol modified
+ read_ref import import read_ref L70–70
~ muse/cli/commands/name_rev.py .py 1 symbol added, 1 symbol modified
+ iter_branch_refs import import iter_branch_refs L113–113
~ muse/cli/commands/patch_id.py .py 1 symbol added, 1 symbol modified
+ read_ref import import read_ref L68–68
~ muse/cli/commands/push.py .py 1 symbol added, 1 symbol modified
+ read_ref import import read_ref L99–99
~ muse/cli/commands/range_diff.py .py 1 symbol added, 1 symbol modified
+ read_ref import import read_ref L96–96
~ muse/cli/commands/rebase.py .py 1 symbol added, 1 symbol modified
+ read_ref import import read_ref L63–63
~ muse/cli/commands/remote.py .py 1 symbol added, 1 symbol modified
+ read_ref import import read_ref L73–73
~ muse/cli/commands/show_ref.py .py 1 symbol added, 1 symbol modified
+ iter_branch_refs import import iter_branch_refs L84–84
~ muse/cli/commands/switch.py .py 1 symbol added, 1 symbol modified
+ read_ref import import read_ref L80–80
~ muse/cli/commands/update_ref.py .py 1 symbol added, 1 symbol modified
+ read_ref import import read_ref L76–76
~ run
~ muse/cli/commands/verify_commit.py .py 1 symbol added, 1 symbol modified
+ read_ref import import read_ref L66–66
~ muse/cli/config.py .py 1 symbol added, 1 symbol modified
+ read_ref import import read_ref L56–56
~ muse/core/doc_extractor.py .py 1 symbol added, 5 symbols modified
~ muse/core/doc_history.py .py 1 symbol modified
~ muse/core/gc.py .py 1 symbol added, 1 symbol modified
+ iter_branch_refs import import iter_branch_refs L68–68
~ muse/core/store.py .py 2 symbols added, 4 symbols modified
+ iter_branch_refs import import iter_branch_refs L162–162
+ read_ref import import read_ref L162–162
~ muse/core/workspace.py .py 1 symbol added, 1 symbol modified
+ iter_branch_refs import import iter_branch_refs L61–61
← Older Oldest on task/ref-reading-primitives
All commits
Newer → Latest on task/ref-reading-primitives

0 comments

No comments yet. Be the first to start the discussion.

To add a comment, use the Muse CLI: muse hub commit comment sha256:33363e54e38fc57024a3873f2f4c13db6e994b7947480ccf905cba4a8588f4d5 --body "your comment"