Documentation
¶
Overview ¶
Package ledger is dstow's current-state index of the symlinks it believes exist (DESIGN.md §6 + A10; ADR 0001). It is one JSON document per machine at $XDG_STATE_HOME/dstow/ledger.json — never a journal, never a history: entries are the links dstow currently believes exist, pruned wherever disk contradicts them (disk is always the truth).
The package splits cleanly along §6.3's read/write line. Load (§6.2/§6.3) is a lock-free snapshot that never creates or writes a file. Update (§6.2/§6.3, A10) holds an exclusive flock for the whole operation, prunes contradicted entries in scope, runs the caller's mutation, and commits with one atomic temp-file+fsync+rename. Contradicted is the single owner of the disk-disagrees test so report (reads) and prune (writes) can never disagree.
The package returns data and typed errors only (A4): it never writes to stdout/stderr and renders no prose for humans beyond its error strings, which carry the §6.5 remedies. RecordedAt is the caller's to stamp — entry creation belongs to the deploy verbs — so the package itself stamps nothing.
Index ¶
Constants ¶
const Version = 1
Version is the schema version this dstow writes and understands (§6.5). It is bumped only on an incompatible change; v1 is the first schema.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type CorruptError ¶
CorruptError refuses an unparseable or invalid-version ledger (§6.5): corruption must never degrade into amnesia, so Load names the path and points at the remedy rather than starting empty.
func (*CorruptError) Error ¶
func (e *CorruptError) Error() string
func (*CorruptError) Unwrap ¶
func (e *CorruptError) Unwrap() error
type Entry ¶
type Entry struct {
Link string `json:"link"` // target-relative, exactly how stow.Expected keys results
Package string `json:"package"` // canonical percent-encoded FQN
Source string `json:"source"` // package-relative
Destination string `json:"destination"` // literal symlink text as written — the damaged evidence
RecordedAt time.Time `json:"recorded_at"` // RFC 3339 UTC: when the entry entered the ledger
}
Entry is one ledgered link (§6.1). link is target-relative and source package-relative — exactly how stow.Expected keys and values its results — so ledger, Expected, and Owner compose directly.
func (Entry) Contradicted ¶
Contradicted reports whether disk disagrees with the entry under the given target root (CONTEXT.md "Contradicted entry"): the recorded path is gone, holds a non-link, or holds a different link text than recorded. Evidence is complete prose when contradicted, naming what disk shows against what the entry records. This is the one owner of the test — check (ops) consults it too, so report and prune can never disagree.
type Ledger ¶
type Ledger struct {
Version int `json:"version"`
Targets map[string][]Entry `json:"targets"` // absolute target root → entries; the grouping is rebuild's replace boundary
}
Ledger is the whole document (§6.1). Targets maps an absolute target root to its entries; the grouping is load-bearing — it is rebuild's replace boundary.
type LockedError ¶
type LockedError struct {
LockPath string
}
LockedError is fail-fast lock contention (§6.2): another dstow operation holds the ledger lock, and dstow refuses to wait (dpkg/pacman precedent).
func (*LockedError) Error ¶
func (e *LockedError) Error() string
type NewerVersionError ¶
NewerVersionError refuses a ledger written by a newer dstow (§6.5): never guess, never rewrite the file down — the remedy is to upgrade dstow.
func (*NewerVersionError) Error ¶
func (e *NewerVersionError) Error() string
type Pruned ¶
type Pruned struct {
TargetRoot string
Entry Entry
Evidence string // complete prose: what disk shows vs what the entry records
}
Pruned records one entry removed by scoped pruning: the target root it lived under, the entry itself, and the complete evidence prose (what disk shows against what the entry recorded). The caller reports each prune loudly (§6.4).
func Update ¶
Update runs a write transaction against the ledger (§6.2/§6.3, A10). It takes an exclusive non-blocking flock on the sibling lock for the whole operation (contention → *LockedError, immediately), then under the lock: takes a fresh Load (never a stale snapshot), prunes contradicted entries the scope covers (reporting each in the returned slice — the entry is pruned, disk is never touched), runs fn on the pruned document, drops any empty target group, and commits with one atomic write. fn returning an error aborts the transaction with no write.
type Scope ¶
type Scope struct {
Packages []string // canonical FQNs: prune entries of these packages
Paths []string // absolute link paths (target root joined with entry link): prune entries at these paths
All bool // the ledger-wide broom (clean §6.3)
}
Scope is a writer's pruning scope (§6.3): an entry is covered when All is set (the ledger-wide broom, clean §6.3), when its package is named, or when its absolute link path is named. Contradicted entries in scope are pruned; unrelated damage evidence survives.