Files
agent-tools/cmd/agentws/rm_test.go
T
unkin-agent 6c88d17736
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
agentws: refuse rm on a branch name shared by several repos
2026-10-02 22:50:59 +10:00

104 lines
2.9 KiB
Go

package main
import (
"path/filepath"
"strings"
"testing"
"git.unkin.net/unkin/agent-tools/internal/agent"
)
// addOtherRepoWorktree clones a second source repo "other" and gives it a
// managed worktree on branch, so two repos share one branch name.
func addOtherRepoWorktree(t *testing.T, f *fixture, branch string) string {
t.Helper()
src := filepath.Join(f.root, "src", "other")
git(t, filepath.Join(f.root, "src"), "clone", f.bare, src)
path := filepath.Join(f.wtRoot, agent.WorktreeDirName("other", branch))
git(t, src, "worktree", "add", path, "-b", branch, "origin/main")
return path
}
func TestResolveUniqueBranch(t *testing.T) {
f := newFixture(t)
want := f.addWorktree(t, "benvin/one")
f.addWorktree(t, "benvin/two")
wt, err := resolveWorktree("benvin/one", "")
if err != nil {
t.Fatal(err)
}
if wt.path != want {
t.Errorf("path %q, want %q", wt.path, want)
}
}
func TestResolveAmbiguousBranchRefused(t *testing.T) {
f := newFixture(t)
a := f.addWorktree(t, "benvin/shared")
b := addOtherRepoWorktree(t, f, "benvin/shared")
_, err := resolveWorktree("benvin/shared", "")
if err == nil {
t.Fatal("ambiguous branch resolved, want refusal")
}
for _, p := range []string{a, b} {
if !strings.Contains(err.Error(), p) {
t.Errorf("error %q does not list candidate %s", err, p)
}
}
}
func TestRmAmbiguousBranchRemovesNothing(t *testing.T) {
f := newFixture(t)
a := f.addWorktree(t, "benvin/shared")
b := addOtherRepoWorktree(t, f, "benvin/shared")
cmd := newRootCmd()
cmd.SetArgs([]string{"rm", "benvin/shared"})
cmd.SetOut(new(strings.Builder))
cmd.SetErr(new(strings.Builder))
if err := cmd.Execute(); err == nil {
t.Fatal("rm succeeded on an ambiguous branch")
}
if !exists(a) || !exists(b) {
t.Error("ambiguous rm removed a worktree")
}
}
func TestResolveByPathDespiteSharedBranch(t *testing.T) {
f := newFixture(t)
f.addWorktree(t, "benvin/shared")
b := addOtherRepoWorktree(t, f, "benvin/shared")
wt, err := resolveWorktree(b, "")
if err != nil {
t.Fatal(err)
}
if wt.path != b || wt.repo != "other" {
t.Errorf("got %s (%s), want %s (other)", wt.path, wt.repo, b)
}
}
func TestResolveRepoDisambiguates(t *testing.T) {
f := newFixture(t)
a := f.addWorktree(t, "benvin/shared")
b := addOtherRepoWorktree(t, f, "benvin/shared")
for repo, want := range map[string]string{"repo": a, "other": b} {
wt, err := resolveWorktree("benvin/shared", repo)
if err != nil {
t.Fatalf("--repo %s: %v", repo, err)
}
if wt.path != want {
t.Errorf("--repo %s: path %q, want %q", repo, wt.path, want)
}
}
if _, err := resolveWorktree("benvin/shared", "missing"); err == nil {
t.Error("--repo missing resolved, want no match")
}
}
func TestResolvePathOutsideRepoFilterRefused(t *testing.T) {
f := newFixture(t)
a := f.addWorktree(t, "benvin/one")
if _, err := resolveWorktree(a, "other"); err == nil {
t.Error("path in repo resolved under --repo other")
}
}