This Day In History For 2027-08-18
1 Year Ago (more context)
|
2026-08-18
| ||
| 23:30 |
merge -X ours|theirs: resolve content conflicts wholesale (#91)
merge3 already resolved every region except one -- the case where both sides changed it differently. That branch now takes a side instead of always writing an envelope; the clean cases above it are untouched, which is the whole point. A region only one side changed is still that side's under either strategy, so -X is not 'discard their work', it is 'stop asking me'. The mechanical cases are what it is for: a regenerated lockfile, a vendored tree taken whole from upstream. Applies to content disagreements -- conflicting hunks, add-vs-add, and both-modified binaries. It deliberately does NOT resolve modify-vs-delete: that is a disagreement about whether the file should exist, not about its contents, and either reading silently destroys work. git declines it too. -X ours is not --backout, and the help says so outright: --backout reverses NAME's change, -X ours keeps your side where the two collide and reverses nothing. They read alike and do different things. Composes with precedent (#103) without either knowing about the other: precedent is a pass over the outcome set, so a strategy that leaves no conflict leaves it nothing to replay or record. Verified both ways -- -X records no precedent, and a plain merge still conflicts and records. A bad or missing -X value is a usage error rather than a silent fall back to markers, which would look exactly like a strategy that ran and found nothing. check-in: 52b8c57f4c user: dmestas tags: trunk | |
| 22:40 |
export-git: drop a verb-list line pasted into its usage block
'zit export-git --help' printed " \ import-fossil bring a fossil repository's history into zit" as its second line, backslash included. The verbatim help pins cover merge and stash only. The new pin checks shape instead: no rendered help line may start with a backslash, which catches the paste for every verb. The reference gains merge --no-precedent, which was documented under the wrong verb. check-in: 5fe0d9eafe user: dmestas tags: trunk | |
| 21:28 |
stash: reserve .zit-stash so it cannot be tracked
The sidecar was absent from the control-path registry, so extras listed it and add accepted it: an ordinary add put the contents of stashed work into a check-in and synced it to every peer, recoverable only by shunning. The stash help already promised "never an artifact"; nothing enforced it. Authoritative tier, matching what losing the file costs. check-in: 503637a369 user: dmestas tags: trunk | |
| 20:37 |
precedent: remember conflict resolutions and replay them
A merge records each conflict in the local .zit-precedent sidecar; commit attaches the resolution the operator settled on; a later merge whose conflicted bytes match replays it instead of writing markers. Keyed by path and conflicted bytes, exact because the diff3 envelope carries all three sides. Whole-file, so a file whose other conflict moved will not replay. Replay is named per file, never silent. --no-precedent declines for one merge without forgetting. 'zit precedent list|show|forget', alias rerere. The sidecar is a reserved advisory name, so it can never become an artifact. check-in: a9a24a857c user: dmestas tags: trunk | |
| 20:09 | • Changes to wiki page "Home" artifact: f711f33eaa user: dmestas | |
| 19:39 | fix(release): export tag-only mirror changes check-in: 91cc1528fc user: dmestas tags: trunk | |
| 19:37 | • Edit [4c2286bcb4]: Add tag "version-0.1.4". artifact: 0a381180f8 user: dmestas | |
| 19:22 | release: prepare zit 0.1.4 check-in: 4c2286bcb4 user: dmestas tags: trunk, version-0.1.4 | |
| 19:05 | release: qualify portable packaged binaries check-in: 4290d14e17 user: dmestas tags: trunk | |
| 17:53 |
reference: keep the index on narrow viewports
The sidebar was display:none below 800px, which is most of the time an embedded doc is read -- a panel, a phone, a split window. A 60-section reference with no navigation at all is worst exactly where scrolling costs most, and the rule was invisible because it only fires at widths you do not develop at. Below 800px the rail becomes a compact index above the content, links flowing as wrapped chips rather than one per line. It is collapsed by default there: expanded, it pushed the page title a full screen down, so a reader met a wall of verb names before learning what the page was. The disclosure is hidden entirely on the wide layout, where the rail is always open and the control would be noise. Verified in a real browser at 1400, 780 and 500 pixels: 70 index entries reachable at every width, against 1 before. check-in: 65fe7b9ec5 user: dmestas tags: trunk | |
| 16:04 |
www: embed the docs, pinned so the reference cannot drift
The command reference and the caching write-up move into the tree as embedded documentation, which quarry serves on fossil's own /doc/VERSION/PATH route, already implemented in its api/register.go. Fossil's www/embeddeddoc.wiki gives the reason to prefer this over the wiki, and it is the reason the pin below can exist: The documentation files are versioned together with the source code files so it is always clear what version of the documentation goes with a particular release. A wiki page cannot be pinned by a test; nothing ties it to a checkout. A tracked file can. reference_test.zig checks both directions -- a dispatched verb with no section, and a section naming no verb -- with a reviewed-exception list for sections that document an absence on purpose, which is what the export-fossil section is. The reference had drifted for weeks: grep, purge, config and trust all shipped undocumented, and nothing noticed because noticing needed a human to compare two lists. The caching page's ladder is corrected while embedding it. It reported 641.9s / 58.3s / 0.31s; those were Debug numbers. Measured in the mode that ships: 29.63s full derive, 0.34s record-body replay, 0.04s image. Having a cache is worth 87x and the image a further 8.5x -- both real, neither 188x. Its footnote about a separate environment reporting 0.38s 'unreconciled' is resolved: same machine, optimized build. info also moved to the image since it was written, leaving branch and tag on the record-body rung. check-in: 269e24b3c3 user: dmestas tags: trunk | |
| 15:13 |
branch and tag read the warm image: the resolved §5 tag surface (#98)
The image carries the active tag set now -- name, tagtype, optional value, per rid -- so tagsOf, branches, tagNamesMatching and activeTagValue all answer from either backing. Stored resolved: the derive has applied §5.1's cancel rule and §5.3's precedence before serialize runs, so nothing here re-judges either. That is what fossil does, where tagxref holds one row per (rid, tag) with propagation flattened in by tag_propagate at write time. It subsumes the §5.2 override columns from the previous change; those are gone rather than kept beside a general mechanism that already holds the same bytes. Two readers still went straight to tagxref and had to be routed: activeBranchValue and hasActiveClosed. Both answered plausibly on an image rather than refusing -- the first as a null-deref in a postcondition under safety and, with that assert compiled out, a different branch listing; the second as a listing quietly missing every (closed) marker. tagNamesMatching keeps a per-backing arm on purpose. The derive holds a (rid, tag) map with no per-rid index, so walking rids and asking each for its tags is O(rids x map) there; sharing one loop cost 42s where two cost 0.37s. check-in: ce9e7a1cd4 user: dmestas tags: trunk | |
| 14:12 |
build: how to measure this project without being lied to
Every rule was paid for by a wrong answer that looked convincing: an issue filed against this repository proposed an architectural change on the strength of a 58s figure that was a bare-zig-build Debug number; the ~25x pack figure this file carried came from a --release=fast that was quietly building ReleaseSafe; a single run reported a 20% regression for a change that was a 3.7x improvement; and an optimization that won by 50x was erroring out on the first artifact and printing nothing. It sits beside the build rather than in the wiki because each rule is only true of THIS build script -- bare zig build means Debug because of the line above it, and every --release resolves to the preference for the same reason. A page elsewhere would rot the day one of those changes and nothing would fail. check-in: 4e355fbfd1 user: dmestas tags: trunk | |
| 13:34 |
log: walk the derived adjacency, the way fossil does
The default listing prints an ID per check-in and reads nothing else, yet it reconstructed and re-parsed every reachable manifest to find P cards. On a repository whose manifests inline the whole file set -- sqlite's are 2,219 F cards and 186KB each -- that is 6GB of text decompressed and parsed to answer a question that reads none of it. Fossil does not do this. manifest_crosslink parses a manifest once and writes the edge to a persistent table: CREATE TABLE plink(pid, cid, isprim, mtime, baseid, UNIQUE(pid,cid)); CREATE INDEX plink_i2 ON plink(cid,pid); Every later traversal is an indexed read of it -- timeline.c's ancestor walk is a recursive CTE over plink and touches no manifest. The tell is fossil's parsed-manifest cache: MX_MANIFEST_CACHE is 6, and its comment says it exists for rebuild. Nothing on the read path needed more. zit's derive holds the same relation, with the is_primary flag plink's isprim carries, and since #98 the zero-parse image carries it too, so this walk reads no artifact content at all. --long still needs D/U/C, so it stays on the reading walk. log tip, min of repeated runs, warm, ReleaseFast: libfossil 1.28s -> 0.02s libspatialite 4.81s -> 0.00s fossil 20.40s -> 0.11s tcl 40.05s -> 0.65s sqlite 62.90s -> 0.51s Output byte-identical across all seven corpora. WHAT MOVED: the reading walk re-hashed and re-validated every reachable artifact, so log doubled as an integrity check. It no longer does -- which is fossil's split, where validation happens at crosslink and test-integrity re-checks. zit verify is that verb, and the wrong-full-ID test now asserts verify catches what log stopped catching, so the coverage cannot go missing unnoticed. check-in: cc996c1af2 user: dmestas tags: trunk | |
| 13:07 |
info reads the warm image too: §5.2 overrides, resolved (#98)
info was the last of the three verbs held on the record-body rung, and it was held by one thing: amend --comment stores its override as a tag, and tagxref is empty on an image backing, so the fast path printed the manifest's original comment. On tcl that cost 58s to print one check-in. The image carries the three display overrides now -- comment, user, date -- RESOLVED. The derive has already applied the cancel rule and mtime precedence by the time they are written, so the image stores the answer and never re-judges it, the same trade branch_id already makes with the §6.1 fallback. That is also what fossil does: tagxref holds one row per (rid, tag) with propagation flattened in by tag_propagate at write time, so its readers do group-bys rather than precedence. activeTagValue now asserts derived backing instead of answering null there. It returned null for a caller that had a tag, which is the silent shape of wrong this whole issue is about; displayOverride is the image-safe door for the subset the image actually carries. check-in: 8c3abc36c7 user: dmestas tags: trunk | |
| 02:18 |
ls, cat and bisect read the warm image instead of re-deriving (#98)
On tcl's tip zit ls drops from 58.3s to 0.31s: the derived state it needed was already in the cache, in the zero-parse image, and the verb asked for the record-body replay anyway. Adjacency arrived in the image last change; what remained was every read that went around the accessors. events, its count, and store.count are all empty on an image backing, so a bound taken from them read zero and a branch value read from tagxref fell back to main_branch for every rid -- the section 8.4 walk then never left the branch and answered start:/root: with a check-in from somewhere else, exit 0 and no diagnostic. Those reads route through hasEvent, mtimeOf, hashOf, ridCount and eventsIter now, which name one enumeration order for both backings rather than inheriting insertion order from one of them. info stays on the full derive: amend --comment stores its override as a tag, and the image carries no tag tables, so on the fast path info printed the manifest's original comment. An existing test caught that the moment the verb moved; branch and tag stay behind for the same reason. check-in: 2772dd3942 user: dmestas tags: trunk | |
| 02:10 |
log: memoize the delta bases the walk re-resolves
walkLog reconstructed every manifest with log.content, which walks the delta chain from scratch. Check-in manifests are routinely stored as deltas against their neighbours, so the same base chain was re-resolved once per check-in -- work that grows with the history behind a node rather than with the node. Per-check-in cost climbed with repository size (0.5ms on libfossil against 2.2ms on sqlite) instead of staying flat. Every other read path in this file already took #84's PlaintextCache; this one did not. Output is byte-identical -- contentCached is the same bytes, only less work. log tip, min of repeated runs, warm, ReleaseFast: pikchr 0.14s -> 0.04s wapp 0.05s -> 0.01s libfossil 1.26s -> 0.34s libspatialite 4.69s -> 2.28s fossil 19.36s -> 7.24s sqlite 59.70s -> 23.81s tcl 38.29s -> 5.99scheck-in: 55b176c8dd user: dmestas tags: trunk | |
| 00:02 |
repoimage: carry adjacency, and read it through one door (#98)
The image held mtimes, hashes, branch ids and the symbol table but not the parent/child relation, which is why every verb needing ancestry re-derived the whole log on open. Six CSR columns carry it now, both directions with the primary flag -- primary-parent selection and merge-edge skipping both read it, so an image without it answers wrongly rather than refusing. The two backings hold the same relation in different shapes, so edgesOf hides which one a caller got, and the equivalence test compares them in order with a guard that fails when the corpus has no edges to compare. Behaviour-neutral: no assert relaxed, no verb moved. Freeing those needs an events equivalent as well -- resolve reads self.events directly, and that table is empty on an image backing. check-in: 82de6f83d0 user: dmestas tags: trunk | |