jesseduffield.lazygit/pkg/integration/tests/worktree/new_worktree_picker.go
Stefan Haller 768d9f1a3f Rework the worktrees-panel 'n' into a branch picker
The old 'n' flow opened a "normal vs detached" menu (the same meaningless
gate the 'w' flow used to have), then asked for a base ref, a path typed from
scratch, and a branch name in three separate prompts.

Replace it with a single picker prompt titled "New worktree for branch",
suggesting local branches not already checked out anywhere, plus remote
branches that don't yet have a local branch of the same name. The entered
value is classified on confirm: an existing local branch checks out into a
new worktree, a remote branch creates a new local tracking branch, and
anything else creates a new branch off the current ref. All three then feed
the same location menu the 'w' flow uses, so paths are chosen from candidates
rather than typed blind. Picking a remote or new branch needs no separate
name prompt — the picker value already is the name. Checked-out branches are
filtered from the suggestions, and a verbatim type-in of one is rejected with
an error.

createWorktree now takes the context to switch focus to once the worktree is
created, so 'n' lands back in the worktrees panel while 'w' still lands in
the branches panel.

This deletes the old NewWorktree / NewWorktreeCheckout core and the now-
orphaned i18n (CreateWorktreeFrom, CreateWorktreeFromDetached, NewWorktreeBase,
NewBranchNameLeaveBlank), completing the migration started for 'w'.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 18:53:05 +02:00

65 lines
1.9 KiB
Go

package worktree
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var NewWorktreePicker = NewIntegrationTest(NewIntegrationTestArgs{
Description: "From the worktrees panel, the picker suggests only branches not already checked out, guards verbatim type-ins, and checks out an existing branch",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.NewBranch("mybranch")
shell.CreateFileAndAdd("README.md", "hello world")
shell.Commit("initial commit")
shell.NewBranchFrom("feature", "mybranch")
shell.Checkout("mybranch")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Worktrees().
Focus().
Lines(
Contains("(main worktree)"),
).
Press(keys.Universal.New).
Tap(func() {
// mybranch is checked out by the current worktree, so it's not
// suggested; feature is
t.ExpectPopup().Prompt().
Title(Equals("New worktree for branch")).
SuggestionLines(Contains("feature")).
// typing a checked-out branch verbatim is still rejected
Type("mybranch").
Confirm()
t.ExpectPopup().Alert().
Title(Equals("Error")).
Content(Contains("Branch mybranch is checked out by worktree repo")).
Confirm()
}).
Press(keys.Universal.New).
Tap(func() {
// picking an existing branch checks it out (no new branch)
t.ExpectPopup().Prompt().
Title(Equals("New worktree for branch")).
Type("feature").
Confirm()
t.ExpectPopup().Menu().
Title(Equals("Worktree location")).
Confirm()
}).
// we stay in the worktrees panel, now switched into the new worktree
IsFocused().
Lines(
Contains("feature").IsSelected(),
Contains("(main worktree)"),
)
t.Views().Status().
Content(Contains("repo(feature) → feature"))
},
})