Artifact 9e51477a57c121884912d8fbadd6bc469b246735fc745ef460e2dc4d5925a798:
- File
internal/checkout/fork_test.go
— part of check-in
[7ea6fba63f]
at
2026-10-06 15:57:25
on branch trunk
— fix(checkout): merge the way fossil does, and commit merges with their parent (#244) (#252)
The CLI's merge marked a conflict with vfile.chnged=5, which fossil reads as "added by integrate", and recorded no merge-in version or vmerge row, so a merge went unseen and the next commit dropped the merge parent.
Merging now lives in the library as Checkout.Merge and records what fossil records: chnged=2 and mrid for a file taken from the merged-in version, chnged=3 for an added file, a per-file vmerge row for a merged file, and vmerge id 0 for the merge. Conflicts use fossil's markers and are found by looking for them (Checkout.Conflicts), so fossil and go-libfossil read each other's merges. Where fossil relies on its undo copy, Merge keeps the file or refuses instead.
Commit reads vmerge for merge parents, and, as fossil's commit does, refuses unresolved conflict markers, empty commits, unknown names and partial commits of a merge. The CLI's merge, conflicts, mark-resolved and ci commands call the library; ci now commits the checkout. (user: [email protected], size: 2962) [annotate] [blame] [check-ins using]
package checkout import ( "testing" _ "github.com/danmestas/go-libfossil/internal/testdriver" ) func TestBranchLeaves_SingleLeaf(t *testing.T) { r, cleanup := newTestRepoWithCheckin(t) defer cleanup() leaves, err := BranchLeaves(r, "trunk") if err != nil { t.Fatalf("BranchLeaves: %v", err) } if len(leaves) != 1 { t.Fatalf("got %d leaves, want 1", len(leaves)) } } func TestBranchLeaves_Empty(t *testing.T) { r, cleanup := newTestRepoWithCheckin(t) defer cleanup() leaves, err := BranchLeaves(r, "nonexistent-branch") if err != nil { t.Fatalf("BranchLeaves: %v", err) } if len(leaves) != 0 { t.Fatalf("got %d leaves, want 0", len(leaves)) } } func TestWouldFork_SingleLeaf(t *testing.T) { r, cleanup := newTestRepoWithCheckin(t) defer cleanup() dir := t.TempDir() co, err := Create(r, dir, CreateOpts{}) if err != nil { t.Fatalf("Create: %v", err) } defer co.Close() forked, err := co.WouldFork() if err != nil { t.Fatalf("WouldFork: %v", err) } if forked { t.Fatal("WouldFork = true, want false (single leaf)") } } func TestWouldFork_TrunkNoSymTag(t *testing.T) { r, cleanup := newTestRepoWithCheckin(t) defer cleanup() dir := t.TempDir() co, err := Create(r, dir, CreateOpts{}) if err != nil { t.Fatalf("Create: %v", err) } defer co.Close() rid1, _, _ := co.Version() if err := co.Extract(rid1, ExtractOpts{}); err != nil { t.Fatalf("Extract: %v", err) } co.env.Storage.WriteFile(co.dir+"/fork.txt", []byte("fork"), 0644) _, _, err = co.Commit(CommitOpts{Message: "second commit", User: "test", AllowEmpty: true}) if err != nil { t.Fatalf("Commit: %v", err) } // Manually re-insert the original commit as a leaf to simulate a fork. _, err = r.DB().Exec("INSERT OR IGNORE INTO leaf(rid) VALUES(?)", int64(rid1)) if err != nil { t.Fatalf("insert leaf: %v", err) } forked, err := co.WouldFork() if err != nil { t.Fatalf("WouldFork: %v", err) } if !forked { t.Fatal("WouldFork = false, want true (trunk fork without sym-trunk tag)") } } func TestWouldFork_DifferentBranch(t *testing.T) { r, cleanup := newTestRepoWithCheckin(t) defer cleanup() dir := t.TempDir() co, err := Create(r, dir, CreateOpts{}) if err != nil { t.Fatalf("Create: %v", err) } defer co.Close() rid1, _, _ := co.Version() if err := co.Extract(rid1, ExtractOpts{}); err != nil { t.Fatalf("Extract: %v", err) } co.env.Storage.WriteFile(co.dir+"/b.txt", []byte("branch"), 0644) _, _, err = co.Commit(CommitOpts{ Message: "branch commit", User: "test", Branch: "feature-x", AllowEmpty: true, }) if err != nil { t.Fatalf("Commit: %v", err) } _, err = r.DB().Exec("INSERT OR IGNORE INTO leaf(rid) VALUES(?)", int64(rid1)) if err != nil { t.Fatalf("insert leaf: %v", err) } forked, err := co.WouldFork() if err != nil { t.Fatalf("WouldFork: %v", err) } if forked { t.Fatal("WouldFork = true, want false (other leaf is on different branch)") } }