Artifact da8c6f14d5f318287fd9c9dcb6bdc84bd83905cc24e4bf882c7f1014a142a182:
- File
repo_submanifest_test.go
— part of check-in
[14f17e675e]
at
2026-10-18 16:44:14
on branch feat/submanifest-reader
— feat(manifest): write tree check-ins behind enable-submanifests
Checkin now honours draft-fossil-submanifests-00 §8.1: with enable-submanifests on and a pinned submanifest-k it stores the canonical tree first, marks each sub-manifest unsent, records the seen-submanifest indicator that arms the §7.2 gate, and writes a manifest of S cards with no F card and never a B card. The setting is off by default, so every commit is byte-identical to before. A stored k outside 1..12 falls back to a flat manifest and logs it (§6.3); unchanged sub-manifests are shared by content addressing.
EnableSubmanifests is §8.1's local request: a valid pin wins and a different explicit k is refused as a re-tune; with no valid pin an explicit k is pinned, or §6.3's selection runs over the current check-in; a request that cannot be met changes neither setting. RetuneSubmanifests is the manual §6.4 re-tune. After a tree commit the §6.4 gate re-pins k while submanifest-auto-retune is on, and only advises otherwise.
A sync run reports avoid-submanifests in SyncResult, and CheckinOpts.AvoidSubmanifests keeps a commit made in that sync flat (§7.2). The settings' names and parsers move to internal/manifest, which sync now uses. Repo.EnableSubmanifests and Repo.RetuneSubmanifests expose the two requests, the first returning the operator warning. A test shows fossil 2.28 never receives a tree this writer made. (user: [email protected], size: 1775) [annotate] [blame] [check-ins using]
package libfossil import ( "path/filepath" "strings" "testing" "time" fsltype "github.com/danmestas/go-libfossil/internal/fsltype" "github.com/danmestas/go-libfossil/internal/manifest" _ "github.com/danmestas/go-libfossil/internal/testdriver" ) // EnableSubmanifests pins k, turns emission on and hands back the operator // warning; later commits are trees, and RetuneSubmanifests moves the pin. func TestEnableSubmanifestsWritesTrees(t *testing.T) { r, err := Create(filepath.Join(t.TempDir(), "t.fossil"), CreateOpts{User: "u"}) if err != nil { t.Fatal(err) } defer r.Close() files := []FileToCommit{ {Name: "README.md", Content: []byte("# Example\n")}, {Name: "src/main.c", Content: []byte("int main(void){return 0;}\n")}, {Name: "src/node11.c", Content: []byte("/* node11 */\n")}, {Name: "src/util.c", Content: []byte("/* util */\n")}, } at := time.Date(2026, 7, 26, 0, 0, 0, 0, time.UTC) first, _, err := r.Commit(CommitOpts{Files: files, Comment: "flat", User: "u", Time: at}) if err != nil { t.Fatal(err) } if _, _, err := r.EnableSubmanifests(first, 13); err == nil { t.Fatal("k 13 accepted") } k, warning, err := r.EnableSubmanifests(first, 0) if err != nil || k != 1 || !strings.Contains(warning, "Fossil 2.29") { t.Fatalf("EnableSubmanifests = %d, %q, %v", k, warning, err) } if err := r.RetuneSubmanifests(3); err != nil { t.Fatal(err) } second, _, err := r.Commit(CommitOpts{Files: files[:1], Comment: "tree", User: "u", Time: at.Add(time.Hour), ParentID: first}) if err != nil { t.Fatal(err) } d, err := manifest.GetManifest(r.Inner(), fsltype.FslID(second)) if err != nil { t.Fatal(err) } if len(d.S) != 2 || len(d.F) != 0 { t.Fatalf("second commit: %d S cards, %d F cards", len(d.S), len(d.F)) } }