Expand description
Refs subsystem.
Implements the local-disk side of docs/specs/SPEC-REFS.md: ref names,
the 65-byte wire encoding, the symbolic-or-detached HEAD file, and
shallow-boundary persistence at .mkit/shallow.
Wire format (per SPEC-REFS §1): exactly 64 lowercase-hex characters
plus a trailing 0x0A newline = 65 bytes. Uppercase hex is rejected
on read. Trailing \r and ASCII whitespace are tolerated when
parsing local files (so a Windows-edited HEAD does not brick a
repo), but fresh writes always emit the strict 65-byte form.
Ref name grammar (SPEC-REFS §3): [A-Za-z0-9._-]+ segments joined
by /, with no leading/trailing /, no ./.. segments, no
backslashes, no NULs. In addition, no segment may end in .lock
(the canonical lock-file suffix) and the final segment may not be
the literal HEAD (which would shadow the repo-level HEAD
pointer). We share the validator with the future transport layer
via validate_ref_name / validate_ref_prefix.
CAS variants for update_ref follow SPEC-REFS §5: Any (clobber),
Missing (fail if it exists), Match(H) (fail if current value !=
H). As of #637, the local-filesystem Match read-compare-write is
serialized under a shared refs.lock in the common dir (the same
blocking kernel-lock primitive repo_lock uses elsewhere), so it is
atomic across processes regardless of what other locks each caller
holds — this closes the v1 gap previously documented here.
Structs§
- Ref
- A listed ref entry: name (with
refs/heads/or similar prefix stripped) plus the resolved hash, when readable. - Remote
RefBatch - Batched writer for remote-tracking refs (#645): amortises the
parent-directory fsync across every ref written into it, instead of
paying one per ref like
write_remote_refin a loop.
Enums§
- Head
- HEAD pointer: either a symbolic reference to a branch name, or a detached hash.
- RefError
- Errors raised by this module.
- RefWrite
Condition - CAS condition for
update_ref.
Constants§
- HEADS_
DIR - Subdirectory holding branch refs (
.mkit/refs/heads). - HEAD_
FILE - HEAD file relative to the
.mkitroot. - REFS_
DIR - Subdirectory holding all refs (
.mkit/refs). - REMOTES_
DIR - Subdirectory holding remote-tracking refs (
.mkit/refs/remotes). - SHALLOW_
FILE - Shallow-boundary file relative to the
.mkitroot. - TAGS_
DIR - Subdirectory holding tag refs (
.mkit/refs/tags).
Functions§
- decode_
ref_ wire - Decode a ref wire blob into a
Hash. Tolerates a trailing newline /\r/ ASCII whitespace (so files round-tripped through a Windows editor still parse), but rejects uppercase hex per SPEC-REFS §1. - delete_
ref - Delete a branch ref. Errors with
RefError::NotFoundif absent. - delete_
ref_ if_ matches - CAS-guarded delete: removes a branch ref only if its current on-disk
value is exactly
expected. Issue #658. - delete_
ref_ safe - Delete a branch ref unless it is the currently checked-out branch.
- delete_
ref_ safe_ with_ history delete_ref_with_historyguarded by the same current-branch check asdelete_ref_safe— refuses to delete (and does not touch the journal of) the branch HEAD currently points at. This is the history-mmr counterpartmkit branch -d/-Droute through.- delete_
ref_ with_ history - Delete a branch ref and permanently destroy its history-MMR journal partition, so a later branch created with the same name never resumes a deleted incarnation’s leaves (issue #648).
- delete_
ref_ with_ history_ if_ matches delete_ref_with_history, but CAS-guarded likedelete_ref_if_matches: only deletes (and destroys the journal of)branchif its current on-disk value is exactlyexpected. Issue #658 — thehistory-mmrcounterpartmkit branch -mroutes through so a rename’s rollback of a lost race also drops the correct journal.- delete_
remote_ ref - Delete a remote-tracking branch ref (e.g. after the upstream
deleted the branch). Errors with
RefError::NotFoundif absent. - delete_
tag - Delete a tag ref.
- encode_
ref_ wire - Encode
hto its 65-byte wire form (lowercase hex +\n). - init
- Initialise the ref layout: creates
refs/,refs/heads/,refs/tags/,refs/remotes/under the common dir and writes a defaultHEAD = ref: refs/heads/main\ninto the worktree state dir ifHEADdoes not already exist. - list_
refs - List all branch refs, sorted lexicographically by name.
- list_
remote_ names - List the remote names that have at least one tracking ref on disk
(the immediate subdirectories of
refs/remotes/), sorted. A missingrefs/remotes/yields an empty list. Entries whose names fail the ref grammar are skipped (consistent with how malformed ref files are skipped bylist_refs). - list_
remote_ refs - List all remote-tracking refs for one remote.
- list_
tags - List all tag refs, sorted lexicographically by name.
- load_
shallow_ boundaries - Load shallow-boundary hashes from
.mkit/shallow. ReturnsOk(None)if the file does not exist or is empty. - open_
and_ update_ ref_ with_ history_ and_ backfill update_ref_with_history_and_backfill, but closes a race that shape leaves open when two concurrent writers have never touchedbranch’s journal before:CommitHistory::open_atruns AFTER the per-branch lock is acquired here, not before, so a concurrent writer already holding the lock can never be mid-sync(writing the on-disk metadata blob) while this call’s ownopen_atreads it — see this module’s privateupdate_ref_with_history_critical_sectionhelper’s doc comment for the full mechanism.mkit-cli’swrite_ref_recording_historyis the production caller.- parse_
lowercase_ hash - Strict lowercase-only hex parser: exactly
HEX_LENlowercase-hex bytes, decoded in a single pass. SPEC-REFS §1 forbids uppercase on read; the generalhash::from_hextolerates both cases for programmatic callers, so this is the stricter variant every on-the-wire / on-disk reader (ref wire blobs, the applied-packs record) shares to keep a hand-edited or foreign-cased line malformed rather than silently accepted. - read_
head - Read this worktree’s
HEAD. - read_
ref - Read the hash a branch ref points to. Returns
Ok(None)if the ref file does not exist. - read_
remote_ ref - Read a remote-tracking branch ref.
- read_
tag - Read the hash a tag points to.
- resolve_
head - Resolve
HEADto a commit hash. ReturnsOk(None)when HEAD points at a branch that has no commit yet. - update_
head - Update the ref HEAD currently points at (or HEAD itself, if
detached) to
commit_hash. - update_
ref - CAS-aware ref write per SPEC-REFS §5.
- update_
ref_ with_ history - Combined ref-write + history-MMR-append, protected by a single repo-level lock. Issue #157.
- update_
ref_ with_ history_ and_ backfill update_ref_with_history, additionally backfilling an empty journal fromparent_ofbefore the CAS-write + append — all inside the SAMErefs-history.lockacquisition (issue #638 / INV-18).- update_
tag - CAS-aware tag write — same semantics as
update_refbut forrefs/tags/. - validate_
ref_ name - Validate a ref name per SPEC-REFS §3. Used at every transport boundary; transports MUST NOT silently lower-case or canonicalise.
- validate_
ref_ prefix - Validate a prefix passed to
list_refs. An empty prefix is allowed. A single trailing/is allowed; otherwise the prefix must satisfyvalidate_ref_name. - write_
head_ branch - Write
HEADas a symbolic ref pointing atbranch. - write_
head_ detached - Write
HEADas a detached hash. - write_
ref - Write a branch ref (unconditional — equivalent to
update_ref(branch, RefWriteCondition::Any, h)). - write_
remote_ ref - Write a remote-tracking branch ref unconditionally.
- write_
shallow_ boundaries - Write shallow-boundary hashes to
.mkit/shallow. Passing an empty slice removes the file. - write_
tag - Write a tag ref (unconditional).
Type Aliases§
- RefResult
- Result alias used throughout this module.