Skip to content
go-libfossil Timeline
Login

Timeline

50 descendants of 6651024b58887913

2026-10-20
00:25
test(manifest,verify): unit tests for commit and verify over a sparse store check-in: c935561cfc user: [email protected] tags: feat/submanifest-reader, main, trunk
00:25
test(conformance): zit checks the sparse store

zit clones go-libfossil's flat history through a cone, and both sides must report the same number of elided phantoms over the same cone. Each side then commits over its sparse store and pushes to a dense store of the other. The commit carries no R card, and the receiver holds the whole check-in. check-in: 0a63c3b22f user: [email protected] tags: feat/submanifest-reader, main, trunk

00:25
test(conformance): one sparse-store fixture for every origin check-in: a76ce676f6 user: [email protected] tags: feat/submanifest-reader, main, trunk
00:25
test(conformance): cover the sparse store's step-3 requirements

Cases elide out-of-cone blobs from a dense clone, as a cone-scoped clone would leave the store. They check the three absence classes, the client and server sync filters, recomputation on a cone change, loss of the cone (unreadable, or dropped by fossil rebuild, after which fossil's pull heals the store), verify and rebuild counts, R-card omission and skipping, a commit over elided subtrees pushed to a dense peer, widening, hybrid histories, and delta bases.

Holding out-of-cone sub-manifest nodes is recorded as a deviation from §5.1. zit holds them too, because a tree that cannot be enumerated never links.

A checkout's record names the phantom for a file that neither cone covers, so a checkout opens over a sparse store. check-in: b907b41650 user: [email protected] tags: feat/submanifest-reader, main, trunk

00:25
feat(sync): never request a sparse store's elided phantoms

The client's phantom load and the server's request_phantoms skip elided phantoms (draft-fossil-sparse-cone-00 §5.2). A dense store classifies nothing and behaves as before. Repo.StoreCone and Repo.SetStoreCone expose the store cone. check-in: 37f15485b4 user: [email protected] tags: feat/submanifest-reader, main, trunk

00:25
feat(manifest,verify): commit over a sparse store, and count absences

A commit over a store with a store cone leaves out the R card (draft-fossil-sparse-cone-00 §4.3). It refers to out-of-cone files the store lacks by hash alone (§5.3). VerifyRCard skips over a sparse store, and skips a manifest that has no R card, since an absent R card is not damage.

verify.Report gains Phantoms (transit) and Elided. Neither is an Issue, so a store complete within its cone verifies OK (§5.2). Rebuild keeps the store cone and reports the same counts. check-in: cd98ba38cb user: [email protected] tags: feat/submanifest-reader, main, trunk

00:25
feat(content): store cone and the three absence classes of the sparse store

The store cone (draft-fossil-sparse-cone-00 §5) is kept in a storecone table that exists only while a cone is set. fossil rebuild drops tables it does not know, so losing the cone reads as dense and the store heals toward dense (§5.2). A cone that does not parse also reads as dense.

LoadAbsences sorts every phantom into transit, shunned or elided by zit's rules. A phantom is elided when F cards name it only outside the store cone and no held delta uses it as a base. check-in: 524c749185 user: [email protected] tags: feat/submanifest-reader, main, trunk

2026-10-19
23:58
Merge branch 'feat/submanifest-pragma' into feat/submanifest-reader check-in: 6681b95432 user: [email protected] tags: feat/submanifest-reader, main, trunk
23:53
test(conformance): skip zit tests on a zit that predates send-submanifests

A zit older than check-in 0431958ff4 gates trees on the announced version, so against it the interop tests fail on the protocol change rather than on anything go-libfossil does. zitBinary now probes the binary for the pragma's name, which a zit that sends it carries; zit's version cannot tell, since 0.5.0 was tagged before the change. An older zit is skipped with its path, version and the check-in needed, or fails the run under REQUIRE_ZIT_BIN=1 as a missing one does.

Tracked in #452. check-in: b9c7364ff2 user: [email protected] tags: feat/submanifest-reader, main, trunk

23:44
Merge branch 'fix/update-cone-symlink' into feat/submanifest-reader check-in: 44ac676efe user: [email protected] tags: feat/submanifest-reader, main, trunk
23:12
vfile: assert a Disk is made, and test one on a storage without links check-in: 6eb99ff380 user: [email protected] tags: feat/submanifest-reader, main, trunk
23:10
test(stash): fossil pops go's symlink stash and go pops fossil's check-in: 805385f535 user: [email protected] tags: feat/submanifest-reader, main, trunk
23:09
test: fossil reads go's symlink undo state and go reads fossil's; RestoreFiles keeps links check-in: 03f0b0c67b user: [email protected] tags: feat/submanifest-reader, main, trunk
23:06
fix(stash): stash, revert and apply symlinks as fossil's stash does

Save reads each changed file through vfile.Disk, so a symlink is stashed as its target's name and recorded with file_islink, and its revert makes it a link to the committed target. Apply writes a stashed symlink as a symlink and deletes a link before writing, so neither writes through one. check-in: 5be36b41a0 user: [email protected] tags: feat/submanifest-reader, main, trunk

23:02
fix(checkout): revert a symlink as fossil's revert does

restoreCommitted writes through vfile.Disk with the row's islink, so a repointed link is made a link to its committed target again instead of having that name written into the file it points to. check-in: 6a440bc42f user: [email protected] tags: feat/submanifest-reader, main, trunk

22:58
fix(undo): save and restore symlinks as fossil's undo does

Move checkout's link-aware diskView into vfile.Disk, so checkout, undo and stash share one RepoFILE view: Stat, Read, Write (which deletes a link before writing, makes a symlink when allow-symlinks is on, creates the directory and sets the executable bit as file_setexe does), SetExe, MTime and Remove. The allow-symlinks setting is read by vfile.OpenDisk.

undo.Save, Undo, Redo, Swap, ReadFile and RestoreFiles now take a Disk: a symlink is read as its target's name and recorded with isLink, and is deleted and made a symlink again on restore, as undo_save and undo_one do, so Undo of an Update no longer writes through a link. check-in: 858c20561f user: [email protected] tags: feat/submanifest-reader, main, trunk

22:55
fix(manifest): warn with zit's §8.1 flag-day rule; pin the dated -00 revision

zit retired the sub-manifest draft's provisional phase the same day as the send-submanifests errata (erratum submanifests-00-s8.2-provisional-phase- retired): §8.2 is gone, and its one permanent rule, that the setting must not be enabled on a repository a non-reading peer serves, moves to §8.1. zit's enable warning now states that rule in place of the disposable- fixture text, so go-libfossil's, worded as zit's, does too.

The conformance suite pins the draft at zit check-in bbc6794bf0, the revision dated 19 October 2026 whose Appendix C lists the nine errata it applies; the Appendix A vectors are unchanged.

Tracked in #452. check-in: efba058666 user: [email protected] tags: feat/submanifest-reader, main, trunk

22:50
test: undo, revert and stash of a repointed symlink (red) check-in: 5a08dc00df user: [email protected] tags: feat/submanifest-reader, main, trunk
22:49
test(checkout): pin revert of renames against fossil's revert and undo

An add at a rename's old name ends as fossil's revert leaves it, by every name the revert can be given, and Undo restores what fossil undo does. A three-file rotation and a chain reverted by its middle name end under their committed names; reverting only a chain's second rename keeps the first one pending.

Tracked in #248. check-in: 4bec3ce730 user: [email protected] tags: feat/submanifest-reader, main, trunk

22:48
test(checkout): a renamed symlink is not merged, and the rename drops the old name

Covers the rename and dry-run paths of Update's symlink conflict: the link is listed in Unmerged, nothing is written through it, and only a real run deletes the old name, as fossil's update does. check-in: ef49615d6c user: [email protected] tags: feat/submanifest-reader, main, trunk

21:50
fix(sync): gate sub-manifest trees on the send-submanifests pragma

draft-fossil-submanifests-00 §7.2 no longer gates S-bearing artifacts on the peer's announced version: fossil 2.29 announces 22900 and reads no tree. A peer that reads trees now says so with pragma send-submanifests, which go-libfossil sends in every request right after client-version and in every reply, clone replies included, right after server-version, whatever the sub-manifest settings. The version threshold and the 22900 reader marker are gone; client-version and server-version announce 22800, the fossil release whose protocol this library speaks.

A tree manifest or sub-manifest is refused to a peer that has not sent the pragma with "Peer does not accept sub-manifests.", never converted or omitted. A server decides from the whole request it answers, a client from the replies it has received in the exchange. avoid-submanifests moves from the ci-lock answer into the same leading run of every reply.

Enabling emission over a stored submanifest-k outside 1 to 12 without an explicit k is refused, naming the stored value (§8.1).

The conformance suite pins the draft with the 2026-10-19 errata applied: SM-7.2-1 and SM-6.3-3 are met rather than deviations, SM-7.2-2, SM-7.2-3, SM-6.3-1/2/7 and SM-8.1-3 follow the corrected text, and SM-7.2-4 covers the pragma's placement. The zit interop pushes a tree go-libfossil wrote to zit and checks both sides refuse trees when the pragma is stripped.

Tracked in #452. check-in: 05a53c393d user: [email protected] tags: feat/submanifest-reader, main, trunk

20:09
fix(checkout): revert renames onto taken names, saving undo first

Checkout.Revert refused to undo a rename when another file held the old name: a swap, a chain, a new add or an untracked file there. Like fossil's revert it now saves each file it writes or deletes for undo, then reverts in one transaction, so Undo or fossil undo brings back what it overwrote, and a failed revert puts the files back.

Undoing a rename takes back the old name from whatever row holds it: a row renamed onto it is reverted to its own old name, and any other row is dropped, as fossil's UPDATE OR REPLACE drops it. Every committed file ends under its committed name; fossil's own revert leaves a swap renamed and stops tracking the second file of a chain.

Tracked in #248. check-in: 80764da743 user: [email protected] tags: feat/submanifest-reader, main, trunk

18:49
fix(checkout): Update decides the cone before renames, and never merges symlinks

A file outside a sparse checkout's cone is never on disk, so it read as missing, hence changed, and followed the target's rename; any upstream rename outside the cone then refused the update. It is now classified before renames are followed and matched by name: a rename outside the cone moves only the record, one into the cone writes the file under its new name, and an unedited file renamed out of it leaves the disk.

A symlink edited locally and changed by the target was merged through the link, writing conflict markers into the file it points at. As fossil's update does, it is now a conflict with nothing written, listed in UpdateResult.Unmerged; a rename still removes the old name. check-in: f373c9a8ae user: [email protected] tags: feat/submanifest-reader, main, trunk

18:34
fix(checkout): materialize a symlink entering the cone as a symlink

The cones merge called extractSingleFile without the islink argument the symlink fix added, so it did not build. SetCone now passes the row's islink, and a file entering the cone is written as Extract writes it: a symlink with allow-symlinks on. check-in: 36fccc1f87 user: [email protected] tags: feat/submanifest-reader, main, trunk

18:29
Merge branch 'feat/cones' into feat/submanifest-reader check-in: 1a17a3defe user: [email protected] tags: feat/submanifest-reader, main, trunk
18:29
Merge branch 'fix/scan-symlink-extract' into feat/submanifest-reader

# Conflicts: # internal/checkout/update.go check-in: 6708292b55 user: [email protected] tags: feat/submanifest-reader, main, trunk

18:27
Merge branch 'fix/receipt-followups' into feat/submanifest-reader check-in: 41ff5d315a user: [email protected] tags: feat/submanifest-reader, main, trunk
18:27
Merge branch 'fix/stash-undo-followups' into feat/submanifest-reader check-in: 22101b521f user: [email protected] tags: feat/submanifest-reader, main, trunk
18:27
fix(checkout): write symlink entries as fossil does, so a fresh checkout extracts

Since the scan began recording islink and chnged 7/9, Create followed by Extract without Force failed on any repository with an "l" file: the file was missing, the scan read it as UNLINK, and the missing-file skip only covered plain edits.

Extract and Update now write a symlink entry as fossil's vfile_to_disk does: as a symlink to the blob content while allow-symlinks is on and the storage can make links, otherwise as a plain file holding the target. A symlink is deleted before a file is written over it, and setMergedMode leaves symlinks and directories alone, as file_setexe does. Extract's missing-file skip covers mode changes too, so the first Extract after Create plays fossil's open whatever the entry.

With allow-symlinks off, fossil itself reports such a file UNLINK and its checkout refuses without --force; Extract keeps that behavior, and an interop test pins it against fossil's open in both modes.

ScanENotFile no longer refuses a directory at a pending add or removal recorded with chnged=0, matching the else-if in vfile_check_signature.

Tracked in #449 check-in: 8cad365e82 user: [email protected] tags: feat/submanifest-reader, main, trunk

16:51
Merge branch 'feat/submanifest-reader' into feat/cones

Update now follows the target's renames and saves undo state. A file outside the cone stays a record-only step: never written, chmodded, backed up or read for undo. A local edit that a rename would carry out of the cone is refused, naming the cone. check-in: 74aa290eda user: [email protected] tags: feat/submanifest-reader, main, trunk

16:29
Merge branch 'feat/submanifest-reader' into fix/stash-undo-followups

# Conflicts: # internal/undo/undo.go check-in: d6ac19e580 user: [email protected] tags: feat/submanifest-reader, main, trunk

16:26
fix(stash,undo): scan before stashing; return undo changes, print nothing

Stash save now scans the checkout first, as fossil's stash_create does (vfile_check_signature), so an edit no scan had recorded is stashed too. Save takes the scanner, a *checkout.Checkout, as its first argument.

Undo and redo no longer print to standard output: they return the files they changed, as []undo.Change, in the undo table's row order, the order fossil undoes them in.

Tracked in #448 check-in: 2dfae63b63 user: [email protected] tags: feat/submanifest-reader, main, trunk

16:25
Merge branch 'fix/update-undo' into feat/submanifest-reader check-in: da7c8a19cd user: [email protected] tags: feat/submanifest-reader, main, trunk
16:10
fix(checkout): save undo state in Update, as fossil does

Update saved no undo state, so nothing could reverse it. It now reads the file of every step that writes or removes one before writing, as fossil's update calls undo_save, and saves those files with copies of vfile and vmerge and the checked-out version in the same transaction that moves the checkout to the target. If a write fails partway the files are put back, as fossil's undo_rollback does.

Checkout.Undo and Checkout.Redo (internal and public) swap that state back and forth and keep checkout-hash naming the restored version. The undo package gains ReadFile, SaveTx and RestoreFiles, and its undo table now has fossil's schema (isExe, unique pathname, rowid order, the executable bit read from disk), so fossil undo reverses a go-libfossil update and Checkout.Undo reverses fossil update; fossil 2.28 interop tests check both. Under js/wasm, which has no undo package, Update saves nothing.

Tracked in #446 check-in: 294a537880 user: [email protected] tags: feat/submanifest-reader, main, trunk

15:59
Merge branch 'fix/update-renames' into feat/submanifest-reader

# Conflicts: # CHANGELOG.md check-in: 5d0a52d706 user: [email protected] tags: feat/submanifest-reader, main, trunk

15:45
docs(manifest): CheckinOpts.User is the U card, fossil's --user-override

It is never checked against the user table; the check-in's rcvfrom row credits that login's uid when the table holds it and the local setup user otherwise, as fossil credits g.userUid whatever the U card says. A test pins that an unknown name commits under that name. check-in: 54c9e56786 user: [email protected] tags: feat/submanifest-reader, main, trunk

14:52
fix(db): forget a receipt's row when its transaction rolls back

Receipt.ID took (rcvid, mtime) to identify its own row and checked it with a SELECT on every use. After a rollback the rcvid can be reused by another receipt's insert, and under a frozen clock the mtime matches too, so the receipt attached to the wrong row.

Fossil holds g.rcvid for its process and never re-reads the row (content_rcvid_init); a rollback ends the process with it. A Receipt outlives transactions, so the transaction or savepoint that makes its row now records that, forgets the id if it rolls back, and hands it to the enclosing level when released. A kept id costs no query, which takes one SELECT per stored blob off the clone path.

Also checks that a tree check-in's sub-manifests share the commit's receipt. check-in: 0269bd9461 user: [email protected] tags: feat/submanifest-reader, main, trunk

14:41
Merge branch 'feat/submanifest-reader' into feat/cones

Update's rewrite meets the sparse worktree: a file outside the cone is a record-only step, counted in OutOfCone, and never planned, scanned, checked, written, backed up as NAME-original or chmodded; reloading vfile moves its record to the target. SetCone records the mtime of each file it materializes, as Extract now does. check-in: 47f89f0798 user: [email protected] tags: feat/submanifest-reader, main, trunk

14:40
docs: state where text Julian times are checked and how sweep errors read

Only macOS arm64 and linux-x64 fossil have been compared bit for bit, so the rebuild test no longer claims Windows is exact. julian.go says which long doubles fall back to 53 bits wrongly, and ExpandAll's doc says its errors match Cache.Expand's in kind, not always in wording. check-in: e4c84f20f9 user: [email protected] tags: feat/submanifest-reader, main, trunk

14:38
test(fsltype): check macOS fossil's event times at its own long double

TestTextJulianDayMatchesFossil compared macOS arm64 fossil's stored values with the text form at the running platform's long double, so it failed on linux-x64, where fossil itself stores different last digits. TestTextJulianDayPerLongDouble already checks those values at 53 bits and linux-x64 fossil's at 64, so the platform-blind test goes. check-in: e499428d3b user: [email protected] tags: feat/submanifest-reader, main, trunk

12:56
fix(verify): count a tree gap found in the one-pass check-in sweep

checkCheckins now gathers into a staging report and copied only its issues back, so the MissingRefs count treeGap adds was lost: Verify reported a missing sub-manifest as an issue but counted zero missing references. check-in: 39b524c37c user: [email protected] tags: feat/submanifest-reader, main, trunk

12:47
fix(verify): give treeGap a cache after the one-pass blob walk

The rebuild speed-up hands checkOneCheckin each check-in's expanded bytes and drops the pass-wide expansion cache. treeGap, from the sub-manifest reader, still lists a check-in's files to find a missing sub-manifest, and it needs a cache: without one every delta manifest re-expands its baseline. checkCheckins now keeps a small cache for those manifest reads only. check-in: 1a45812566 user: [email protected] tags: feat/submanifest-reader, main, trunk

12:47
Merge branch 'perf/rebuild-blob-check' into feat/submanifest-reader

# Conflicts: # CHANGELOG.md check-in: e3c81fb936 user: [email protected] tags: feat/submanifest-reader, main, trunk

12:47
Merge branch 'fix/stash-undo-storage' into feat/submanifest-reader

# Conflicts: # CHANGELOG.md # internal/checkout/vfile.go check-in: 189088f46c user: [email protected] tags: feat/submanifest-reader, main, trunk

12:46
Merge branch 'fix/merge3-markers' into feat/submanifest-reader

# Conflicts: # CHANGELOG.md check-in: 2a0701c7d3 user: [email protected] tags: feat/submanifest-reader, main, trunk

12:46
Merge branch 'fix/tag-events' into feat/submanifest-reader check-in: e9e08cbb58 user: [email protected] tags: feat/submanifest-reader, main, trunk
02:08
Merge branch 'fix/private-blob-public-checkin' into feat/submanifest-reader check-in: 52ca05c6c4 user: [email protected] tags: feat/submanifest-reader, main, trunk
02:08
fix(manifest): make every file blob a public check-in names public

A public check-in could reuse content first stored privately, say by syncing a private branch, and leave it in the private table. Sync never sends private blobs to a peer without private access, so that peer got a check-in whose file stayed a phantom and could not be checked out.

storeFileBlobs now calls content.MakePublic on each file blob inside the check-in's transaction, as fossil's commit calls content_make_public for each F card (checkin.c). The blob is already queued in unsent, so the next push carries it. The sub-manifest writer already does this for trees.

Tracked in #439. check-in: 6d239246d0 user: [email protected] tags: feat/submanifest-reader, main, trunk

02:00
Merge branch 'fix/scan-missing-perms' into feat/submanifest-reader check-in: ef787892fe user: [email protected] tags: feat/submanifest-reader, main, trunk
02:00
Merge branch 'fix/tag-events' into feat/submanifest-reader

# Conflicts: # CHANGELOG.md check-in: 2e1d1e6fb7 user: [email protected] tags: feat/submanifest-reader, main, trunk

02:00
Merge branch 'fix/rcvfrom-receipts' into feat/submanifest-reader

# Conflicts: # CHANGELOG.md # internal/manifest/manifest.go # internal/sync/handler.go check-in: 6651024b58 user: [email protected] tags: feat/submanifest-reader, main, trunk