gleamunison/publication_index
The store-local publication index: one name hash line per published
subject, at the path cli_lifecycle.manifest_path hands out, terminated by
a newline. Published manifests are bytes other tooling reads, so this
module is the only parser, renderer and writer of that format — publish,
unpublish and purge all go through it and none of them re-derive the line
shape or the write dance.
Two rules each caller used to restate on its own:
- A MISSING index is an empty one (nothing published yet). Any other read failure is an error: flattening it into an empty index let a rewrite truncate content the command never managed to read.
- A rewrite goes through
<path>.tmpand a rename, so a crash mid-write leaves the previous index intact instead of half-written.
Types
One index line. Opaque is a non-empty line the format does not recognise;
a rewrite keeps it verbatim rather than dropping bytes it cannot interpret.
Blank lines carry no information and never survive parse.
pub type Line {
Entry(name: String, hash: String)
Opaque(text: String)
}
Constructors
-
Entry(name: String, hash: String) -
Opaque(text: String)
Values
pub fn describe(
label: String,
failure: Failure,
) -> #(Int, String)
Render a failure in the wording the index commands have always used:
<label>: cannot <stage> the index: <detail>.
pub fn hash_of(
lines: List(Line),
name: String,
) -> option.Option(String)
The hash name is published under, if it is published at all.
pub fn parse(content: String) -> List(Line)
Parse index text into lines, dropping the blanks the trailing newline and any empty line produce.
pub fn read(path: String) -> Result(List(Line), Failure)
Read and parse the index. A missing file is an empty index; every other read failure is reported instead of being flattened into “nothing published yet”.
pub fn render(lines: List(Line)) -> String
Render lines back to the exact on-disk shape. An empty index renders as a lone newline, which is what every writer of this file has always produced.
pub fn replace(
path: String,
lines: List(Line),
) -> Result(Nil, Failure)
Write lines to the index atomically: content goes to <path>.tmp first and
is renamed into place, so a crash mid-write leaves the previous index intact.
A failed replace removes the temp file rather than leaving litter in a store.
pub fn rewrite(
path: String,
lines: List(Line),
keep: fn(String, String) -> Bool,
) -> Result(Nil, Failure)
Rewrite the index keeping the entries keep accepts, by name and hash.
Lines the format does not recognise are always kept.
pub fn upsert(
path: String,
lines: List(Line),
entries: List(Line),
) -> Result(Nil, Failure)
Replace the index with entries taking the place of any existing line for
the same name — publish’s upsert, which is how re-publishing a def moves its
recorded hash without disturbing the rest of the index.