Artifact 5ca02448f2f7def4020911272c26c759e9897b14161149a2dc75ba66dbefcbcc:
- File
checkout_rcard_test.go
— part of check-in
[318f46de9e]
at
2026-10-21 11:48:51
on branch feat/submanifest-reader
— feat(checkout): verify a present R card on extract, as fossil's checkout
Extract now runs fossil's repo-cksum check after materializing: a present R card is compared with the aggregate over every file the manifest names, read from the store, so a sparse checkout over a dense store reaches the same verdict as a dense one, and a sparse store skips the check. Like fossil, a disagreement is a warning delivered through ExtractOpts.Warn and never fails the extract; repo-cksum off disables it. The conformance case builds its repository with fossil and checks fossil warns exactly where go-libfossil does. Clears the SC-4.3-4 scope note. (user: [email protected], size: 2271) [annotate] [blame] [check-ins using] [more...]
package libfossil import ( "path/filepath" "strings" "testing" "time" "github.com/danmestas/go-libfossil/db" "github.com/danmestas/go-libfossil/internal/blob" "github.com/danmestas/go-libfossil/internal/fsltype" "github.com/danmestas/go-libfossil/internal/manifest" ) // badRCardChild commits two files and stores a child naming the same files // under a wrong R card, as fossil's test-content-put would. func badRCardChild(t *testing.T) (*Repo, int64) { t.Helper() r, err := Create(filepath.Join(t.TempDir(), "r.fossil"), CreateOpts{User: "u"}) if err != nil { t.Fatal(err) } t.Cleanup(func() { r.Close() }) parent, _, err := r.Commit(CommitOpts{User: "u", Comment: "good", Files: []FileToCommit{ {Name: "src/a.c", Content: []byte("a\n")}, {Name: "tools/t.c", Content: []byte("t\n")}, }}) if err != nil { t.Fatal(err) } d, err := manifest.GetManifest(r.inner, fsltype.FslID(parent)) if err != nil { t.Fatal(err) } parentUUID, err := r.inner.UUIDByRID(parent) if err != nil { t.Fatal(err) } d.C, d.R, d.D, d.P, d.Z = "bad", strings.Repeat("0", 32), d.D.Add(time.Hour), []string{parentUUID}, "" data, err := d.Marshal() if err != nil { t.Fatal(err) } var rid fsltype.FslID if err := r.inner.WithTx(func(tx *db.Tx) error { rid, _, err = blob.Store(tx, data) return err }); err != nil { t.Fatal(err) } if _, err := manifest.Crosslink(r.inner); err != nil { t.Fatal(err) } return r, int64(rid) } func TestExtractWarnsOnBadRCard(t *testing.T) { for _, setting := range []string{"", "off"} { r, bad := badRCardChild(t) if setting != "" { if err := r.SetConfig("repo-cksum", setting); err != nil { t.Fatal(err) } } narrow, err := NewCone([]string{"src"}, nil) if err != nil { t.Fatal(err) } co, err := r.CreateCheckout(t.TempDir(), CheckoutCreateOpts{Cone: narrow}) if err != nil { t.Fatal(err) } var warned []string err = co.Extract(bad, ExtractOpts{Warn: func(m string) { warned = append(warned, m) }}) co.Close() if err != nil { t.Fatalf("repo-cksum=%q: extract of a bad R card failed: %v", setting, err) } want := 1 if setting == "off" { want = 0 } if len(warned) != want { t.Fatalf("repo-cksum=%q: warnings %q, want %d", setting, warned, want) } } }