summaryrefslogtreecommitdiffstats
path: root/pkg
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2023-07-24 17:16:59 +1000
committerJesse Duffield <jessedduffield@gmail.com>2023-07-30 18:35:23 +1000
commitb3060065d9a776c755903a1297ab3954c01853a8 (patch)
tree84891e7b8be47a734b8e709fce779c4257e14d48 /pkg
parenta313b1670496e1e73745b5a6a922432fb81ce0e6 (diff)
Support fastforwarding worktree
Diffstat (limited to 'pkg')
-rw-r--r--pkg/commands/git_commands/git_command_builder.go12
-rw-r--r--pkg/commands/git_commands/sync.go9
-rw-r--r--pkg/gui/controllers/branches_controller.go30
-rw-r--r--pkg/integration/components/shell.go7
-rw-r--r--pkg/integration/tests/test_list.go1
-rw-r--r--pkg/integration/tests/worktree/fast_forward_worktree_branch.go52
6 files changed, 107 insertions, 4 deletions
diff --git a/pkg/commands/git_commands/git_command_builder.go b/pkg/commands/git_commands/git_command_builder.go
index 78e0236a3..27f2e4a6c 100644
--- a/pkg/commands/git_commands/git_command_builder.go
+++ b/pkg/commands/git_commands/git_command_builder.go
@@ -1,6 +1,8 @@
package git_commands
-import "strings"
+import (
+ "strings"
+)
// convenience struct for building git commands. Especially useful when
// including conditional args
@@ -66,6 +68,14 @@ func (self *GitCommandBuilder) GitDir(path string) *GitCommandBuilder {
return self
}
+func (self *GitCommandBuilder) GitDirIf(condition bool, path string) *GitCommandBuilder {
+ if condition {
+ return self.GitDir(path)
+ }
+
+ return self
+}
+
func (self *GitCommandBuilder) ToArgv() []string {
return append([]string{"git"}, self.args...)
}
diff --git a/pkg/commands/git_commands/sync.go b/pkg/commands/git_commands/sync.go
index d67c6aa79..c32286e6d 100644
--- a/pkg/commands/git_commands/sync.go
+++ b/pkg/commands/git_commands/sync.go
@@ -82,6 +82,7 @@ type PullOptions struct {
RemoteName string
BranchName string
FastForwardOnly bool
+ WorktreeGitDir string
}
func (self *SyncCommands) Pull(task gocui.Task, opts PullOptions) error {
@@ -90,6 +91,7 @@ func (self *SyncCommands) Pull(task gocui.Task, opts PullOptions) error {
ArgIf(opts.FastForwardOnly, "--ff-only").
ArgIf(opts.RemoteName != "", opts.RemoteName).
ArgIf(opts.BranchName != "", opts.BranchName).
+ GitDirIf(opts.WorktreeGitDir != "", opts.WorktreeGitDir).
ToArgv()
// setting GIT_SEQUENCE_EDITOR to ':' as a way of skipping it, in case the user
@@ -97,7 +99,12 @@ func (self *SyncCommands) Pull(task gocui.Task, opts PullOptions) error {
return self.cmd.New(cmdArgs).AddEnvVars("GIT_SEQUENCE_EDITOR=:").PromptOnCredentialRequest(task).WithMutex(self.syncMutex).Run()
}
-func (self *SyncCommands) FastForward(task gocui.Task, branchName string, remoteName string, remoteBranchName string) error {
+func (self *SyncCommands) FastForward(
+ task gocui.Task,
+ branchName string,
+ remoteName string,
+ remoteBranchName string,
+) error {
cmdArgs := NewGitCmd("fetch").
Arg(remoteName).
Arg(remoteBranchName + ":" + branchName).
diff --git a/pkg/gui/controllers/branches_controller.go b/pkg/gui/controllers/branches_controller.go
index 623514638..4415fb012 100644
--- a/pkg/gui/controllers/branches_controller.go
+++ b/pkg/gui/controllers/branches_controller.go
@@ -3,6 +3,7 @@ package controllers
import (
"errors"
"fmt"
+ "os"
"strings"
"github.com/jesseduffield/gocui"
@@ -426,15 +427,23 @@ func (self *BranchesController) fastForward(branch *models.Branch) error {
)
return self.c.WithLoaderPanel(message, func(task gocui.Task) error {
- if branch == self.c.Helpers().Refs.GetCheckedOutRef() {
+ worktree, ok := self.worktreeForBranch(branch)
+ if ok {
self.c.LogAction(action)
+ worktreeGitDir := ""
+ // if it is the current worktree path, no need to specify the path
+ if !git_commands.IsCurrentWorktree(worktree.Path) {
+ worktreeGitDir = worktree.GitDir
+ }
+
err := self.c.Git().Sync.Pull(
task,
git_commands.PullOptions{
RemoteName: branch.UpstreamRemote,
BranchName: branch.UpstreamBranch,
FastForwardOnly: true,
+ WorktreeGitDir: worktreeGitDir,
},
)
if err != nil {
@@ -444,7 +453,10 @@ func (self *BranchesController) fastForward(branch *models.Branch) error {
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
} else {
self.c.LogAction(action)
- err := self.c.Git().Sync.FastForward(task, branch.Name, branch.UpstreamRemote, branch.UpstreamBranch)
+
+ err := self.c.Git().Sync.FastForward(
+ task, branch.Name, branch.UpstreamRemote, branch.UpstreamBranch,
+ )
if err != nil {
_ = self.c.Error(err)
}
@@ -455,6 +467,20 @@ func (self *BranchesController) fastForward(branch *models.Branch) error {
})
}
+func (self *BranchesController) worktreePathForBranch(branch *models.Branch) string {
+ worktreeForRef, ok := self.worktreeForBranch(branch)
+ if ok {
+ return worktreeForRef.Path
+ }
+
+ dir, err := os.Getwd()
+ if err != nil {
+ // swallow for now
+ return ""
+ }
+ return dir
+}
+
func (self *BranchesController) createTag(branch *models.Branch) error {
return self.c.Helpers().Tags.OpenCreateTagPrompt(branch.FullRefName(), func() {})
}
diff --git a/pkg/integration/components/shell.go b/pkg/integration/components/shell.go
index bfa82c45e..741135e2f 100644
--- a/pkg/integration/components/shell.go
+++ b/pkg/integration/components/shell.go
@@ -261,6 +261,13 @@ func (self *Shell) AddWorktree(base string, path string, newBranchName string) *
})
}
+// add worktree and have it checkout the base branch
+func (self *Shell) AddWorktreeCheckout(base string, path string) *Shell {
+ return self.RunCommand([]string{
+ "git", "worktree", "add", path, base,
+ })
+}
+
func (self *Shell) AddFileInWorktree(worktreePath string) *Shell {
self.CreateFile(filepath.Join(worktreePath, "content"), "content")
diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go
index 0e619f8b9..981f705e2 100644
--- a/pkg/integration/tests/test_list.go
+++ b/pkg/integration/tests/test_list.go
@@ -227,6 +227,7 @@ var tests = []*components.IntegrationTest{
worktree.Crud,
worktree.CustomCommand,
worktree.DetachWorktreeFromBranch,
+ worktree.FastForwardWorktreeBranch,
worktree.ForceRemoveWorktree,
worktree.Rebase,
worktree.RemoveWorktreeFromBranch,
diff --git a/pkg/integration/tests/worktree/fast_forward_worktree_branch.go b/pkg/integration/tests/worktree/fast_forward_worktree_branch.go
new file mode 100644
index 000000000..99d32f40a
--- /dev/null
+++ b/pkg/integration/tests/worktree/fast_forward_worktree_branch.go
@@ -0,0 +1,52 @@
+package worktree
+
+import (
+ "github.com/jesseduffield/lazygit/pkg/config"
+ . "github.com/jesseduffield/lazygit/pkg/integration/components"
+)
+
+var FastForwardWorktreeBranch = NewIntegrationTest(NewIntegrationTestArgs{
+ Description: "Fast-forward a linked worktree branch from another worktree",
+ ExtraCmdArgs: []string{},
+ Skip: false,
+ SetupConfig: func(config *config.AppConfig) {},
+ SetupRepo: func(shell *Shell) {
+ // both main and linked worktree will have changed to fast-foward
+ shell.NewBranch("mybranch")
+ shell.CreateFileAndAdd("README.md", "hello world")
+ shell.Commit("initial commit")
+ shell.EmptyCommit("two")
+ shell.EmptyCommit("three")
+ shell.NewBranch("newbranch")
+
+ shell.CloneIntoRemote("origin")
+ shell.SetBranchUpstream("mybranch", "origin/mybranch")
+ shell.SetBranchUpstream("newbranch", "origin/newbranch")
+
+ // remove the 'three' commit so that we have something to pull from the remote
+ shell.HardReset("HEAD^")
+ shell.Checkout("mybranch")
+ shell.HardReset("HEAD^")
+
+ shell.AddWorktreeCheckout("newbranch", "../linked-worktree")
+ },
+ Run: func(t *TestDriver, keys config.KeybindingConfig) {
+ t.Views().Branches().
+ Focus().
+ Lines(
+ Contains("mybranch").Contains("↓1").IsSelected(),
+ Contains("newbranch (worktree)").Contains("↓1"),
+ ).
+ Press(keys.Branches.FastForward).
+ Lines(
+ Contains("mybranch").Contains("✓").IsSelected(),
+ Contains("newbranch (worktree)").Contains("↓1"),
+ ).
+ NavigateToLine(Contains("newbranch (worktree)")).
+ Press(keys.Branches.FastForward).
+ Lines(
+ Contains("mybranch").Contains("✓"),
+ Contains("newbranch (worktree)").Contains("✓").IsSelected(),
+ )
+ },
+})