Skip to content
zit Today In History
Login

Today In History

This Day In History For 2027-08-17

1 Year Ago (more context)

2026-08-17
22:54
build: the ~25x pack figure does not reproduce; record what does

Measured on wapp warm, modes interleaved and repeated: pack is ~8.5s fast, ~9.5s safe, ~10.7s small, and the read path is 0.31/0.33/0.36 with leaves at 0.01s in all three. So fast buys ~12% on writes and nothing measurable on reads.

The '599ms fast against 15.2s safe, ~25x' this file carried reproduces in neither the ratio nor the absolutes; the delta encoder's search was reworked since it was taken. Left uncorrected it would have justified almost any correctness cost, which is the expensive kind of stale number to leave in a comment that decides the shipped build. check-in: 6181a57e0c user: dmestas tags: trunk

22:37
build: ship ReleaseFast

zit ships ReleaseFast, so --release names it. This reverses the ReleaseSafe pin; pack runs ~25x faster and read verbs are indistinguishable between the modes (ls over tcl's 300MB store is 0.31s fast against 0.33s safe, leaves 0.01s in both).

The cost is real: over a thousand std.debug.assert calls compile to nothing, so release_assert_test.zig stops being belt-and-braces and becomes the thing keeping an assert from standing in for validation of untrusted input. Its rationale is rewritten around that.

Stating a preference makes it the ONLY reachable release mode, which the old comment got wrong: it documented --release=fast as an escape hatch from the ReleaseSafe pin, and that flag produced a ReleaseSafe binary anyway -- safety strings present to prove it. Anything benchmarked through it before now measured the checked build. The ci pin moves from 'keeps assertions alive' to 'the mode is stated, not left to whoever packages', which is the part that survives the reversal. check-in: da904fbe1c user: dmestas tags: trunk

21:30
CI: assert fossil's version, do not only print it (#100)

smoke is the only lane that runs a real fossil against zit, so runners on different fossils make the conformance claim mean a different thing on each -- a regression against the newer can pass on the older, and newer-only behaviour reddens the older for something that is not a defect. Both are silent, because the version is printed hundreds of log lines before the failure it explains. fossil sqlite3 quoting its output on 2.26 but not 2.28 cost three round trips that way. The printed line stays; the release notes still need it. check-in: ab3a1983cb user: dmestas tags: trunk

20:25
grep -S and -G: the pickaxe over history (#92)

-S reports the check-ins where the occurrence count of PATTERN changed, -G those where a changed line mentions it. A string added once and deleted later is two lines, where plain grep reports every version that held it in between.

The issue expected this to need a diff per revision. It does not: a path whose blob hash matches its parent's cannot have moved either answer, so the walk compares F-card hashes and reads only the blobs that changed. Deletions are picked up from the parent side, which a walk over the child's files alone would miss.

Merges compare against the primary parent, as git log -S does; counting against every parent reports one appearance twice. check-in: 28c48bb3f7 user: dmestas tags: trunk

20:00
archive differential: fossil sqlite3 quotes its output on 2.26 (#95)

The runner on 2.26 returns the check-in uuid wrapped in single quotes where 2.28 returns it bare, so the name handed to fossil tarball could not resolve -- and the failure named the hash, which reads like a missing check-in rather than a quoting difference. The harness strips to hex and then insists on a 40- or 64-character hash, so a future output change is refused by name here instead of failing two commands later. The CI step no longer runs its own copy of the query; one place for this to go wrong is enough. check-in: f37a155d45 user: dmestas tags: trunk

19:42
archive differential: fossil's documented argument order, and print its errors (#95)

One runner carries fossil 2.26 where the others carry 2.28, and 2.26 refuses options before the positionals -- fossil documents 'tarball VERSION OUTPUTFILE [OPTIONS]' and 2.28 merely tolerated the other order.

The reason that took a full CI round trip to find is the second change: a failure said 'see $WORK/x.log' on a machine nobody can log into. It now prints the log, so fossil's own sentence reaches the build output. check-in: e492130985 user: dmestas tags: trunk

19:28
-R: say which mistake was made, not 'no checkout here' (#97)

The discovery message tells the operator to name the repository with -R. For a -R failure that advises supplying the flag already supplied, and it reads the same whether the path was mistyped or simply holds no repository -- so a stale path in a script looked like a bug in the verb. Reported against tarball; every -R verb had it. One reporter, routed through all nine resolveRoot call sites; the no-flag discovery message is unchanged. check-in: 10a1236a7a user: dmestas tags: trunk

19:28
archive differential: unpack zips without an unzip binary (#95)

The runners have no unzip, so the harness exited 2 for a missing tool and the step failed on its own coverage guard instead. Adding a third tool to the battery for one step is the worse trade: python3 is already required here, and ZipFile.extractall drops modes and symlinks -- the exact defect this differential exists to catch -- so the external attributes are applied explicitly rather than trusted to an extractor. check-in: 2420f6fb88 user: dmestas tags: trunk

19:16
ci: the archive differential asserts on output it never captured

archive-fossil-diff.sh writes the per-format comparison to stderr, but the step piped only stdout into diff.log, so the 'kinds compared' line the coverage guard greps for was never in the file -- it counted 0 on every platform and the step could not pass.

pipefail with it: the pipeline was taking tee's status, so the differential's own failure, including its exit 2 for a missing tool, was swallowed and only the guard could ever fail this step. check-in: 98243aad6a user: dmestas tags: trunk

19:00
zit purge: recoverable removal of leaf check-ins (#87)

Removes a check-in and the blobs only it introduced, into a local graveyard that purge undo restores and purge obliterate empties.

The drop set is (seed + reachable(seed)) minus reachable(everything retained), so a blob a surviving check-in still names is never freed -- dropping it would create a phantom rather than reclaim anything. Only leaves go, judged over the whole named set: purging a parent alongside its child is accepted, purging it alone is refused.

Reuses shun's rewriteAndSwap and records no tombstone: a purge is local, so content that already synced comes back from a peer. The help says so and points at shun. check-in: 8536f59fba user: dmestas tags: trunk

18:41
ls: size from the frame header, full names through the index (#96)

A blob's plaintext length is already in every frame kind -- a zlib container states it outright, a delta carries it in its own header -- so --size reports one without resolving a chain. The binary verdict cannot be had that way (a NUL may be the last byte), so --long still reads every blob and keeps its exact columns.

The larger cost was neither: resolveHexPrefix scanned the whole store per file to resolve a full-width name the digest index answers outright, which slowed plain ls too. On tcl's tip --long drops 167s to 93s and --size costs what plain ls costs. check-in: 3b7e8c7569 user: dmestas tags: trunk

17:12 • Edit [e091f2ac80]: Mark "Closed". artifact: c640720389 user: dmestas
17:10
smoke S11: a stock fossil push refused by the content policy (#88)

Unlike S10, which its own comment notes survives deleting the server's admission check, this one genuinely exercises the decision: the violating file is ordinary new content fossil pushes because it is new.

Records the limitation in the header: fossil exits 0 after printing the refusal, so the assertions are on the store and on fossil's output rather than its exit status. zit push exits 1. check-in: abc41cae82 user: dmestas tags: trunk

16:41
serve refuses a push that violates its content policy (#88)

#81's predicates bind a checkout; nothing stopped a push from a clone that never adopted them, or from stock fossil. Fossil cannot close this at all -- its hooks are before-commit (client-side) and after-receive.

The policy is the SERVER's, resolved per round from its own settings, never from the artifacts arriving: a push carrying its own policy would otherwise arrive bearing permission to land. Only inspecting rules cross the wire; before-commit has no server-side counterpart.

A push sends artifacts by hash and only a manifest names paths, so the walk is manifest-first -- the policy gates what becomes REACHABLE, not what bytes transit. Decided before ingest, so a refusal stores nothing, and the whole round is refused rather than half of it.

Verified against fossil 2.28: it prints the refusal text verbatim and lands nothing. Note it exits 0 while doing so, where zit push exits 1. closed check-in: e091f2ac80 user: dmestas tags: push-policy

16:41
grep: search a file's history for a literal (#92)

zit had no content search at all -- not git's pickaxe, not fossil grep's file-scoped walk. This is the latter: each named file's stored versions newest-first, every version whose content contains PATTERN reported with line numbers. A run of check-ins that never touched the file shares one blob and reports once.

PATTERN is literal; zit carries no regex engine and git log -S is literal for the same reason. Working-tree search stays ripgrep's job -- what only zit can do is read content that is not on disk.

A version the store cannot produce is counted and reported on stderr, not skipped: a search that quietly examined less looks like one that found nothing. Exit 0 found, 1 not found. check-in: a0ab591180 user: dmestas tags: trunk

16:20
zip: the same archive in the format Windows reads (#95)

Selection, top-level directory, reproducibility, and the refusal to write a partial archive are shared with tarball whole; only the container differs. Zip's header carries the size and CRC, so a member is compressed before its header is written, and deflate is used only when it makes the member smaller. Modes live in the central directory's external attributes, which is where a reader looks and where an executable silently becomes 0644 if you get it wrong -- so the fossil differential compares both formats now. check-in: c454de8df9 user: dmestas tags: trunk

15:32
tarball: check zit's archives against fossil's, modes included (#95)

Comparing zit to itself cannot catch a wrong permission bit -- writer and reader agree in the same direction. Fossil is an independent witness that already gets it right, so the harness unpacks both archives and compares member set, modes, and contents. It found one: -R was dropped at dispatch, which every test missed by running inside a checkout. Fossil versions symlinks where zit add still refuses them, so an imported corpus is also what finally exercises the l-perm path. check-in: 96a6d46d19 user: dmestas tags: trunk

14:41
tarball: write a check-in's files as a reproducible gzip tar (#95)

The effective-set walk already resolves sub-manifests and delta chains in canonical order, so this is that walk with an archive writer. Members carry the F card's permission, so an executable stays executable. Two runs of one version are byte-identical: history supplies the order and the timestamps, and no uid, gid, or build host is recorded. A file the store does not hold is refused by name -- a partial archive looks exactly like success. check-in: 580d0691c7 user: dmestas tags: trunk

14:29 • Closed ticket [a679b1197b]: tag list conflates release names with raw and propagating tags plus 2 other changes artifact: 678596fc39 user: dmestas
14:29
Merge tag-list release filtering to trunk

Plain tag listing now reflects only singleton symbolic release names, while raw listing preserves complete repository tag state.

Refs ticket a679b1197b61127930f7e2a6478145c561dd54cc. check-in: 24356ebb90 user: dmestas tags: trunk

14:28
Fix tag list release-name filtering

Plain tag list now shows only singleton symbolic names globally and on a check-in, excluding branch machinery, raw properties, and propagating tags. Raw listing preserves every active tag, stored prefix, and value.

Add a tag-type-filtered repository-state query and end-to-end coverage for mixed singleton, propagating, raw, and branch tags.

Refs ticket a679b1197b61127930f7e2a6478145c561dd54cc. closed check-in: 41852f0a9e user: dmestas tags: fix-tag-list-release-filter

13:58
Create new branch named "fix-tag-list-release-filter" check-in: cf62ee5ea1 user: dmestas tags: fix-tag-list-release-filter
13:58 • New ticket [a679b1197b] tag list conflates release names with raw and propagating tags. artifact: a192e0fc20 user: dmestas
13:33 • Edit [f01eb5b6a0]: Mark "Closed". artifact: 36c8ca0bf7 user: dmestas
13:33
merge quarry-support: ls --long and log --long (#96, #93) check-in: 15fa309b01 user: dmestas tags: trunk
13:27
ls --long and log --long: one invocation answers a page (#96, #93)

ls --long adds size, the F card's permission token, and text/binary. The permission is the fact no other verb can supply -- it lives in the manifest, and the blob it names does not know it is executable -- so a listing could not mark executables and mis-rendered symlinks. --under bounds the listing to one directory, which is also what makes --long's per-file content read affordable.

log --long adds each check-in's timestamp, user and comment. log CHECKIN PATH already selected the check-ins touching PATH; emitting only hashes meant a file-history page cost a subprocess per row.

Both are opt-in; the default outputs are byte-identical. A blob the store cannot produce reports 'absent' rather than a zero-byte text file. closed check-in: f01eb5b6a0 user: dmestas tags: quarry-support

11:06
merge sparse-cone: classify paths against the cone and name the deciding member (#79) check-in: 187ad81e8c user: dmestas tags: trunk
01:05
cone test: classify paths against the cone and name the deciding member (#79)

Longest match across both polarities decides coverage, so the verdict alone cannot say why a file is missing. The member prints bare so it pastes into zit cone remove. Exits 0 when every path is covered, 1 when any is elided. closed check-in: 3cb62134a3 user: dmestas tags: sparse-cone

00:14
Create new branch named "sparse-cone" check-in: a620c24254 user: dmestas tags: sparse-cone