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, withrestore(the graph repair that record is for) andclear_deletionsbeside it.separate— one combined document split into a metadata node and a body file, andcombineback.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 (thecontent_hashandupdatedstamps), 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::createwrote. 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§
- Content
State - 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
reparentactually did.