zit 0.9.0 is about stores that live a long time and grow large: a forge's bare store written by an application, a horizon or sparse clone kept in sync for months, a history thinned to save space. It adds three verbs an application can drive without a checkout, makes commits and syncs cost what changed instead of what the tree holds, and closes several ways a clone or a pair of concurrent commits could lose or hide work.
This release is from trunk. The caches beside a store change format and are rebuilt once on first open; the store itself and the wire stay Fossil's.
New
commit -R STORE --stdin PATH -m MSGrecords one file's bytes from standard input as a check-in, with no checkout. It holds the store's lock throughout, so concurrent writers land in order. Unchanged bytes exit 3 and print the parent.--parent,--branch,--user,--allow-forkand--no-checksapply as they do to commit.log CHECKIN PATH -F jsonanddiff -F jsonreport a file's history and a two-version diff in Fossil's field names, so an application reads them without parsing text.log PATHandannotatefollow renames, continuing under the old name below the check-in that recorded one;--no-followgives the name-literal view.purge artifacts HASH...thins a file's history: it removes named file versions, keeps every check-in, and stays recoverable withpurge undountilpurge obliterate. A version any open leaf or the checkout holds is refused. A local.zit-thinnedlist keeps pull and serve from bringing removed versions back. It is never sent to peers.- Exit 8 means content absent by policy:
cat,diffandannotateof a version that was purged, shunned, or left out by a cone or horizon.diffused to show such a version as an emptied file, andannotatecredited a removed version's lines to the next one. zit serve --read-onlyserves clones and pulls and refuses every push.zit init --submanifest Kstarts a store with sub-manifests on and k pinned, so a tree that will grow wide is a tree from its first check-in.--cone-parentsgives a sparse cone the parents property: the root's files and the files directly in each parent directory of a member are covered too, so a narrow cone is navigable. The sparse-cone draft states the rule and itscone-parentspragma.
Faster
- A flat manifest is stored as a delta of its skip base, the ancestor at its height with the lowest set bit cleared, so no chain is deeper than popcount(height) and no commit stores a whole manifest. This is Subversion's skip-delta scheme, by Greg Hudson.
- Sync, pull and a server taking a push store a check-in received whole as a delta against its parent. A sender answers with the delta it already stores when the peer holds its basis, in Fossil's delta form. A pull of a few one-file check-ins now moves kilobytes.
repo-cksumis off unless turned on, so a commit no longer reads every blob in the tree for theRcard. Fossil writes the card by default;zit settings repo-cksum onrestores that.revertwith no paths finds what changed first, asstatusdoes, and restores only that.- A horizon clone's no-op sync resumes from its saved classification instead of classifying the whole store again.
- A large clone checks received deltas by walking each delta tree once instead of rebuilding every artifact through its whole chain.
crosslink --linesno longer flattens each parent's whole tree. On the Linux kernel store its first run covers 1.77 times as many check-ins in the same time.- The cache carries a checksum of its image alone and is read through a mapping, so opening a very large store checks what it reads instead of copying the whole cache onto the heap. File reads and writes move at most 1 GiB per call, so on macOS a cache past 2 GiB is reused instead of re-derived.
import-git --intoopens the destination through its saved scan index and checks mapped check-ins by lookup.
Fixed
- Two commits in one checkout could both succeed and fork the branch. A commit now refuses to publish when another moved its checkout while it was being prepared.
- A horizon clone's sync could stop uploading check-ins committed after its first sync. Its cursor now advances only by what it received.
- A horizon name tied on time resolves by ancestry before hash, as
updatedoes, so a branch committed within one clock tick resolves to its tip. - A client reports a busy peer only for the 503 a zit server sends for a held lock; any other 503 gets the plain status line.
- A pushed sub-manifest setting needs Setup as well as Admin, and a card refused for want of it refuses only itself.
Compatibility
The store and the wire are Fossil's. A stock fossil clone of a 0.9.0 store,
thinned or not, succeeds, and the delta form zit now sends is the one Fossil
already reads. Two things differ from 0.8.1 on disk: a new check-in has no
R card unless repo-cksum is on, and stored manifests are skip deltas,
which every reader expands as before.
The caches beside a store (.zit-cache) change format. The first open by
0.9.0 rebuilds them once, then they are reused. On a small store that takes
moments. On a store the size of the Linux kernel's history it took 43
minutes and 4.1 GB of memory, so a forge should open its large stores once
before serving traffic from them.
The sparse-cone, horizon and sub-manifest drafts gain the rules above.
Qualification
The release manifest records native qualification against the exact tagged source archive on macOS ARM64, Linux x86-64 and Linux ARM64, using the pinned Zig 0.17.0 toolchain. Publication is gated on unit and end-to-end tests, Git differentials, deterministic simulation, seeded fuzzing, and Fossil interoperability checks on every distributed target.
For the basis of the conformance claim, see the 0.1.0 release notes.