Skip to main content

Module mutate

Module mutate 

Source
Expand description

Mutation with link maintenance — the crate’s hard, valuable half.

Creating, moving, and deleting a document are never single-file operations in a linked workspace: the spanning relation and its inverse live in other documents, and every touched link must keep pointing at the truth. Each op here computes the full set of affected documents, edits their metadata with fig’s comment-preserving fig::Embed editor (byte-minimal diffs, fence style and format untouched, labels on [label](path) links kept), and only then touches the filesystem.

§Identity is additive here (DESIGN §4)

Everything below operates on paths and never requires an ID. When a registry is present, each op additionally keeps it true — create registers (if the policy’s on_create fires), rename updates id → path, delete tombstones — and a colophon:<id> entry in another document’s metadata is deliberately not rewritten by a move: the registry update is what keeps it resolving, which is the entire point of linking by ID. With crate::identity::NoIdentity/prov_graph::index::NoIndex these hooks monomorphize to nothing.

The vocabulary is never hardcoded: the spanning relation and its inverse come from the workspace’s prov_graph::relation::RelationSet.

§Writes are staged, not issued

Every op here computes its edits and stages them into a ChangeSet, which lands as one unit — documents and, when the op moved an ID, the registry with them. No error can leave the workspace half-linked, and behind the write-ahead journal (crate::journal) no crash can either: an interrupted op resolves to the workspace fully before it or fully after it. Ops remain documents-only: no directory moves.

§Where the code lives

The module is split by what a reader is after: one file per verb, each an impl Workspace block.

  • create — a new document authored under a parent, in the parent’s shape.
  • adopt, reparent — an existing document linked under a parent: additively (adopt), or in place of the parent it already claims (reparent).
  • rename — a document’s path changes and every link that touched it follows; retitle — its title changes and every inbound label follows.
  • delete — the one verb that destroys a document; tombstone — the record it leaves in the workspace’s deletion log, with restore (the graph repair that record is for) and clear_deletions beside it.
  • separate — one combined document split into a metadata node and a body file, and combine back.
  • duplicate — a shallow copy as a fresh sibling.
  • convert — the re-spellings that move no document: a link’s style, and a metadata block’s language or embedding shape.
  • save — a content edit’s own bookkeeping (the content_hash and updated stamps), landed either with the caller’s new text in one write or reconciled afterward against what is already on disk.

maintain holds the plumbing those verbs share: walking the spanning relation (up to the root, down a subtree, along one entry), resolving the two files of a separated pair, and retargeting every inbound reference to a document that moved.

Tests sit in each file’s own mod tests, as elsewhere in the crate. The fixtures they share — a seeded workspace, a linked tree, a backend that fails the nth write — are in support, which no sibling could own without every other one reaching across for it.

Structs§

Created
The files Workspace::create wrote. Under a combined parent this is just the one document; under a separated parent it is the pair — the metadata node the parent links, plus its sibling prose body file — so a caller (the CLI) can report both.

Enums§

ContentState
What a document’s recorded content checksum says about its bytes right now.
Diagnosis
Whether a removal should work out what it breaks.
Reparented
What reparent actually did.