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") } }