Support .. range syntax in muse log
Context
Issue #27 added .. range syntax to muse diff and noted that muse rev-list already supports it. muse log a..b was deferred because it requires more than arg-parsing sugar — it needs a stop-at walk.
Desired Behavior
muse log dev..feat/x
Show only commits reachable from feat/x but not reachable from dev — i.e. the commits unique to the feature branch. This is the standard meaning of A..B in log context.
Why This Is Different From muse diff
muse diff a..b is pure sugar — split the arg, pass two refs to the existing two-commit diff path.
muse log a..b requires a new walk strategy:
- Resolve
AandBto commit IDs - Walk from
B, collecting commits - Stop (exclude) any commit reachable from
A
muse log currently accepts one ref and walks from there to root. It has no exclude/stop-at mechanism. muse rev-list already implements this via _parse_range_ref and ancestor exclusion — that logic needs to be ported or shared with log.
Implementation Sketch
| File | Change |
|---|---|
muse/cli/commands/log.py |
Detect .. in the ref positional, split into (exclude_ref, start_ref), pass exclude_commit_id to the walk |
muse/core/commits.py (or equivalent) |
Add a walk_excluding_ancestors(start, exclude) helper, or reuse the one already in rev_list.py |
muse rev-list has the ancestor-exclusion walk at _ancestors_of — worth extracting to a shared utility rather than duplicating.
Acceptance Criteria
muse log dev..feat/xshows only commits onfeat/xnot reachable fromdevmuse log dev..feat/x --jsonreturns the correct filtered commit listmuse log feat/x(no..) still works as before_ancestors_ofor equivalent is extracted to a shared location rather than duplicated betweenlogandrev-list
Implemented in MP #4 (merged). The stop-at walk was added to
muse/cli/commands/log.pyusingmuse.core.graph.ancestor_idsto compute the exclude set, then filtering raw commits before display. TDD coverage intests/test_log_dotdot_range.py— 8 tests (LOG_DR1–LOG_DR8) covering: plain ref still works, feature-only commits shown, empty when same ref, JSON schema, -n limit, unknown exclude ref errors, unknown include ref errors, and raw commit IDs as refs. All 8 pass.