Artifact 8702f12f3701dc192a7b19133e7f6fcbcbc41ee4833a5eb78b8d27f6e2abe05d:
- File
hub/commit_tags_test.go
— part of check-in
[7536beb856]
at
2026-05-06 20:40:32
on branch trunk
— feat(hub): CommitOpts.Tags — attach tags at commit time (incl. branch=) (#148)
Plumbs libfossil's `Tags []TagSpec` primitive through `hub.CommitOpts` so callers can land a checkin on a non-current branch (or attach any other tag) without going around the EdgeSync API to libfossil.
Fossil branches are propagating tags: `branch=<name>` + `sym-<name>=*` together place a checkin on a branch. Exposing `Tags` rather than a git-flavored `Branch string` keeps the API fossil-native and is strictly more expressive — any tag (closed, release, custom) can be attached at commit time, not just branch creators.
Empty `Tags` preserves the existing trunk-default behavior; current callsites compile and run unchanged.
Closes #147 (user: [email protected], size: 4084) [annotate] [blame] [check-ins using]
package hub import ( "context" "testing" _ "github.com/danmestas/libfossil/db/driver/modernc" ) // TestCommit_BranchTags_LandsOnNamedBranch verifies that supplying the fossil // branch tag pair (branch=<name> + sym-<name>=*) on CommitOpts.Tags lands the // checkin on that branch. After the commit, BranchTip(name) resolves to the // new commit and trunk's tip is unchanged. func TestCommit_BranchTags_LandsOnNamedBranch(t *testing.T) { h := newTestHub(t) ctx := context.Background() trunkRev, err := h.Commit(ctx, CommitOpts{ Files: []FileToCommit{{Name: "seed.txt", Content: []byte("seed\n")}}, Message: "seed trunk", Author: "hub", }) if err != nil { t.Fatalf("seed Commit: %v", err) } r := h.Repo().handle trunkTipBefore, err := r.BranchTip("trunk") if err != nil { t.Fatalf("BranchTip(trunk) before: %v", err) } const branch = "feature/x" branchRev, err := h.Commit(ctx, CommitOpts{ Files: []FileToCommit{{Name: "branch.txt", Content: []byte("on branch\n")}}, Message: "first commit on " + branch, Author: "hub", Tags: []TagSpec{ {Name: "branch", Value: branch}, {Name: "sym-" + branch, Value: "*"}, }, }) if err != nil { t.Fatalf("branch Commit: %v", err) } if branchRev == trunkRev { t.Fatalf("branch commit produced the same RevID as trunk seed: %s", branchRev) } branchTip, err := r.BranchTip(branch) if err != nil { t.Fatalf("BranchTip(%q): %v", branch, err) } branchRID, err := r.ResolveVersion(string(branchRev)) if err != nil { t.Fatalf("ResolveVersion(%s): %v", branchRev, err) } if branchTip != branchRID { t.Errorf("BranchTip(%q) = %d, want %d (the new commit)", branch, branchTip, branchRID) } trunkTipAfter, err := r.BranchTip("trunk") if err != nil { t.Fatalf("BranchTip(trunk) after: %v", err) } if trunkTipAfter != trunkTipBefore { t.Errorf("trunk tip moved: was %d, now %d — branch commit must not advance trunk", trunkTipBefore, trunkTipAfter) } got, err := h.ReadAt(ctx, branchRev, "branch.txt") if err != nil { t.Fatalf("ReadAt(branchRev): %v", err) } if string(got) != "on branch\n" { t.Errorf("ReadAt(branchRev) = %q, want %q", got, "on branch\n") } } // TestCommit_BranchTags_PropagateForward verifies that a second commit // carrying the same branch tag pair lands on the branch's tip (parented // by the previous branch commit), not on trunk. This is the propagation // path: subsequent commits don't fork unless explicitly told to. func TestCommit_BranchTags_PropagateForward(t *testing.T) { h := newTestHub(t) ctx := context.Background() if _, err := h.Commit(ctx, CommitOpts{ Files: []FileToCommit{{Name: "seed.txt", Content: []byte("seed\n")}}, Message: "seed trunk", Author: "hub", }); err != nil { t.Fatalf("seed Commit: %v", err) } const branch = "feature/y" branchTags := []TagSpec{ {Name: "branch", Value: branch}, {Name: "sym-" + branch, Value: "*"}, } first, err := h.Commit(ctx, CommitOpts{ Files: []FileToCommit{{Name: "f.txt", Content: []byte("v1\n")}}, Message: "first on branch", Author: "hub", Tags: branchTags, }) if err != nil { t.Fatalf("first branch Commit: %v", err) } second, err := h.Commit(ctx, CommitOpts{ Files: []FileToCommit{{Name: "f.txt", Content: []byte("v2\n")}}, Message: "second on branch", Author: "hub", Tags: branchTags, }) if err != nil { t.Fatalf("second branch Commit: %v", err) } if first == second { t.Fatalf("second commit returned same RevID as first: %s", first) } r := h.Repo().handle tip, err := r.BranchTip(branch) if err != nil { t.Fatalf("BranchTip(%q): %v", branch, err) } secondRID, err := r.ResolveVersion(string(second)) if err != nil { t.Fatalf("ResolveVersion(second): %v", err) } if tip != secondRID { t.Errorf("BranchTip(%q) = %d, want %d (the second commit)", branch, tip, secondRID) } got, err := h.ReadAt(ctx, RevID(branch), "f.txt") if err != nil { t.Fatalf("ReadAt(branch symbolic): %v", err) } if string(got) != "v2\n" { t.Errorf("ReadAt(%q, f.txt) = %q, want %q", branch, got, "v2\n") } }