Skip to content
quarry Artifact [ab8ee52102]
Login

Artifact [ab8ee52102]

Artifact ab8ee521028dd3d7db3946b28d21f939d0d192e0f080f60939cd7cb3c48050d7:


package index

import "testing"

// defaultIs checks the answer after the fixture's direct writes, which
// bypass the fold and so drop the memo themselves, as a fold does.
func defaultIs(t *testing.T, ix *Index, want string) {
	t.Helper()
	ix.invalidateCounts()
	if got := ix.DefaultBranch(); got != want {
		t.Fatalf("FAIL: DefaultBranch = %q, want %q", got, want)
	}
}

func TestDefaultBranchOfAnEmptyRepositoryIsTrunk(t *testing.T) {
	defaultIs(t, openIndex(t), "trunk")
}

// The case the old rule got wrong: a separate main branch with newer
// work is not the default while trunk exists.
func TestDefaultBranchKeepsTrunkWhenMainIsNewer(t *testing.T) {
	ix := openIndex(t)
	ci(t, ix, "a1", "trunk", "2026-01-01T00:00:00", "root")
	ci(t, ix, "b1", "main", "2026-08-01T00:00:00", "side line", "a1")
	foldSymbols(t, ix)
	defaultIs(t, ix, "trunk")
	ci(t, ix, "b2", "main", "2026-08-02T00:00:00", "more", "b1")
	foldSymbols(t, ix)
	defaultIs(t, ix, "trunk")
}

// tcl, tk and tcllib renamed trunk to main by adding a propagating
// sym-main without cancelling sym-trunk: trunk is another name for main
// there, and main is what the repository calls its line.
func TestDefaultBranchFollowsARenamedTrunk(t *testing.T) {
	ix := openIndex(t)
	ci(t, ix, "a1", "trunk", "2011-03-05T00:00:00", "before the rename")
	ci(t, ix, "b1", "main", "2026-08-01T00:00:00", "renamed", "a1")
	tag(t, ix, "b1", "sym-trunk", "*", "2026-08-01T00:00:00")
	foldSymbols(t, ix)
	defaultIs(t, ix, "main")
}

// A feature branch that forgot to cancel sym-trunk makes trunk resolve
// into it; that never makes the feature branch the default.
func TestDefaultBranchIgnoresATrunkAliasOntoAFeatureBranch(t *testing.T) {
	ix := openIndex(t)
	ci(t, ix, "a1", "trunk", "2026-01-01T00:00:00", "root")
	ci(t, ix, "f1", "wild-idea", "2026-08-01T00:00:00", "fork", "a1")
	tag(t, ix, "f1", "sym-trunk", "*", "2026-08-01T00:00:00")
	foldSymbols(t, ix)
	defaultIs(t, ix, "trunk")
}

func TestDefaultBranchWithoutTrunkPrefersMainThenMaster(t *testing.T) {
	ix := openIndex(t)
	ci(t, ix, "m1", "master", "2026-09-01T00:00:00", "git import")
	foldSymbols(t, ix)
	defaultIs(t, ix, "master")
	ci(t, ix, "n1", "main", "2020-01-01T00:00:00", "older, still preferred")
	foldSymbols(t, ix)
	defaultIs(t, ix, "main")
}

// No conventional name at all: the branch the history starts on, not
// whichever branch was pushed to last.
func TestDefaultBranchFallsBackToTheOldestRootBranch(t *testing.T) {
	ix := openIndex(t)
	ci(t, ix, "r1", "develop", "2020-01-01T00:00:00", "first")
	ci(t, ix, "f1", "feature", "2026-08-01T00:00:00", "newer", "r1")
	ci(t, ix, "r2", "orphan", "2024-01-01T00:00:00", "a later root")
	foldSymbols(t, ix)
	defaultIs(t, ix, "develop")
}

// The answer is memoised until the next fold: it sits on the CI path of
// every new check-in.
func TestDefaultBranchIsMemoisedUntilAFold(t *testing.T) {
	ix := openIndex(t)
	ci(t, ix, "m1", "main", "2026-01-01T00:00:00", "root")
	foldSymbols(t, ix)
	defaultIs(t, ix, "main")
	ci(t, ix, "t1", "trunk", "2026-01-02T00:00:00", "unfolded")
	if got := ix.DefaultBranch(); got != "main" {
		t.Fatalf("FAIL: answer moved without a fold: %q", got)
	}
	defaultIs(t, ix, "trunk")
}