1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2024-12-12 11:15:00 +02:00

Support fastforwarding worktree

This commit is contained in:
Jesse Duffield 2023-07-24 17:16:59 +10:00
parent a313b16704
commit b3060065d9
6 changed files with 107 additions and 4 deletions

View File

@ -1,6 +1,8 @@
package git_commands package git_commands
import "strings" import (
"strings"
)
// convenience struct for building git commands. Especially useful when // convenience struct for building git commands. Especially useful when
// including conditional args // including conditional args
@ -66,6 +68,14 @@ func (self *GitCommandBuilder) GitDir(path string) *GitCommandBuilder {
return self return self
} }
func (self *GitCommandBuilder) GitDirIf(condition bool, path string) *GitCommandBuilder {
if condition {
return self.GitDir(path)
}
return self
}
func (self *GitCommandBuilder) ToArgv() []string { func (self *GitCommandBuilder) ToArgv() []string {
return append([]string{"git"}, self.args...) return append([]string{"git"}, self.args...)
} }

View File

@ -82,6 +82,7 @@ type PullOptions struct {
RemoteName string RemoteName string
BranchName string BranchName string
FastForwardOnly bool FastForwardOnly bool
WorktreeGitDir string
} }
func (self *SyncCommands) Pull(task gocui.Task, opts PullOptions) error { 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.FastForwardOnly, "--ff-only").
ArgIf(opts.RemoteName != "", opts.RemoteName). ArgIf(opts.RemoteName != "", opts.RemoteName).
ArgIf(opts.BranchName != "", opts.BranchName). ArgIf(opts.BranchName != "", opts.BranchName).
GitDirIf(opts.WorktreeGitDir != "", opts.WorktreeGitDir).
ToArgv() ToArgv()
// setting GIT_SEQUENCE_EDITOR to ':' as a way of skipping it, in case the user // 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() 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"). cmdArgs := NewGitCmd("fetch").
Arg(remoteName). Arg(remoteName).
Arg(remoteBranchName + ":" + branchName). Arg(remoteBranchName + ":" + branchName).

View File

@ -3,6 +3,7 @@ package controllers
import ( import (
"errors" "errors"
"fmt" "fmt"
"os"
"strings" "strings"
"github.com/jesseduffield/gocui" "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 { 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) 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( err := self.c.Git().Sync.Pull(
task, task,
git_commands.PullOptions{ git_commands.PullOptions{
RemoteName: branch.UpstreamRemote, RemoteName: branch.UpstreamRemote,
BranchName: branch.UpstreamBranch, BranchName: branch.UpstreamBranch,
FastForwardOnly: true, FastForwardOnly: true,
WorktreeGitDir: worktreeGitDir,
}, },
) )
if err != nil { if err != nil {
@ -444,7 +453,10 @@ func (self *BranchesController) fastForward(branch *models.Branch) error {
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC}) return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
} else { } else {
self.c.LogAction(action) 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 { if err != nil {
_ = self.c.Error(err) _ = 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 { func (self *BranchesController) createTag(branch *models.Branch) error {
return self.c.Helpers().Tags.OpenCreateTagPrompt(branch.FullRefName(), func() {}) return self.c.Helpers().Tags.OpenCreateTagPrompt(branch.FullRefName(), func() {})
} }

View File

@ -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 { func (self *Shell) AddFileInWorktree(worktreePath string) *Shell {
self.CreateFile(filepath.Join(worktreePath, "content"), "content") self.CreateFile(filepath.Join(worktreePath, "content"), "content")

View File

@ -227,6 +227,7 @@ var tests = []*components.IntegrationTest{
worktree.Crud, worktree.Crud,
worktree.CustomCommand, worktree.CustomCommand,
worktree.DetachWorktreeFromBranch, worktree.DetachWorktreeFromBranch,
worktree.FastForwardWorktreeBranch,
worktree.ForceRemoveWorktree, worktree.ForceRemoveWorktree,
worktree.Rebase, worktree.Rebase,
worktree.RemoveWorktreeFromBranch, worktree.RemoveWorktreeFromBranch,

View File

@ -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(),
)
},
})