Skip to content
go-libfossil Timeline
Login

Timeline

20 descendants of 15762adeb6bb427a

2026-10-13
17:32
chore(release): v0.12.0 changelog (#435) leaf check-in: 7a25e35893 user: [email protected] tags: main, trunk, v0.12.0
16:51
fix(manifest): maintain the leaf table incrementally (RS-7.3-3) (#434)

* fix(manifest): maintain the leaf table incrementally (RS-7.3-3)

The leaf table was recomputed from scratch at the end of every crosslink batch, so a check-in lost its leaf verdict whenever a later batch linked an untagged child to it. repo-state-01 Section 7.3, as corrected, and fossil keep that verdict: a check-in and its plink parents are rechecked only when a branch tag is written to it or propagation updates or deletes its branch row (src/tag.c:195, :100-102), and the checks run when the batch ends (src/leaf.c leaf_do_pending_checks).

The rule now lives in a new internal/leaf package: Check (leaf_check), Rebuild (the explicit full rebuild) and Pending (the deferred schedule). internal/tag schedules a recheck at exactly the branch-row writes; the crosslink sweep, receive linker and repair gate apply a batch's schedule at the gate, each phantom-fill cascade transaction and each commit or tag transaction apply their own before commit, and verify.Rebuild keeps the whole-table recompute. Reparenting schedules nothing, as in fossil, so the reparent case is split into a one-batch case and a per-artifact case.

Tracked in #426.

* fix(manifest): recheck leaves a cancel reaches; drop rechecks of a failed receive tx check-in: 628f932301 user: [email protected] tags: main, trunk

16:10
test(conformance): refresh the corrected sync §9.4 erratum (#431)

zit check-in 00e1711e802e corrects the erratum's account of Fossil 2.28: forbid-delta-manifests defaults on only since 2.29, and 2.28 defaults it off. The draft text is unchanged. Re-pin the erratum copy and its SHA-256 in the sync requirements table, and record the check-in in the README. check-in: caa2797892 user: [email protected] tags: main, trunk

15:55
test(conformance): re-pin the -01 drafts with the 2026-10-13 errata (#430)

* test(conformance): re-pin the -01 drafts with the 2026-10-13 errata

Re-pin the repo-state and sync-protocol drafts to zit check-in 5a1b741b25d8, which applies five more -01 errata: repo-state §5.3, §7.3 and §8.3, sync-protocol §9.4/§9.5 and §10.1. zit now keeps each -01 text under the -00 file name; the copies keep their -01 names and conformance/rfcs/README.md records the zit path and check-in. The new errata are pinned, and the requirement tables are re-read against every changed hunk.

The §7.3 and §8.3 cases that were deviations now pass as written, and new cases cover a date tag's arrival order (§5.3), untagged leaves and a merge parent's recheck (§7.3).

The sync server answers each guard-passing ci-lock with pragma avoid-delta-manifests while forbid-delta-manifests is on, defaulting to on as the draft and fossil 2.29 do (fossil 2.28 defaults it off). The client leaves its transfer unchanged on that pragma. A file or cfile whose content does not match its hash now fails the client's round, in a pull and a clone: the reply rolls back, prefix included, and no further round starts.

The leaf table is still recomputed per crosslink batch, so a parent whose untagged child arrives in a later batch loses the verdict §7.3 keeps; that case is marked as a gap, tracked in #426.

* fix(sync): continue after a uvfile content error; renumber the avoid-delta-manifests row

A uvfile whose content does not match its HASH is a handler-reported content error: warn, commit the prefix and follow ordinary continuation (sync-protocol-01 10.1). The avoid-delta-manifests client row is SP-9.5-7 now that share-links took SP-9.5-5 and SP-9.5-6. Older unreleased changelog entries drop the pending-erratum wording. check-in: 600861484f user: [email protected] tags: main, trunk

15:33
chore: ignore .agent-config at any depth; drop a stray tool trace (#429)

.gitignore anchored .agent-config/* to the repository root, so a local tool's trace written under conformance/ was committed with the suite in #264. Remove it and ignore .agent-config directories wherever they are. check-in: fd0add2110 user: [email protected] tags: main, trunk

15:25
feat(sync): add share-links mode for pragma req-links and link (#428)

* feat(sync): add share-links mode for pragma req-links and link

sync-protocol-01 Section 9.5 makes share-links mode OPTIONAL. With SyncOpts.ShareLinks a pulling session sends pragma req-links in its first request, as fossil's --share-links does, unless SyncOpts.ProjectCode names another project. It keeps each pragma link URL ARG MTIME as config link:URL = ARG, defossilized and otherwise verbatim, replacing an existing link only with a strictly newer MTIME. A wrong token count, a URL that is not HTTP(S) or an MTIME that is not a positive decimal drops the link.

Where fossil 2.28 differs the draft is followed: fossil fails fatally on a link URL its parser rejects and reads MTIME with strtoll base 0.

New sync.9.5 client cases run against fossil sync --share-links as well. SP-9.5-4 loses its scope note and is covered; SP-9.5-5 and SP-9.5-6 are new rows for which links a client keeps and when it sends req-links.

Tracked in #425.

* test(sync): cover links in later rounds and push+pull req-links; match project code case-insensitively check-in: 5473c06942 user: [email protected] tags: main, trunk

15:15
fix(sync): answer a client clone_seqno with bad command; make Clone's phantom pull opt-in (#427)

* fix(sync): answer a client clone_seqno with bad command; make Clone's phantom pull opt-in

Two deliberate #255 deviations from sync-protocol-01 move to conformance.

SP-5.2-6: the server now answers a client-sent clone_seqno with "error bad command" and processes the cards after it, as Section 5.2 requires for a reply-only card and as fossil's page_xfer does.

SP-8.2-5: Clone now sends nothing after clone_seqno 0 and its cleanup round, so by default it leaves the phantoms a clone produces in place, as fossil(1)'s clone does. The follow-up pull that fetched them is now opt-in through CloneOpts.PullPhantoms, whose doc comment says enabling it departs from Section 8.2.

Both cases leave the sync deviations map. Tracked in #424.

* fix(sync): quote a client clone_seqno as received in bad command; keep DST coverage of the opt-in pull

Tracked in #424. check-in: d3fb5397c8 user: [email protected] tags: main, trunk

14:56
test(sync): cover links in later rounds and push+pull req-links; match project code case-insensitively leaf check-in: cb003db2f4 user: [email protected] tags: trunk, feat/425-share-links
14:49
feat(sync): add share-links mode for pragma req-links and link

sync-protocol-01 Section 9.5 makes share-links mode OPTIONAL. With SyncOpts.ShareLinks a pulling session sends pragma req-links in its first request, as fossil's --share-links does, unless SyncOpts.ProjectCode names another project. It keeps each pragma link URL ARG MTIME as config link:URL = ARG, defossilized and otherwise verbatim, replacing an existing link only with a strictly newer MTIME. A wrong token count, a URL that is not HTTP(S) or an MTIME that is not a positive decimal drops the link.

Where fossil 2.28 differs the draft is followed: fossil fails fatally on a link URL its parser rejects and reads MTIME with strtoll base 0.

New sync.9.5 client cases run against fossil sync --share-links as well. SP-9.5-4 loses its scope note and is covered; SP-9.5-5 and SP-9.5-6 are new rows for which links a client keeps and when it sends req-links.

Tracked in #425. check-in: a565d1c467 user: [email protected] tags: trunk, feat/425-share-links

14:23
test(conformance): report deviations marked on repo-state API cases (#423)

rsAPICases copied each case's gap mark but never its deviation mark, so repostate.8.3.ckout-inclusive-whole-name, listed in repostateDeviations by #420, ran as an ordinary pass and the coverage report showed RS-8.3-4 as COVERED.

Copy the deviation mark too, and state that case the way the other deviation cases are written: it holds go-libfossil to the draft's answer (Section 8.3 retries "ckout." under ci, where ckout is a keyword, so it names the working files), checks fossil(1) against its own answer (the ckout tag's check-in), and is skipped as a deviation while go-libfossil follows fossil. RS-8.3-4 now reports DEVIATION until the 8.3 erratum is applied. check-in: e71b5c241f user: [email protected] tags: main, trunk

14:09
fix(sync): run each request, reply and clone round in one transaction (#422)

A received delta found wrong when its basis arrives later in the pass fails sync-protocol-01 Section 7.7's commit check, which now rolls back everything the pass stored, as fossil's page_xfer and client_sync transactions do, instead of undoing the delta by hand and keeping the rest. The phantom-fill cascades and the server's closing leaf and tag repair run inside that transaction. Any other card error still commits the prefix before it (Section 10.1); on the client that prefix now includes the reply's buffered igot phantoms and visibility changes.

db.DB.WithBoundTx binds a DB to one write transaction so code written against *DB, nested WithTx included, joins it as savepoints instead of contending for the write lock from a second connection.

SP-7.7-4 is covered; the new SP-10.1-6 has sync.10.1.integrity-error-prefix. Tracked in #418. check-in: c5f5838169 user: [email protected] tags: main, trunk

13:36
feat(resolve): checkout-inclusive request where ckout names the working files (#420)

* feat(resolve): checkout-inclusive request where ckout names the working files

Checkout.ResolveWorking is fossil's "ci+" request (repo-state-01 8.3): while the checkout has a version, "ckout" answers the working files, reported as WorkingVersion.Working rather than as a pseudo-RID. Every other name goes through the same resolver as Checkout.ResolveVersion, restricted to check-ins as fossil's ci+ is. The draft also makes ckout a keyword in a plain "ci" request; this follows fossil, where only ci+ has it.

New repostate.8.3 cases run the request against fossil test-name-to-id --type ci+, and RS-8.3-4 loses its scope note. Tracked in #419.

* fix(resolve): record the ckout retry as a fossil deviation; tighten tests check-in: 0889d8b777 user: [email protected] tags: main, trunk

12:56
fix(sync): verify a dangling delta when its basis arrives in the same pass (#417)

Tracked in #412. check-in: 056f36e0bc user: [email protected] tags: main, trunk

12:27
fix(sync): repair leaves and tags for check-ins the cascade links (#414) (#416)

* fix(sync): repair leaves and tags for check-ins the cascade links (#414)

A pulled check-in arrives as an announced phantom filled the next round, so the phantom-fill cascade links it. The session's closing sweep then found nothing left to link and skipped the leaf and tag-propagation repair, which gated on the sweep's own count: the check-in had an event row and no leaf row, and its parent stayed a leaf. The server handler had the same gap for a pushed artifact that fills a phantom.

AfterDephantomize and AfterDephantomizeBatch now return how many artifacts they linked. The sync client and the handler add that up over the session and close it with the new CrosslinkAfterCascades, which runs the repair once when the sweep or the cascades linked anything (repo-state-01 Section 7.3, RS-7.3-4), not once per file. The receive linker's cancellation paths gate on the same flag.

The repo-state harness gains a pull load: the first artifacts of a script are held and crosslinked locally, the rest pulled in process from a go-libfossil server holding them all. New cases repostate.7.3.pulled-child and repostate.7.6.pulled-retag, checked against fossil per artifact, each run as a .pull case too.

Tracked in #414.

* fix(sync): repair leaves of cascade links when a session fails (#414) check-in: 0035af8ac5 user: [email protected] tags: main, trunk

11:59
fix(manifest): link check-ins with absent files; refuse absent baselines (#415)

* fix(manifest): link check-ins with absent files; refuse absent baselines

The crosslink sweep held a check-in back until every file it names was stored. A root check-in, or one on a present parent, whose files never arrived got no event, plink, mlink, leaf or tag rows. fossil links it against phantom files (add_one_mlink, uuid_to_rid(..., 1)), and repo-state-01 Section 4.2 makes an unresolved reference a phantom, not an error. The sweep -- Crosslink, the close of every sync and clone, and verify.Rebuild -- now waits only on a delta manifest's baseline. The receive-time cascade and receive linker still wait for files while blobs are still arriving; the closing sweep bounds that wait.

verify.Rebuild linked a delta manifest whose baseline was absent, with no baseline id. fossil refuses it (fetch_baseline) and files it in orphan under a phantom for the baseline; artifact-format-01 Section 8.3 calls this a soft failure retried when the baseline arrives. Every path now does the same, so a sync requests the baseline and the phantom-fill cascade links the manifest when it lands. Rebuild clears and rederives orphan.

The gap case repostate.4.2.root-absent-file passes and is unmarked; new cases cover a present parent with an absent file and an absent or late baseline, each also through verify.Rebuild where fossil rebuild agrees.

Tracked in #406.

* fix(manifest): refuse a non-manifest baseline and drop the orphan row on link

Tracked in #406. check-in: 67fc6ced4b user: [email protected] tags: main, trunk

11:38
test(sync): mark dangling deltas whose basis arrives in the same pass (#413)

* test(sync): mark a dangling delta whose basis arrives in the same pass

SP-7.7-4 requires every artifact stored in a pass whose bytes are available in that pass to be checked against its HASH. A delta stored dangling is not rechecked when its basis arrives later in the same reply or request; fossil's commit hook catches it and rolls the round back. Add client, clone and server cases for it, marked as gaps.

Tracked in #412.

* test(sync): note how the server late-basis case must tighten when its gap closes check-in: 8f03734a23 user: [email protected] tags: main, trunk

11:14
fix(sync): verify a received delta against HASH before storing it (#410)

sync-protocol-01 Section 7.7 verifies a reconstructable non-clone file before storage, and SP-7.7-4 has every newly stored artifact whose bytes are available hashed before commit. The client and a clone stored a delta against a held basis as given, and the server checked only a file delta, so a delta that did not give HASH stayed stored under that name until something expanded it.

The check moves to storeReceived, the one choke point every receive path shares, so the client, the server (file and cfile) and a clone refuse a delta whose result is not HASH, or that does not apply. An unheld basis still leaves the delta stored dangling.

Tracked in #405. check-in: b3914d95b3 user: [email protected] tags: main, trunk

11:14
feat(repo): name the current trunk and a branch's open leaf (#411)

* feat(repo): name the current trunk and a branch's open leaf

Repo.CurrentTrunk resolves the main-branch setting's name the way ResolveVersion does, as fossil does for update outside a checkout and open with no version (repo-state-01 Section 9). Repo.BranchOpenLeaf names the open leaf of a branch with the greatest mtime, or reports the branch not open; fossil's branch info takes whichever open leaf its query meets first, and this follows the draft. checkout.BranchLeaves and the new checkout.BranchOpenLeaf share one open-leaf query.

RS-9-1 and RS-9-4 lose their scope notes and gain cases.

* fix(repo): resolve the current trunk as a check-in, reject an empty branch name

Tracked in the stacked work on repo-state-01 Section 9. check-in: c2795c4f48 user: [email protected] tags: main, trunk

11:05
feat(resolve): resolve checkout-relative names and branch-type requests (#409)

* feat(resolve): resolve checkout-relative names and branch-type requests

Checkout.ResolveVersion resolves current, prev/previous and next relative to the open checkout, after tip and before the other forms, as fossil's symbolic_name_to_rid does; a keyword that names nothing falls through. Repo.ResolveBranchStart is the branch-type request: it resolves a name and walks back to the first check-in of its branch. Section 8.3 walks back from every result; fossil only from tag:NAME and plain names, and this follows the draft.

The repostate.8.3 checkout and branch-type cases run against the new entry points, with new cases for a keyword shadowing a tag, prev at a root, an untyped ckout, root:current and a branch-type hash. Tracked in #386.

* fix(resolve): match check-ins only for branch-type requests, merge via checkout

A branch-type request is rewritten to a check-in request (repo-state-01 Section 8.3), so a technote tagged with the branch name cannot answer it. A checkout with no recorded version resolves the ordinary forms, and merge resolves its version through the open checkout. Tracked in #386.

* fix(resolve): wrap a long test line check-in: cba2d0c823 user: [email protected] tags: main, trunk

10:59
feat(repo): set the hash policy by name (#408)

artifact-format-01 7.1 (AF-7.1-2) matches policy value strings case-sensitively and exactly and makes an unrecognized value fatal. No surface took a value string, so the row stayed partial.

Repo.SetHashPolicy takes sha1, auto, sha3, sha3-only or shun-sha1, as fossil's hash-policy command does with fossil_strcmp, stores the ordinal, and refuses any other string without touching the stored policy. Auto in a repository that already holds a SHA3 artifact stores sha3 (7.3).

New conformance cases drive every name, wrong-case names, unknown names and the empty name through it, and the AF-7.1-2 scope note is dropped. check-in: feea6a1614 user: [email protected] tags: main, trunk

10:52
fix(manifest): link a check-in atop an absent parent despite absent files (#407)

* fix(manifest): link a check-in atop an absent parent despite absent files

The crosslink deferral held back a check-in until every F-card blob was stored. When the primary parent's manifest is itself absent, no mlink row depends on those files (fossil's add_mlink returns before reading one, and the parent's crosslink derives the transition once it arrives), so the wait could never complete for files the repository will not receive. The libfossil repository holds one such check-in, a fossil-scm commit imported without its history; the sweep lost its event and plink rows that fossil rebuild writes (RS-4.2-2).

missingCheckinRefs now skips the F-cards when the primary parent is unavailable; the baseline is still required. Adds conformance case repostate.4.2.phantom-parent-absent-file and a unit test that also checks the child's mlink is derived once the parent arrives.

Tracked in #398.

* fix(manifest): record the remaining crosslink deferral gaps

Adds gap case repostate.4.2.root-absent-file, a receive-linker ordering test for the child-before-parent path, and notes the narrowed exemption. Tracked in #398 and #406. check-in: 15762adeb6 user: [email protected] tags: main, trunk