ref: df1f2fb3daa1acd25c88510f259d5535fb482126
dir: /ref/store/files/transaction_names_test.go/
package files_test
import (
"testing"
"codeberg.org/lindenii/furgit/internal/testgit"
objectid "codeberg.org/lindenii/furgit/object/id"
"codeberg.org/lindenii/furgit/ref"
refstore "codeberg.org/lindenii/furgit/ref/store"
)
func TestFilesTransactionValidateUpdateNames(t *testing.T) {
t.Parallel()
testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { //nolint:thelper
testRepo := testgit.NewRepo(t, testgit.RepoOptions{ObjectFormat: algo, Bare: true})
_, _, commitID := testRepo.MakeCommit(t, "base")
store := openFilesStore(t, testRepo, algo)
tests := []struct {
name string
queue func(refstore.Transaction) error
wantErr bool
}{
{
name: "create refs/heads/main",
queue: func(tx refstore.Transaction) error {
return tx.Create("refs/heads/main", commitID)
},
},
{
name: "create foo/bar",
queue: func(tx refstore.Transaction) error {
return tx.Create("foo/bar", commitID)
},
},
{
name: "create FETCH_HEAD",
queue: func(tx refstore.Transaction) error {
return tx.Create("FETCH_HEAD", commitID)
},
wantErr: true,
},
{
name: "create MERGE_HEAD",
queue: func(tx refstore.Transaction) error {
return tx.Create("MERGE_HEAD", commitID)
},
wantErr: true,
},
{
name: "create bad refname",
queue: func(tx refstore.Transaction) error {
return tx.Create("refs/heads/.bad", commitID)
},
wantErr: true,
},
{
name: "verify unsafe delete-style name",
queue: func(tx refstore.Transaction) error {
return tx.Verify("foo/bar", commitID)
},
wantErr: true,
},
{
name: "verify pseudoref-style name",
queue: func(tx refstore.Transaction) error {
return tx.Verify("PSEUDOREF", commitID)
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tx, err := store.BeginTransaction()
if err != nil {
t.Fatalf("BeginTransaction: %v", err)
}
err = tt.queue(tx)
if (err != nil) != tt.wantErr {
t.Fatalf("queue err=%v, wantErr=%v", err, tt.wantErr)
}
_ = tx.Abort()
})
}
})
}
func TestFilesTransactionSymbolicTargetRules(t *testing.T) {
t.Parallel()
testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { //nolint:thelper
testRepo := testgit.NewRepo(t, testgit.RepoOptions{ObjectFormat: algo, Bare: true})
_, _, mainID := testRepo.MakeCommit(t, "main")
testRepo.UpdateRef(t, "refs/heads/main", mainID)
testRepo.UpdateRef(t, "ORIG_HEAD", mainID)
store := openFilesStore(t, testRepo, algo)
tests := []struct {
name string
queue func(refstore.Transaction) error
wantErr bool
}{
{
name: "head requires branch target",
queue: func(tx refstore.Transaction) error {
return tx.CreateSymbolic("HEAD", "foo")
},
wantErr: true,
},
{
name: "head accepts refs/heads target",
queue: func(tx refstore.Transaction) error {
return tx.CreateSymbolic("HEAD", "refs/heads/main")
},
},
{
name: "non-head allows top-level target",
queue: func(tx refstore.Transaction) error {
return tx.CreateSymbolic("refs/heads/top-level", "ORIG_HEAD")
},
},
{
name: "non-head rejects invalid target",
queue: func(tx refstore.Transaction) error {
return tx.CreateSymbolic("refs/heads/invalid", "foo..bar")
},
wantErr: true,
},
{
name: "non-head allows worktree target",
queue: func(tx refstore.Transaction) error {
return tx.CreateSymbolic("refs/heads/worktree-target", "worktrees/wt1/HEAD")
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tx, err := store.BeginTransaction()
if err != nil {
t.Fatalf("BeginTransaction: %v", err)
}
err = tt.queue(tx)
if (err != nil) != tt.wantErr {
t.Fatalf("queue err=%v, wantErr=%v", err, tt.wantErr)
}
_ = tx.Abort()
})
}
tx, err := store.BeginTransaction()
if err != nil {
t.Fatalf("BeginTransaction(final symbolic): %v", err)
}
err = tx.CreateSymbolic("refs/heads/top-level", "ORIG_HEAD")
if err != nil {
t.Fatalf("CreateSymbolic(top-level): %v", err)
}
err = tx.Commit()
if err != nil {
t.Fatalf("Commit(CreateSymbolic top-level): %v", err)
}
got, err := store.Resolve("refs/heads/top-level")
if err != nil {
t.Fatalf("Resolve(top-level): %v", err)
}
sym, ok := got.(ref.Symbolic)
if !ok {
t.Fatalf("Resolve(top-level) type = %T, want ref.Symbolic", got)
}
if sym.Target != "ORIG_HEAD" {
t.Fatalf("top-level target = %q, want %q", sym.Target, "ORIG_HEAD")
}
})
}