mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-05-11 12:25:47 +02:00
Add more worktree tests
This commit is contained in:
parent
b93b9dae88
commit
a313b16704
12 changed files with 325 additions and 30 deletions
|
@ -74,6 +74,7 @@ The permitted contexts are:
|
||||||
| -------------- | -------------------------------------------------------------------------------------------------------- |
|
| -------------- | -------------------------------------------------------------------------------------------------------- |
|
||||||
| status | The 'Status' tab |
|
| status | The 'Status' tab |
|
||||||
| files | The 'Files' tab |
|
| files | The 'Files' tab |
|
||||||
|
| worktrees | The 'Worktrees' tab |
|
||||||
| localBranches | The 'Local Branches' tab |
|
| localBranches | The 'Local Branches' tab |
|
||||||
| remotes | The 'Remotes' tab |
|
| remotes | The 'Remotes' tab |
|
||||||
| remoteBranches | The context you get when pressing enter on a remote in the remotes tab |
|
| remoteBranches | The context you get when pressing enter on a remote in the remotes tab |
|
||||||
|
@ -300,6 +301,7 @@ SelectedRemote
|
||||||
SelectedTag
|
SelectedTag
|
||||||
SelectedStashEntry
|
SelectedStashEntry
|
||||||
SelectedCommitFile
|
SelectedCommitFile
|
||||||
|
SelectedWorktree
|
||||||
CheckedOutBranch
|
CheckedOutBranch
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -19,12 +19,16 @@ func NewBisectCommands(gitCommon *GitCommon) *BisectCommands {
|
||||||
// This command is pretty cheap to run so we're not storing the result anywhere.
|
// This command is pretty cheap to run so we're not storing the result anywhere.
|
||||||
// But if it becomes problematic we can chang that.
|
// But if it becomes problematic we can chang that.
|
||||||
func (self *BisectCommands) GetInfo() *BisectInfo {
|
func (self *BisectCommands) GetInfo() *BisectInfo {
|
||||||
|
return self.GetInfoForGitDir(self.dotGitDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *BisectCommands) GetInfoForGitDir(gitDir string) *BisectInfo {
|
||||||
var err error
|
var err error
|
||||||
info := &BisectInfo{started: false, log: self.Log, newTerm: "bad", oldTerm: "good"}
|
info := &BisectInfo{started: false, log: self.Log, newTerm: "bad", oldTerm: "good"}
|
||||||
// we return nil if we're not in a git bisect session.
|
// we return nil if we're not in a git bisect session.
|
||||||
// we know we're in a session by the presence of a .git/BISECT_START file
|
// we know we're in a session by the presence of a .git/BISECT_START file
|
||||||
|
|
||||||
bisectStartPath := filepath.Join(self.dotGitDir, "BISECT_START")
|
bisectStartPath := filepath.Join(gitDir, "BISECT_START")
|
||||||
exists, err := self.os.FileExists(bisectStartPath)
|
exists, err := self.os.FileExists(bisectStartPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
self.Log.Infof("error getting git bisect info: %s", err.Error())
|
self.Log.Infof("error getting git bisect info: %s", err.Error())
|
||||||
|
@ -44,7 +48,7 @@ func (self *BisectCommands) GetInfo() *BisectInfo {
|
||||||
info.started = true
|
info.started = true
|
||||||
info.start = strings.TrimSpace(string(startContent))
|
info.start = strings.TrimSpace(string(startContent))
|
||||||
|
|
||||||
termsContent, err := os.ReadFile(filepath.Join(self.dotGitDir, "BISECT_TERMS"))
|
termsContent, err := os.ReadFile(filepath.Join(gitDir, "BISECT_TERMS"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// old git versions won't have this file so we default to bad/good
|
// old git versions won't have this file so we default to bad/good
|
||||||
} else {
|
} else {
|
||||||
|
@ -53,7 +57,7 @@ func (self *BisectCommands) GetInfo() *BisectInfo {
|
||||||
info.oldTerm = splitContent[1]
|
info.oldTerm = splitContent[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
bisectRefsDir := filepath.Join(self.dotGitDir, "refs", "bisect")
|
bisectRefsDir := filepath.Join(gitDir, "refs", "bisect")
|
||||||
files, err := os.ReadDir(bisectRefsDir)
|
files, err := os.ReadDir(bisectRefsDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
self.Log.Infof("error getting git bisect info: %s", err.Error())
|
self.Log.Infof("error getting git bisect info: %s", err.Error())
|
||||||
|
@ -85,7 +89,7 @@ func (self *BisectCommands) GetInfo() *BisectInfo {
|
||||||
info.statusMap[sha] = status
|
info.statusMap[sha] = status
|
||||||
}
|
}
|
||||||
|
|
||||||
currentContent, err := os.ReadFile(filepath.Join(self.dotGitDir, "BISECT_EXPECTED_REV"))
|
currentContent, err := os.ReadFile(filepath.Join(gitDir, "BISECT_EXPECTED_REV"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
self.Log.Infof("error getting git bisect info: %s", err.Error())
|
self.Log.Infof("error getting git bisect info: %s", err.Error())
|
||||||
return info
|
return info
|
||||||
|
|
|
@ -48,10 +48,23 @@ func (self *WorktreeLoader) GetWorktrees() ([]*models.Worktree, error) {
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(splitLine, "worktree ") {
|
if strings.HasPrefix(splitLine, "worktree ") {
|
||||||
path := strings.SplitN(splitLine, " ", 2)[1]
|
path := strings.SplitN(splitLine, " ", 2)[1]
|
||||||
|
isMain := path == currentRepoPath
|
||||||
|
|
||||||
|
var gitDir string
|
||||||
|
if isMain {
|
||||||
|
gitDir = filepath.Join(path, ".git")
|
||||||
|
} else {
|
||||||
|
var ok bool
|
||||||
|
gitDir, ok = LinkedWorktreeGitPath(path)
|
||||||
|
if !ok {
|
||||||
|
self.Log.Warnf("Could not find git dir for worktree %s", path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
current = &models.Worktree{
|
current = &models.Worktree{
|
||||||
IsMain: path == currentRepoPath,
|
IsMain: path == currentRepoPath,
|
||||||
Path: path,
|
Path: path,
|
||||||
|
GitDir: gitDir,
|
||||||
}
|
}
|
||||||
} else if strings.HasPrefix(splitLine, "branch ") {
|
} else if strings.HasPrefix(splitLine, "branch ") {
|
||||||
branch := strings.SplitN(splitLine, " ", 2)[1]
|
branch := strings.SplitN(splitLine, " ", 2)[1]
|
||||||
|
@ -91,9 +104,21 @@ func (self *WorktreeLoader) GetWorktrees() ([]*models.Worktree, error) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we couldn't find the git directory, we can't find the branch name
|
||||||
|
if worktree.GitDir == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
rebaseBranch, ok := rebaseBranch(worktree)
|
rebaseBranch, ok := rebaseBranch(worktree)
|
||||||
if ok {
|
if ok {
|
||||||
worktree.Branch = rebaseBranch
|
worktree.Branch = rebaseBranch
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
bisectBranch, ok := bisectBranch(worktree)
|
||||||
|
if ok {
|
||||||
|
worktree.Branch = bisectBranch
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,29 +126,25 @@ func (self *WorktreeLoader) GetWorktrees() ([]*models.Worktree, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func rebaseBranch(worktree *models.Worktree) (string, bool) {
|
func rebaseBranch(worktree *models.Worktree) (string, bool) {
|
||||||
var gitPath string
|
for _, dir := range []string{"rebase-merge", "rebase-apply"} {
|
||||||
if worktree.Main() {
|
if bytesContent, err := os.ReadFile(filepath.Join(worktree.GitDir, dir, "head-name")); err == nil {
|
||||||
gitPath = filepath.Join(worktree.Path, ".git")
|
headName := strings.TrimSpace(string(bytesContent))
|
||||||
} else {
|
shortHeadName := strings.TrimPrefix(headName, "refs/heads/")
|
||||||
// need to find the path of the linked worktree in the .git dir
|
return shortHeadName, true
|
||||||
var ok bool
|
|
||||||
gitPath, ok = LinkedWorktreeGitPath(worktree.Path)
|
|
||||||
if !ok {
|
|
||||||
return "", false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// now we look inside that git path for a file `rebase-merge/head-name`
|
return "", false
|
||||||
// if it exists, we update the worktree to say that it has that for a head
|
}
|
||||||
headNameContents, err := os.ReadFile(filepath.Join(gitPath, "rebase-merge", "head-name"))
|
|
||||||
|
func bisectBranch(worktree *models.Worktree) (string, bool) {
|
||||||
|
bisectStartPath := filepath.Join(worktree.GitDir, "BISECT_START")
|
||||||
|
startContent, err := os.ReadFile(bisectStartPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
headName := strings.TrimSpace(string(headNameContents))
|
return strings.TrimSpace(string(startContent)), true
|
||||||
shortHeadName := strings.TrimPrefix(headName, "refs/heads/")
|
|
||||||
|
|
||||||
return shortHeadName, true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func LinkedWorktreeGitPath(worktreePath string) (string, bool) {
|
func LinkedWorktreeGitPath(worktreePath string) (string, bool) {
|
||||||
|
|
|
@ -4,9 +4,19 @@ package models
|
||||||
type Worktree struct {
|
type Worktree struct {
|
||||||
// if false, this is a linked worktree
|
// if false, this is a linked worktree
|
||||||
IsMain bool
|
IsMain bool
|
||||||
Path string
|
// path to the directory of the worktree i.e. the directory that contains all the user's files
|
||||||
|
Path string
|
||||||
|
// path of the git directory for this worktree. The equivalent of the .git directory
|
||||||
|
// in the main worktree. For linked worktrees this would be <repo_path>/.git/worktrees/<name>
|
||||||
|
GitDir string
|
||||||
|
// If the worktree has a branch checked out, this field will be set to the branch name.
|
||||||
|
// A branch is considered 'checked out' if:
|
||||||
|
// * the worktree is directly on the branch
|
||||||
|
// * the worktree is mid-rebase on the branch
|
||||||
|
// * the worktree is mid-bisect on the branch
|
||||||
Branch string
|
Branch string
|
||||||
// based on the path, but uniquified
|
// based on the path, but uniquified. Not the same name that git uses in the worktrees/ folder (no good reason for this,
|
||||||
|
// I just prefer my naming convention better)
|
||||||
NameField string
|
NameField string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -475,7 +475,10 @@ func (self *BranchesController) rename(branch *models.Branch) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// need to find where the branch is now so that we can re-select it. That means we need to refetch the branches synchronously and then find our branch
|
// need to find where the branch is now so that we can re-select it. That means we need to refetch the branches synchronously and then find our branch
|
||||||
_ = self.c.Refresh(types.RefreshOptions{Mode: types.SYNC, Scope: []types.RefreshableView{types.BRANCHES}})
|
_ = self.c.Refresh(types.RefreshOptions{
|
||||||
|
Mode: types.SYNC,
|
||||||
|
Scope: []types.RefreshableView{types.BRANCHES, types.WORKTREES},
|
||||||
|
})
|
||||||
|
|
||||||
// now that we've got our stuff again we need to find that branch and reselect it.
|
// now that we've got our stuff again we need to find that branch and reselect it.
|
||||||
for i, newBranch := range self.c.Model().Branches {
|
for i, newBranch := range self.c.Model().Branches {
|
||||||
|
|
|
@ -33,6 +33,7 @@ type SessionState struct {
|
||||||
SelectedStashEntry *models.StashEntry
|
SelectedStashEntry *models.StashEntry
|
||||||
SelectedCommitFile *models.CommitFile
|
SelectedCommitFile *models.CommitFile
|
||||||
SelectedCommitFilePath string
|
SelectedCommitFilePath string
|
||||||
|
SelectedWorktree *models.Worktree
|
||||||
CheckedOutBranch *models.Branch
|
CheckedOutBranch *models.Branch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,6 +51,7 @@ func (self *SessionStateLoader) call() *SessionState {
|
||||||
SelectedCommitFile: self.c.Contexts().CommitFiles.GetSelectedFile(),
|
SelectedCommitFile: self.c.Contexts().CommitFiles.GetSelectedFile(),
|
||||||
SelectedCommitFilePath: self.c.Contexts().CommitFiles.GetSelectedPath(),
|
SelectedCommitFilePath: self.c.Contexts().CommitFiles.GetSelectedPath(),
|
||||||
SelectedSubCommit: self.c.Contexts().SubCommits.GetSelected(),
|
SelectedSubCommit: self.c.Contexts().SubCommits.GetSelected(),
|
||||||
|
SelectedWorktree: self.c.Contexts().Worktrees.GetSelected(),
|
||||||
CheckedOutBranch: self.refsHelper.GetCheckedOutRef(),
|
CheckedOutBranch: self.refsHelper.GetCheckedOutRef(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -221,7 +221,11 @@ var tests = []*components.IntegrationTest{
|
||||||
undo.UndoCheckoutAndDrop,
|
undo.UndoCheckoutAndDrop,
|
||||||
undo.UndoDrop,
|
undo.UndoDrop,
|
||||||
worktree.AddFromBranch,
|
worktree.AddFromBranch,
|
||||||
|
worktree.AddFromBranchDetached,
|
||||||
|
worktree.AddFromCommit,
|
||||||
|
worktree.Bisect,
|
||||||
worktree.Crud,
|
worktree.Crud,
|
||||||
|
worktree.CustomCommand,
|
||||||
worktree.DetachWorktreeFromBranch,
|
worktree.DetachWorktreeFromBranch,
|
||||||
worktree.ForceRemoveWorktree,
|
worktree.ForceRemoveWorktree,
|
||||||
worktree.Rebase,
|
worktree.Rebase,
|
||||||
|
|
46
pkg/integration/tests/worktree/add_from_branch_detached.go
Normal file
46
pkg/integration/tests/worktree/add_from_branch_detached.go
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
package worktree
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/config"
|
||||||
|
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||||
|
)
|
||||||
|
|
||||||
|
var AddFromBranchDetached = NewIntegrationTest(NewIntegrationTestArgs{
|
||||||
|
Description: "Add a detached worktree via the branches view",
|
||||||
|
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")
|
||||||
|
},
|
||||||
|
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||||
|
t.Views().Branches().
|
||||||
|
Focus().
|
||||||
|
Lines(
|
||||||
|
Contains("mybranch"),
|
||||||
|
).
|
||||||
|
Press(keys.Worktrees.ViewWorktreeOptions).
|
||||||
|
Tap(func() {
|
||||||
|
t.ExpectPopup().Menu().
|
||||||
|
Title(Equals("Worktree")).
|
||||||
|
Select(Contains(`Create worktree from mybranch (detached)`)).
|
||||||
|
Confirm()
|
||||||
|
|
||||||
|
t.ExpectPopup().Prompt().
|
||||||
|
Title(Equals("New worktree path")).
|
||||||
|
Type("../linked-worktree").
|
||||||
|
Confirm()
|
||||||
|
}).
|
||||||
|
// confirm we're still focused on the branches view
|
||||||
|
IsFocused().
|
||||||
|
Lines(
|
||||||
|
Contains("(no branch)").IsSelected(),
|
||||||
|
Contains("mybranch (worktree)"),
|
||||||
|
)
|
||||||
|
|
||||||
|
t.Views().Status().
|
||||||
|
Content(Contains("repo(linked-worktree)"))
|
||||||
|
},
|
||||||
|
})
|
56
pkg/integration/tests/worktree/add_from_commit.go
Normal file
56
pkg/integration/tests/worktree/add_from_commit.go
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
package worktree
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/config"
|
||||||
|
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||||
|
)
|
||||||
|
|
||||||
|
var AddFromCommit = NewIntegrationTest(NewIntegrationTestArgs{
|
||||||
|
Description: "Add a worktree via the commits view",
|
||||||
|
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.EmptyCommit("commit two")
|
||||||
|
},
|
||||||
|
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||||
|
t.Views().Commits().
|
||||||
|
Focus().
|
||||||
|
Lines(
|
||||||
|
Contains("commit two").IsSelected(),
|
||||||
|
Contains("initial commit"),
|
||||||
|
).
|
||||||
|
NavigateToLine(Contains("initial commit")).
|
||||||
|
Press(keys.Worktrees.ViewWorktreeOptions).
|
||||||
|
Tap(func() {
|
||||||
|
t.ExpectPopup().Menu().
|
||||||
|
Title(Equals("Worktree")).
|
||||||
|
Select(MatchesRegexp(`Create worktree from .*`).DoesNotContain("detached")).
|
||||||
|
Confirm()
|
||||||
|
|
||||||
|
t.ExpectPopup().Prompt().
|
||||||
|
Title(Equals("New worktree path")).
|
||||||
|
Type("../linked-worktree").
|
||||||
|
Confirm()
|
||||||
|
|
||||||
|
t.ExpectPopup().Prompt().
|
||||||
|
Title(Equals("New branch name")).
|
||||||
|
Type("newbranch").
|
||||||
|
Confirm()
|
||||||
|
}).
|
||||||
|
Lines(
|
||||||
|
Contains("initial commit"),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Confirm we're now in the branches view
|
||||||
|
t.Views().Branches().
|
||||||
|
IsFocused().
|
||||||
|
Lines(
|
||||||
|
Contains("newbranch").IsSelected(),
|
||||||
|
Contains("mybranch (worktree)"),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
})
|
88
pkg/integration/tests/worktree/bisect.go
Normal file
88
pkg/integration/tests/worktree/bisect.go
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
package worktree
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/config"
|
||||||
|
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This is important because `git worktree list` will show a worktree being in a detached head state (which is true)
|
||||||
|
// when it's in the middle of a bisect, but it won't tell you about the branch it's on.
|
||||||
|
// Even so, if you attempt to check out that branch from another worktree git won't let you, so we need to
|
||||||
|
// keep track of the association ourselves.
|
||||||
|
|
||||||
|
// not bothering to test the linked worktree here because it's the same logic as the rebase test
|
||||||
|
|
||||||
|
var Bisect = NewIntegrationTest(NewIntegrationTestArgs{
|
||||||
|
Description: "Verify that when you start a bisect in a linked worktree, Lazygit still associates the worktree with the 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.EmptyCommit("commit 2")
|
||||||
|
shell.EmptyCommit("commit 3")
|
||||||
|
shell.AddWorktree("mybranch", "../linked-worktree", "newbranch")
|
||||||
|
},
|
||||||
|
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||||
|
t.Views().Branches().
|
||||||
|
Focus().
|
||||||
|
Lines(
|
||||||
|
Contains("mybranch").IsSelected(),
|
||||||
|
Contains("newbranch (worktree)"),
|
||||||
|
)
|
||||||
|
|
||||||
|
// start a bisect on the main worktree
|
||||||
|
t.Views().Commits().
|
||||||
|
Focus().
|
||||||
|
SelectedLine(Contains("commit 3")).
|
||||||
|
Press(keys.Commits.ViewBisectOptions).
|
||||||
|
Tap(func() {
|
||||||
|
t.ExpectPopup().Menu().
|
||||||
|
Title(Equals("Bisect")).
|
||||||
|
Select(MatchesRegexp(`Mark .* as bad`)).
|
||||||
|
Confirm()
|
||||||
|
|
||||||
|
t.Views().Information().Content(Contains("Bisecting"))
|
||||||
|
}).
|
||||||
|
NavigateToLine(Contains("initial commit")).
|
||||||
|
Press(keys.Commits.ViewBisectOptions).
|
||||||
|
Tap(func() {
|
||||||
|
t.ExpectPopup().Menu().
|
||||||
|
Title(Equals("Bisect")).
|
||||||
|
Select(MatchesRegexp(`Mark .* as good`)).
|
||||||
|
Confirm()
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Views().Branches().
|
||||||
|
Focus().
|
||||||
|
// switch to linked worktree
|
||||||
|
NavigateToLine(Contains("newbranch")).
|
||||||
|
Press(keys.Universal.Select).
|
||||||
|
Tap(func() {
|
||||||
|
t.ExpectPopup().Confirmation().
|
||||||
|
Title(Equals("Switch to worktree")).
|
||||||
|
Content(Equals("This branch is checked out by worktree linked-worktree. Do you want to switch to that worktree?")).
|
||||||
|
Confirm()
|
||||||
|
|
||||||
|
t.Views().Information().Content(DoesNotContain("Bisecting"))
|
||||||
|
}).
|
||||||
|
Lines(
|
||||||
|
Contains("newbranch").IsSelected(),
|
||||||
|
Contains("mybranch (worktree)"),
|
||||||
|
)
|
||||||
|
|
||||||
|
// switch back to main worktree
|
||||||
|
t.Views().Branches().
|
||||||
|
Focus().
|
||||||
|
NavigateToLine(Contains("mybranch")).
|
||||||
|
Press(keys.Universal.Select).
|
||||||
|
Tap(func() {
|
||||||
|
t.ExpectPopup().Confirmation().
|
||||||
|
Title(Equals("Switch to worktree")).
|
||||||
|
Content(Equals("This branch is checked out by worktree repo. Do you want to switch to that worktree?")).
|
||||||
|
Confirm()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
40
pkg/integration/tests/worktree/custom_command.go
Normal file
40
pkg/integration/tests/worktree/custom_command.go
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
package worktree
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/config"
|
||||||
|
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||||
|
)
|
||||||
|
|
||||||
|
var CustomCommand = NewIntegrationTest(NewIntegrationTestArgs{
|
||||||
|
Description: "Verify that custom commands work with worktrees by deleting a worktree via a custom command",
|
||||||
|
ExtraCmdArgs: []string{},
|
||||||
|
Skip: false,
|
||||||
|
SetupConfig: func(cfg *config.AppConfig) {
|
||||||
|
cfg.UserConfig.CustomCommands = []config.CustomCommand{
|
||||||
|
{
|
||||||
|
Key: "d",
|
||||||
|
Context: "worktrees",
|
||||||
|
Command: "git worktree remove {{ .SelectedWorktree.Path | quote }}",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
SetupRepo: func(shell *Shell) {
|
||||||
|
shell.NewBranch("mybranch")
|
||||||
|
shell.CreateFileAndAdd("README.md", "hello world")
|
||||||
|
shell.Commit("initial commit")
|
||||||
|
shell.AddWorktree("mybranch", "../linked-worktree", "newbranch")
|
||||||
|
},
|
||||||
|
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||||
|
t.Views().Worktrees().
|
||||||
|
Focus().
|
||||||
|
Lines(
|
||||||
|
Contains("repo (main)"),
|
||||||
|
Contains("linked-worktree"),
|
||||||
|
).
|
||||||
|
NavigateToLine(Contains("linked-worktree")).
|
||||||
|
Press("d").
|
||||||
|
Lines(
|
||||||
|
Contains("repo (main)"),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
})
|
|
@ -10,8 +10,11 @@ import (
|
||||||
// Even so, if you attempt to check out that branch from another worktree git won't let you, so we need to
|
// Even so, if you attempt to check out that branch from another worktree git won't let you, so we need to
|
||||||
// keep track of the association ourselves.
|
// keep track of the association ourselves.
|
||||||
|
|
||||||
|
// We need different logic for associated the branch depending on whether it's a main worktree or
|
||||||
|
// linked worktree, so this test handles both.
|
||||||
|
|
||||||
var Rebase = NewIntegrationTest(NewIntegrationTestArgs{
|
var Rebase = NewIntegrationTest(NewIntegrationTestArgs{
|
||||||
Description: "Verify that when you start a rebase in a worktree, Lazygit still associates the worktree with the branch",
|
Description: "Verify that when you start a rebase in a linked or main worktree, Lazygit still associates the worktree with the branch",
|
||||||
ExtraCmdArgs: []string{},
|
ExtraCmdArgs: []string{},
|
||||||
Skip: false,
|
Skip: false,
|
||||||
SetupConfig: func(config *config.AppConfig) {},
|
SetupConfig: func(config *config.AppConfig) {},
|
||||||
|
@ -27,10 +30,11 @@ var Rebase = NewIntegrationTest(NewIntegrationTestArgs{
|
||||||
t.Views().Branches().
|
t.Views().Branches().
|
||||||
Focus().
|
Focus().
|
||||||
Lines(
|
Lines(
|
||||||
Contains("mybranch"),
|
Contains("mybranch").IsSelected(),
|
||||||
Contains("newbranch (worktree)"),
|
Contains("newbranch (worktree)"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// start a rebase on the main worktree
|
||||||
t.Views().Commits().
|
t.Views().Commits().
|
||||||
Focus().
|
Focus().
|
||||||
NavigateToLine(Contains("commit 2")).
|
NavigateToLine(Contains("commit 2")).
|
||||||
|
@ -54,8 +58,19 @@ var Rebase = NewIntegrationTest(NewIntegrationTestArgs{
|
||||||
Lines(
|
Lines(
|
||||||
Contains("newbranch").IsSelected(),
|
Contains("newbranch").IsSelected(),
|
||||||
Contains("mybranch (worktree)"),
|
Contains("mybranch (worktree)"),
|
||||||
).
|
)
|
||||||
// switch back to main worktree
|
|
||||||
|
// start a rebase on the linked worktree
|
||||||
|
t.Views().Commits().
|
||||||
|
Focus().
|
||||||
|
NavigateToLine(Contains("commit 2")).
|
||||||
|
Press(keys.Universal.Edit)
|
||||||
|
|
||||||
|
t.Views().Information().Content(Contains("Rebasing"))
|
||||||
|
|
||||||
|
// switch back to main worktree
|
||||||
|
t.Views().Branches().
|
||||||
|
Focus().
|
||||||
NavigateToLine(Contains("mybranch")).
|
NavigateToLine(Contains("mybranch")).
|
||||||
Press(keys.Universal.Select).
|
Press(keys.Universal.Select).
|
||||||
Tap(func() {
|
Tap(func() {
|
||||||
|
@ -63,8 +78,12 @@ var Rebase = NewIntegrationTest(NewIntegrationTestArgs{
|
||||||
Title(Equals("Switch to worktree")).
|
Title(Equals("Switch to worktree")).
|
||||||
Content(Equals("This branch is checked out by worktree repo. Do you want to switch to that worktree?")).
|
Content(Equals("This branch is checked out by worktree repo. Do you want to switch to that worktree?")).
|
||||||
Confirm()
|
Confirm()
|
||||||
|
}).
|
||||||
t.Views().Information().Content(Contains("Rebasing"))
|
Lines(
|
||||||
})
|
Contains("(no branch").IsSelected(),
|
||||||
|
Contains("mybranch"),
|
||||||
|
// even though the linked worktree is rebasing, we still associate it with the branch
|
||||||
|
Contains("newbranch (worktree)"),
|
||||||
|
)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue