This commit is contained in:
Paul Nodet 2026-09-09 18:40:17 +02:00 committed by GitHub
commit 42ee6a8cd5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 92 additions and 4 deletions

View file

@ -76,7 +76,11 @@ type Gui struct {
// this is a mapping of repos to gui states, so that we can restore the original
// gui state when returning from a subrepo.
// In repos with multiple worktrees, we store a separate repo state per worktree.
RepoStateMap map[Repo]*GuiRepoState
RepoStateMap map[Repo]*GuiRepoState
// Holds state shared between all worktrees of the same repo, keyed by the
// repo's common git dir (one entry per repo, where RepoStateMap has one
// entry per worktree).
sharedRepoStateMap map[Repo]*SharedRepoState
Config config.AppConfigurer
Updater *updates.Updater
statusManager *status.StatusManager
@ -273,6 +277,14 @@ type GuiRepoState struct {
var _ types.IRepoStateAccessor = new(GuiRepoState)
// SharedRepoState is state shared between all worktrees of the same repo.
// Unlike GuiRepoState, of which we keep one instance per worktree, there is
// only one instance of this per repo; e.g. commits copied for cherry-picking
// in one worktree can be pasted in another.
type SharedRepoState struct {
CherryPicking *cherrypicking.CherryPicking
}
func (self *GuiRepoState) GetViewsSetup() bool {
return self.ViewsSetup
}
@ -615,6 +627,15 @@ func (gui *Gui) resetState(startArgs appTypes.StartArgs) types.Context {
return gui.c.Context().Current()
}
repoGitDirPath := gui.git.RepoPaths.RepoGitDirPath()
sharedState := gui.sharedRepoStateMap[Repo(repoGitDirPath)]
if sharedState == nil {
sharedState = &SharedRepoState{
CherryPicking: cherrypicking.New(),
}
gui.sharedRepoStateMap[Repo(repoGitDirPath)] = sharedState
}
contextTree := gui.contextTree()
initialScreenMode := initialScreenMode(startArgs, gui.Config)
@ -637,7 +658,7 @@ func (gui *Gui) resetState(startArgs appTypes.StartArgs) types.Context {
},
Modes: &types.Modes{
Filtering: filtering.New(startArgs.FilterPath, ""),
CherryPicking: cherrypicking.New(),
CherryPicking: sharedState.CherryPicking,
Diffing: diffing.New(),
MarkedBaseCommit: marked_base_commit.New(),
},
@ -789,6 +810,7 @@ func NewGui(
showRecentRepos: showRecentRepos,
RepoPathStack: &utils.Stack[types.RepoLocation]{},
RepoStateMap: map[Repo]*GuiRepoState{},
sharedRepoStateMap: map[Repo]*SharedRepoState{},
GuiLog: []string{},
// initializing this to true for the time being; it will be reset to the

View file

@ -8,8 +8,13 @@ import (
)
type Modes struct {
Filtering filtering.Filtering
CherryPicking *cherrypicking.CherryPicking
Filtering filtering.Filtering
// Shared between all worktrees of the same repo (see gui.SharedRepoState).
// Mutate it through this pointer, but never replace it, otherwise it is no
// longer shared.
CherryPicking *cherrypicking.CherryPicking
Diffing diffing.Diffing
MarkedBaseCommit marked_base_commit.MarkedBaseCommit
}

View file

@ -550,6 +550,7 @@ var tests = []*components.IntegrationTest{
worktree.AssociateBranchRebase,
worktree.BareRepo,
worktree.BareRepoWorktreeConfig,
worktree.CherryPickAcrossWorktrees,
worktree.Crud,
worktree.CustomCommand,
worktree.DefaultPathTilde,

View file

@ -0,0 +1,60 @@
package worktree
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var CherryPickAcrossWorktrees = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Copy a commit in one worktree and paste it in another worktree of the same repo",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.NewBranch("mybranch")
shell.EmptyCommit("base")
// the linked worktree's branch stays at "base"
shell.AddWorktree("mybranch", "../linked-worktree", "newbranch")
shell.EmptyCommit("one")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Commits().
Focus().
Lines(
Contains("one").IsSelected(),
Contains("base"),
).
Press(keys.Commits.CherryPickCopy)
t.Views().Information().Content(Contains("1 commit copied"))
t.Views().Worktrees().
Focus().
Lines(
Contains("(main worktree)").IsSelected(),
Contains("linked-worktree"),
).
NavigateToLine(Contains("linked-worktree")).
Press(keys.Universal.Select)
t.Views().Commits().
Focus().
Lines(
Contains("base"),
).
Press(keys.Commits.PasteCommits)
t.ExpectPopup().Alert().
Title(Equals("Cherry-pick")).
Content(Contains("Are you sure you want to cherry-pick the 1 copied commit(s) onto this branch?")).
Confirm()
t.Views().Information().Content(DoesNotContain("commit copied"))
t.Views().Commits().
Lines(
Contains("one"),
Contains("base").IsSelected(),
)
},
})