gabriel / muse public
fix BREAKING gc dev
AI Agent gabriel · 143 days ago · Apr 26, 2026 · Diff

fix(gc): use path helpers throughout; prune stale remote tracking refs under --full

Replace two hardcoded .muse/ path constructions with the canonical helpers from muse.core.paths: - _collect_shelf_objects: repo_root / MUSE_DIR / 'shelf.json' → _shelf_json_path(repo_root) - _collect_reachable_commits: repo_root / MUSE_DIR / 'tags' → _tags_dir(repo_root)

Remove now-unused MUSE_DIR import from muse.core.gc.

Add prune_stale_remote_refs(): when a remote is removed from config, its tracking-ref directory (.muse/remotes/<remote>/) accumulates indefinitely. Under muse gc --full, this function deletes directories for remotes not present in config.toml. Symlinked dirs are skipped (traversal guard). GcResult gains stale_remote_refs_collected and stale_remote_refs_bytes. CLI --full output and --json schema include the new counts.

Add test_gc_path_helpers_and_remote_refs.py: 16 tests covering path-helper correctness, prune_stale_remote_refs unit cases (stale deleted, configured preserved, dry_run, symlink guard, empty dir, nested layout, byte counting), and CLI integration (--full removes stale refs, --json schema, --dry-run, no --full leaves refs alone, zero-stale schema).

sha256:cfede0b60ec5f4c994ff8dc79d03af06d61e0fb150fc29bd970f3306e41e3884 sha
+50 ~15 −1 symbols
sha256:349491546e79c5e8a4c32a9b76240159b0f88ccec38c6bc334d2028579b512ed snapshot
+50
symbols added
~15
symbols modified
−1
symbol removed
0
dead code introduced
Semantic Changes 66 symbols
+ TestCliStaleRemoteRefs class class TestCliStaleRemoteRefs L285–386
+ test_full_dry_run_counts_stale_refs method method test_full_dry_run_counts_stale_refs L325–345
+ test_full_json_includes_stale_remote_refs_fields method method test_full_json_includes_stale_remote_refs_fields L304–323
+ test_full_json_schema_zero_when_nothing_stale method method test_full_json_schema_zero_when_nothing_stale L369–386
+ test_full_removes_stale_remote_refs method method test_full_removes_stale_remote_refs L286–302
+ test_no_full_does_not_prune_stale_refs method method test_no_full_does_not_prune_stale_refs L347–367
+ TestPathHelpers class class TestPathHelpers L118–153
+ test_shelf_json_path_is_canonical method method test_shelf_json_path_is_canonical L119–135
+ test_tags_dir_is_canonical method method test_tags_dir_is_canonical L137–153
+ TestPruneStaleRemoteRefs class class TestPruneStaleRemoteRefs L161–277
+ test_bytes_counted_correctly method method test_bytes_counted_correctly L268–277
+ test_configured_remote_preserved method method test_configured_remote_preserved L174–182
+ test_dry_run_counts_but_does_not_delete method method test_dry_run_counts_but_does_not_delete L203–211
+ test_empty_stale_dir_removed method method test_empty_stale_dir_ L228–237
+ test_nested_refs_all_counted method method test_nested_refs_all_counted L239–253
+ test_no_remotes_dir_is_noop method method test_no_remotes_dir_is_noop L255–266
+ test_only_stale_remotes_removed method method test_only_stale_remotes_ L184–201
+ test_stale_remote_dir_deleted method method test_stale_remote_dir_deleted L162–172
+ test_symlinked_remote_dir_skipped method method test_symlinked_remote_dir_skipped L213–226
+ _env function function _env L69–70
+ _make_one_commit function function _make_one_commit L82–110
+ _make_repo function function _make_repo L57–66
+ _write_remote_ref function function _write_remote_ref L73–79
+ cli variable variable cli L48–48
+ CliRunner import import CliRunner L46–46
+ CommitRecord import import CommitRecord L44–44
+ GcResult import import GcResult L39–39
+ InvokeResult import import InvokeResult L46–46
+ SnapshotRecord import import SnapshotRecord L44–44
+ _remotes_dir import import _remotes_dir L40–40
+ _shelf_json_path import import _shelf_json_path L40–40
+ _tags_dir import import _tags_dir L40–40
+ _write_obj import import _write_obj L42–42
+ annotations import import annotations L31–31
+ blob_id import import blob_id L41–41
+ compute_commit_id import import compute_commit_id L43–43
+ compute_snapshot_id import import compute_snapshot_id L43–43
+ fake_id import import fake_id L41–41
+ json import import json L33–33
+ msgpack import import msgpack L36–36
+ pathlib import import pathlib L34–34
+ prune_stale_remote_refs import import prune_stale_remote_refs L39–39
+ pytest import import pytest L37–37
+ run_gc import import run_gc L39–39
+ write_commit import import write_commit L44–44
+ write_snapshot import import write_snapshot L44–44
+ runner variable variable runner L49–49
~ muse/cli/commands/gc.py .py 1 symbol added, 4 symbols modified
+ prune_stale_remote_refs import import prune_stale_remote_refs L39–39
~ run_gc
~ run
~ muse/core/gc.py .py 2 symbols added, 1 symbol removed, 11 symbols modified
MUSE_DIR import import MUSE_DIR L66–66
+ _remotes_dir import import _remotes_dir L67–67
+ prune_stale_remote_refs function function prune_stale_remote_refs L632–694
← Older Oldest on dev
All commits
Newer → Latest on dev

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:cfede0b60ec5f4c994ff8dc79d03af06d61e0fb150fc29bd970f3306e41e3884 --body "your comment"