pub fn write_ref_recording_history(
layout: &RepoLayout,
branch: &str,
condition: RefWriteCondition,
new_hash: &Hash,
) -> Result<(), RefError>Expand description
CLI-side ref-write helper that records every advance in the
branch’s history MMR when history-mmr is enabled.
Behaviour matrix:
- Default build (no
history-mmr) — exactly equivalent torefs::update_ref(mkit_dir, branch, condition, new_hash). --features history-mmr— takes therefs-history.lockrepo lock, THEN opens a journaledCommitHistoryforbranchunder<mkit_dir>/history/(lock-then-open, not the reverse — seemkit_core::refs::open_and_update_ref_with_history_and_backfill’s doc comment for why), performs the CAS ref-write, appendsnew_hashto the MMR, andsync()s the journal before returning. The journal survivesSIGKILLimmediately after the call returns. Seemkit-core::refs::open_and_update_ref_with_history_and_backfilland SPEC-HISTORY-PROOF §4 for the contract.
If the journal is empty but branch already has a ref value on
disk (a v0.1.x-era repo enabling history-mmr for the first time,
or a crash on the branch’s very first tracked write), this backfills
the full known chain via mkit_core::history::rebuild_from_chain
before proceeding — SPEC-HISTORY-PROOF §4.5. The empty-journal check
AND the backfill loop run inside
mkit_core::refs::update_ref_with_history_and_backfill’s
refs-history.lock critical section (issue #638 / INV-18): running
them before the lock (as this used to) let two ref-only writers on
the same never-before-journaled branch — e.g. two concurrent
update-ref calls, which deliberately skip the worktree lock — both
observe an empty journal and both independently backfill, corrupting
the journal’s leaf positions.
All CLI subcommands that move a branch ref MUST funnel through this
helper rather than calling refs::write_ref or refs::update_ref
directly. Detached-HEAD writes (refs::write_head_detached) are
not history-tracked: the per-branch journal is keyed on the branch
name, and detached HEADs have none.