mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-06-15 00:15:32 +02:00
WIP
This commit is contained in:
@ -127,9 +127,12 @@ type MergeOpts struct {
|
|||||||
|
|
||||||
// Merge merge
|
// Merge merge
|
||||||
func (c *GitCommand) Merge(branchName string, opts MergeOpts) error {
|
func (c *GitCommand) Merge(branchName string, opts MergeOpts) error {
|
||||||
mergeArgs := c.UserConfig.Git.Merging.Args
|
mergeArg := ""
|
||||||
|
if c.UserConfig.Git.Merging.Args != "" {
|
||||||
|
mergeArg = " " + c.UserConfig.Git.Merging.Args
|
||||||
|
}
|
||||||
|
|
||||||
command := fmt.Sprintf("git merge --no-edit %s %s", mergeArgs, c.OSCommand.Quote(branchName))
|
command := fmt.Sprintf("git merge --no-edit%s %s", mergeArg, c.OSCommand.Quote(branchName))
|
||||||
if opts.FastForwardOnly {
|
if opts.FastForwardOnly {
|
||||||
command = fmt.Sprintf("%s --ff-only", command)
|
command = fmt.Sprintf("%s --ff-only", command)
|
||||||
}
|
}
|
||||||
|
@ -1,120 +1,85 @@
|
|||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os/exec"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/secureexec"
|
"github.com/go-errors/errors"
|
||||||
"github.com/jesseduffield/lazygit/pkg/test"
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestGitCommandGetCommitDifferences is a function.
|
|
||||||
func TestGitCommandGetCommitDifferences(t *testing.T) {
|
func TestGitCommandGetCommitDifferences(t *testing.T) {
|
||||||
type scenario struct {
|
type scenario struct {
|
||||||
testName string
|
testName string
|
||||||
command func(string, ...string) *exec.Cmd
|
runner *oscommands.FakeCmdObjRunner
|
||||||
test func(string, string)
|
expectedPushables string
|
||||||
|
expectedPullables string
|
||||||
}
|
}
|
||||||
|
|
||||||
scenarios := []scenario{
|
scenarios := []scenario{
|
||||||
{
|
{
|
||||||
"Can't retrieve pushable count",
|
"Can't retrieve pushable count",
|
||||||
func(string, ...string) *exec.Cmd {
|
oscommands.NewFakeRunner(t).
|
||||||
return secureexec.Command("test")
|
Expect("git rev-list @{u}..HEAD --count", "", errors.New("error")),
|
||||||
},
|
"?", "?",
|
||||||
func(pushableCount string, pullableCount string) {
|
|
||||||
assert.EqualValues(t, "?", pushableCount)
|
|
||||||
assert.EqualValues(t, "?", pullableCount)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Can't retrieve pullable count",
|
"Can't retrieve pullable count",
|
||||||
func(cmd string, args ...string) *exec.Cmd {
|
oscommands.NewFakeRunner(t).
|
||||||
if args[1] == "HEAD..@{u}" {
|
Expect("git rev-list @{u}..HEAD --count", "1\n", nil).
|
||||||
return secureexec.Command("test")
|
Expect("git rev-list HEAD..@{u} --count", "", errors.New("error")),
|
||||||
}
|
"?", "?",
|
||||||
|
|
||||||
return secureexec.Command("echo")
|
|
||||||
},
|
|
||||||
func(pushableCount string, pullableCount string) {
|
|
||||||
assert.EqualValues(t, "?", pushableCount)
|
|
||||||
assert.EqualValues(t, "?", pullableCount)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Retrieve pullable and pushable count",
|
"Retrieve pullable and pushable count",
|
||||||
func(cmd string, args ...string) *exec.Cmd {
|
oscommands.NewFakeRunner(t).
|
||||||
if args[1] == "HEAD..@{u}" {
|
Expect("git rev-list @{u}..HEAD --count", "1\n", nil).
|
||||||
return secureexec.Command("echo", "10")
|
Expect("git rev-list HEAD..@{u} --count", "2\n", nil),
|
||||||
}
|
"1", "2",
|
||||||
|
|
||||||
return secureexec.Command("echo", "11")
|
|
||||||
},
|
|
||||||
func(pushableCount string, pullableCount string) {
|
|
||||||
assert.EqualValues(t, "11", pushableCount)
|
|
||||||
assert.EqualValues(t, "10", pullableCount)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, s := range scenarios {
|
for _, s := range scenarios {
|
||||||
t.Run(s.testName, func(t *testing.T) {
|
t.Run(s.testName, func(t *testing.T) {
|
||||||
gitCmd := NewDummyGitCommand()
|
gitCmd := NewDummyGitCommandWithRunner(s.runner)
|
||||||
gitCmd.OSCommand.Command = s.command
|
pushables, pullables := gitCmd.GetCommitDifferences("HEAD", "@{u}")
|
||||||
s.test(gitCmd.GetCommitDifferences("HEAD", "@{u}"))
|
assert.EqualValues(t, s.expectedPushables, pushables)
|
||||||
|
assert.EqualValues(t, s.expectedPullables, pullables)
|
||||||
|
s.runner.CheckForMissingCalls()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestGitCommandNewBranch is a function.
|
|
||||||
func TestGitCommandNewBranch(t *testing.T) {
|
func TestGitCommandNewBranch(t *testing.T) {
|
||||||
gitCmd := NewDummyGitCommand()
|
runner := oscommands.NewFakeRunner(t).
|
||||||
gitCmd.OSCommand.Command = func(cmd string, args ...string) *exec.Cmd {
|
Expect(`git checkout -b "test" "master"`, "", nil)
|
||||||
assert.EqualValues(t, "git", cmd)
|
gitCmd := NewDummyGitCommandWithRunner(runner)
|
||||||
assert.EqualValues(t, []string{"checkout", "-b", "test", "master"}, args)
|
|
||||||
|
|
||||||
return secureexec.Command("echo")
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.NoError(t, gitCmd.NewBranch("test", "master"))
|
assert.NoError(t, gitCmd.NewBranch("test", "master"))
|
||||||
|
runner.CheckForMissingCalls()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestGitCommandDeleteBranch is a function.
|
|
||||||
func TestGitCommandDeleteBranch(t *testing.T) {
|
func TestGitCommandDeleteBranch(t *testing.T) {
|
||||||
type scenario struct {
|
type scenario struct {
|
||||||
testName string
|
testName string
|
||||||
branch string
|
|
||||||
force bool
|
force bool
|
||||||
command func(string, ...string) *exec.Cmd
|
runner *oscommands.FakeCmdObjRunner
|
||||||
test func(error)
|
test func(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
scenarios := []scenario{
|
scenarios := []scenario{
|
||||||
{
|
{
|
||||||
"Delete a branch",
|
"Delete a branch",
|
||||||
"test",
|
|
||||||
false,
|
false,
|
||||||
func(cmd string, args ...string) *exec.Cmd {
|
oscommands.NewFakeRunner(t).Expect(`git branch -d "test"`, "", nil),
|
||||||
assert.EqualValues(t, "git", cmd)
|
|
||||||
assert.EqualValues(t, []string{"branch", "-d", "test"}, args)
|
|
||||||
|
|
||||||
return secureexec.Command("echo")
|
|
||||||
},
|
|
||||||
func(err error) {
|
func(err error) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Force delete a branch",
|
"Force delete a branch",
|
||||||
"test",
|
|
||||||
true,
|
true,
|
||||||
func(cmd string, args ...string) *exec.Cmd {
|
oscommands.NewFakeRunner(t).Expect(`git branch -D "test"`, "", nil),
|
||||||
assert.EqualValues(t, "git", cmd)
|
|
||||||
assert.EqualValues(t, []string{"branch", "-D", "test"}, args)
|
|
||||||
|
|
||||||
return secureexec.Command("echo")
|
|
||||||
},
|
|
||||||
func(err error) {
|
func(err error) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
},
|
},
|
||||||
@ -123,31 +88,27 @@ func TestGitCommandDeleteBranch(t *testing.T) {
|
|||||||
|
|
||||||
for _, s := range scenarios {
|
for _, s := range scenarios {
|
||||||
t.Run(s.testName, func(t *testing.T) {
|
t.Run(s.testName, func(t *testing.T) {
|
||||||
gitCmd := NewDummyGitCommand()
|
gitCmd := NewDummyGitCommandWithRunner(s.runner)
|
||||||
gitCmd.OSCommand.Command = s.command
|
|
||||||
s.test(gitCmd.DeleteBranch(s.branch, s.force))
|
s.test(gitCmd.DeleteBranch("test", s.force))
|
||||||
|
s.runner.CheckForMissingCalls()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestGitCommandMerge is a function.
|
|
||||||
func TestGitCommandMerge(t *testing.T) {
|
func TestGitCommandMerge(t *testing.T) {
|
||||||
gitCmd := NewDummyGitCommand()
|
runner := oscommands.NewFakeRunner(t).
|
||||||
gitCmd.OSCommand.Command = func(cmd string, args ...string) *exec.Cmd {
|
Expect(`git merge --no-edit "test"`, "", nil)
|
||||||
assert.EqualValues(t, "git", cmd)
|
gitCmd := NewDummyGitCommandWithRunner(runner)
|
||||||
assert.EqualValues(t, []string{"merge", "--no-edit", "test"}, args)
|
|
||||||
|
|
||||||
return secureexec.Command("echo")
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.NoError(t, gitCmd.Merge("test", MergeOpts{}))
|
assert.NoError(t, gitCmd.Merge("test", MergeOpts{}))
|
||||||
|
runner.CheckForMissingCalls()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestGitCommandCheckout is a function.
|
|
||||||
func TestGitCommandCheckout(t *testing.T) {
|
func TestGitCommandCheckout(t *testing.T) {
|
||||||
type scenario struct {
|
type scenario struct {
|
||||||
testName string
|
testName string
|
||||||
command func(string, ...string) *exec.Cmd
|
runner *oscommands.FakeCmdObjRunner
|
||||||
test func(error)
|
test func(error)
|
||||||
force bool
|
force bool
|
||||||
}
|
}
|
||||||
@ -155,12 +116,7 @@ func TestGitCommandCheckout(t *testing.T) {
|
|||||||
scenarios := []scenario{
|
scenarios := []scenario{
|
||||||
{
|
{
|
||||||
"Checkout",
|
"Checkout",
|
||||||
func(cmd string, args ...string) *exec.Cmd {
|
oscommands.NewFakeRunner(t).Expect(`git checkout "test"`, "", nil),
|
||||||
assert.EqualValues(t, "git", cmd)
|
|
||||||
assert.EqualValues(t, []string{"checkout", "test"}, args)
|
|
||||||
|
|
||||||
return secureexec.Command("echo")
|
|
||||||
},
|
|
||||||
func(err error) {
|
func(err error) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
},
|
},
|
||||||
@ -168,12 +124,7 @@ func TestGitCommandCheckout(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Checkout forced",
|
"Checkout forced",
|
||||||
func(cmd string, args ...string) *exec.Cmd {
|
oscommands.NewFakeRunner(t).Expect(`git checkout --force "test"`, "", nil),
|
||||||
assert.EqualValues(t, "git", cmd)
|
|
||||||
assert.EqualValues(t, []string{"checkout", "--force", "test"}, args)
|
|
||||||
|
|
||||||
return secureexec.Command("echo")
|
|
||||||
},
|
|
||||||
func(err error) {
|
func(err error) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
},
|
},
|
||||||
@ -183,52 +134,43 @@ func TestGitCommandCheckout(t *testing.T) {
|
|||||||
|
|
||||||
for _, s := range scenarios {
|
for _, s := range scenarios {
|
||||||
t.Run(s.testName, func(t *testing.T) {
|
t.Run(s.testName, func(t *testing.T) {
|
||||||
gitCmd := NewDummyGitCommand()
|
gitCmd := NewDummyGitCommandWithRunner(s.runner)
|
||||||
gitCmd.OSCommand.Command = s.command
|
|
||||||
s.test(gitCmd.Checkout("test", CheckoutOptions{Force: s.force}))
|
s.test(gitCmd.Checkout("test", CheckoutOptions{Force: s.force}))
|
||||||
|
s.runner.CheckForMissingCalls()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestGitCommandGetBranchGraph is a function.
|
|
||||||
func TestGitCommandGetBranchGraph(t *testing.T) {
|
func TestGitCommandGetBranchGraph(t *testing.T) {
|
||||||
gitCmd := NewDummyGitCommand()
|
runner := oscommands.NewFakeRunner(t).ExpectArgs([]string{
|
||||||
gitCmd.OSCommand.Command = func(cmd string, args ...string) *exec.Cmd {
|
"git", "log", "--graph", "--color=always", "--abbrev-commit", "--decorate", "--date=relative", "--pretty=medium", "test", "--",
|
||||||
assert.EqualValues(t, "git", cmd)
|
}, "", nil)
|
||||||
assert.EqualValues(t, []string{"log", "--graph", "--color=always", "--abbrev-commit", "--decorate", "--date=relative", "--pretty=medium", "test", "--"}, args)
|
gitCmd := NewDummyGitCommandWithRunner(runner)
|
||||||
return secureexec.Command("echo")
|
|
||||||
}
|
|
||||||
_, err := gitCmd.GetBranchGraph("test")
|
_, err := gitCmd.GetBranchGraph("test")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGitCommandGetAllBranchGraph(t *testing.T) {
|
func TestGitCommandGetAllBranchGraph(t *testing.T) {
|
||||||
gitCmd := NewDummyGitCommand()
|
runner := oscommands.NewFakeRunner(t).ExpectArgs([]string{
|
||||||
gitCmd.OSCommand.Command = func(cmd string, args ...string) *exec.Cmd {
|
"git", "log", "--graph", "--all", "--color=always", "--abbrev-commit", "--decorate", "--date=relative", "--pretty=medium",
|
||||||
assert.EqualValues(t, "git", cmd)
|
}, "", nil)
|
||||||
assert.EqualValues(t, []string{"log", "--graph", "--all", "--color=always", "--abbrev-commit", "--decorate", "--date=relative", "--pretty=medium"}, args)
|
gitCmd := NewDummyGitCommandWithRunner(runner)
|
||||||
return secureexec.Command("echo")
|
|
||||||
}
|
|
||||||
cmdStr := gitCmd.UserConfig.Git.AllBranchesLogCmd
|
cmdStr := gitCmd.UserConfig.Git.AllBranchesLogCmd
|
||||||
_, err := gitCmd.Cmd.New(cmdStr).RunWithOutput()
|
_, err := gitCmd.Cmd.New(cmdStr).RunWithOutput()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestGitCommandCurrentBranchName is a function.
|
|
||||||
func TestGitCommandCurrentBranchName(t *testing.T) {
|
func TestGitCommandCurrentBranchName(t *testing.T) {
|
||||||
type scenario struct {
|
type scenario struct {
|
||||||
testName string
|
testName string
|
||||||
command func(string, ...string) *exec.Cmd
|
runner *oscommands.FakeCmdObjRunner
|
||||||
test func(string, string, error)
|
test func(string, string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
scenarios := []scenario{
|
scenarios := []scenario{
|
||||||
{
|
{
|
||||||
"says we are on the master branch if we are",
|
"says we are on the master branch if we are",
|
||||||
func(cmd string, args ...string) *exec.Cmd {
|
oscommands.NewFakeRunner(t).Expect(`git symbolic-ref --short HEAD`, "master", nil),
|
||||||
assert.Equal(t, "git", cmd)
|
|
||||||
return secureexec.Command("echo", "master")
|
|
||||||
},
|
|
||||||
func(name string, displayname string, err error) {
|
func(name string, displayname string, err error) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.EqualValues(t, "master", name)
|
assert.EqualValues(t, "master", name)
|
||||||
@ -237,20 +179,9 @@ func TestGitCommandCurrentBranchName(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"falls back to git `git branch --contains` if symbolic-ref fails",
|
"falls back to git `git branch --contains` if symbolic-ref fails",
|
||||||
func(cmd string, args ...string) *exec.Cmd {
|
oscommands.NewFakeRunner(t).
|
||||||
assert.EqualValues(t, "git", cmd)
|
Expect(`git symbolic-ref --short HEAD`, "", errors.New("error")).
|
||||||
|
Expect(`git branch --contains`, "* master", nil),
|
||||||
switch args[0] {
|
|
||||||
case "symbolic-ref":
|
|
||||||
assert.EqualValues(t, []string{"symbolic-ref", "--short", "HEAD"}, args)
|
|
||||||
return secureexec.Command("test")
|
|
||||||
case "branch":
|
|
||||||
assert.EqualValues(t, []string{"branch", "--contains"}, args)
|
|
||||||
return secureexec.Command("echo", "* master")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
func(name string, displayname string, err error) {
|
func(name string, displayname string, err error) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.EqualValues(t, "master", name)
|
assert.EqualValues(t, "master", name)
|
||||||
@ -259,20 +190,9 @@ func TestGitCommandCurrentBranchName(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"handles a detached head",
|
"handles a detached head",
|
||||||
func(cmd string, args ...string) *exec.Cmd {
|
oscommands.NewFakeRunner(t).
|
||||||
assert.EqualValues(t, "git", cmd)
|
Expect(`git symbolic-ref --short HEAD`, "", errors.New("error")).
|
||||||
|
Expect(`git branch --contains`, "* (HEAD detached at 123abcd)", nil),
|
||||||
switch args[0] {
|
|
||||||
case "symbolic-ref":
|
|
||||||
assert.EqualValues(t, []string{"symbolic-ref", "--short", "HEAD"}, args)
|
|
||||||
return secureexec.Command("test")
|
|
||||||
case "branch":
|
|
||||||
assert.EqualValues(t, []string{"branch", "--contains"}, args)
|
|
||||||
return secureexec.Command("echo", "* (HEAD detached at 123abcd)")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
func(name string, displayname string, err error) {
|
func(name string, displayname string, err error) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.EqualValues(t, "123abcd", name)
|
assert.EqualValues(t, "123abcd", name)
|
||||||
@ -281,10 +201,9 @@ func TestGitCommandCurrentBranchName(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"bubbles up error if there is one",
|
"bubbles up error if there is one",
|
||||||
func(cmd string, args ...string) *exec.Cmd {
|
oscommands.NewFakeRunner(t).
|
||||||
assert.Equal(t, "git", cmd)
|
Expect(`git symbolic-ref --short HEAD`, "", errors.New("error")).
|
||||||
return secureexec.Command("test")
|
Expect(`git branch --contains`, "", errors.New("error")),
|
||||||
},
|
|
||||||
func(name string, displayname string, err error) {
|
func(name string, displayname string, err error) {
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.EqualValues(t, "", name)
|
assert.EqualValues(t, "", name)
|
||||||
@ -295,19 +214,18 @@ func TestGitCommandCurrentBranchName(t *testing.T) {
|
|||||||
|
|
||||||
for _, s := range scenarios {
|
for _, s := range scenarios {
|
||||||
t.Run(s.testName, func(t *testing.T) {
|
t.Run(s.testName, func(t *testing.T) {
|
||||||
gitCmd := NewDummyGitCommand()
|
gitCmd := NewDummyGitCommandWithRunner(s.runner)
|
||||||
gitCmd.OSCommand.Command = s.command
|
|
||||||
s.test(gitCmd.CurrentBranchName())
|
s.test(gitCmd.CurrentBranchName())
|
||||||
|
s.runner.CheckForMissingCalls()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestGitCommandResetHard is a function.
|
|
||||||
func TestGitCommandResetHard(t *testing.T) {
|
func TestGitCommandResetHard(t *testing.T) {
|
||||||
type scenario struct {
|
type scenario struct {
|
||||||
testName string
|
testName string
|
||||||
ref string
|
ref string
|
||||||
command func(string, ...string) *exec.Cmd
|
runner *oscommands.FakeCmdObjRunner
|
||||||
test func(error)
|
test func(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,23 +233,17 @@ func TestGitCommandResetHard(t *testing.T) {
|
|||||||
{
|
{
|
||||||
"valid case",
|
"valid case",
|
||||||
"HEAD",
|
"HEAD",
|
||||||
test.CreateMockCommand(t, []*test.CommandSwapper{
|
oscommands.NewFakeRunner(t).
|
||||||
{
|
Expect(`git reset --hard "HEAD"`, "", nil),
|
||||||
Expect: `git reset --hard HEAD`,
|
|
||||||
Replace: "echo",
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
func(err error) {
|
func(err error) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
gitCmd := NewDummyGitCommand()
|
|
||||||
|
|
||||||
for _, s := range scenarios {
|
for _, s := range scenarios {
|
||||||
t.Run(s.testName, func(t *testing.T) {
|
t.Run(s.testName, func(t *testing.T) {
|
||||||
gitCmd.OSCommand.Command = s.command
|
gitCmd := NewDummyGitCommandWithRunner(s.runner)
|
||||||
s.test(gitCmd.ResetHard(s.ref))
|
s.test(gitCmd.ResetHard(s.ref))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -23,3 +23,12 @@ func NewDummyGitCommandWithOSCommand(osCommand *oscommands.OSCommand) *GitComman
|
|||||||
GetCmdWriter: func() io.Writer { return ioutil.Discard },
|
GetCmdWriter: func() io.Writer { return ioutil.Discard },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewDummyGitCommandWithRunner(runner oscommands.ICmdObjRunner) *GitCommand {
|
||||||
|
builder := oscommands.NewDummyCmdObjBuilder(runner)
|
||||||
|
gitCommand := NewDummyGitCommand()
|
||||||
|
gitCommand.Cmd = builder
|
||||||
|
gitCommand.OSCommand.Cmd = builder
|
||||||
|
|
||||||
|
return gitCommand
|
||||||
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-errors/errors"
|
"github.com/go-errors/errors"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/commands/loaders"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/filetree"
|
"github.com/jesseduffield/lazygit/pkg/gui/filetree"
|
||||||
@ -75,7 +76,10 @@ func (c *GitCommand) BeforeAndAfterFileForRename(file *models.File) (*models.Fil
|
|||||||
// all files, passing the --no-renames flag and then recursively call the function
|
// all files, passing the --no-renames flag and then recursively call the function
|
||||||
// again for the before file and after file.
|
// again for the before file and after file.
|
||||||
|
|
||||||
filesWithoutRenames := c.GetStatusFiles(GetStatusFileOptions{NoRenames: true})
|
filesWithoutRenames := loaders.
|
||||||
|
NewFileLoader(c.Common, c.Cmd, c.GitConfig).
|
||||||
|
GetStatusFiles(loaders.GetStatusFileOptions{NoRenames: true})
|
||||||
|
|
||||||
var beforeFile *models.File
|
var beforeFile *models.File
|
||||||
var afterFile *models.File
|
var afterFile *models.File
|
||||||
for _, f := range filesWithoutRenames {
|
for _, f := range filesWithoutRenames {
|
||||||
|
@ -223,3 +223,11 @@ func findDotGitDir(stat func(string) (os.FileInfo, error), readFile func(filenam
|
|||||||
func VerifyInGitRepo(osCommand *oscommands.OSCommand) error {
|
func VerifyInGitRepo(osCommand *oscommands.OSCommand) error {
|
||||||
return osCommand.Cmd.New("git rev-parse --git-dir").Run()
|
return osCommand.Cmd.New("git rev-parse --git-dir").Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *GitCommand) GetDotGitDir() string {
|
||||||
|
return c.DotGitDir
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *GitCommand) GetCmd() oscommands.ICmdObjBuilder {
|
||||||
|
return c.Cmd
|
||||||
|
}
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/common"
|
"github.com/jesseduffield/lazygit/pkg/common"
|
||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
@ -29,9 +28,14 @@ type BranchLoader struct {
|
|||||||
reflogCommits []*models.Commit
|
reflogCommits []*models.Commit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BranchLoaderGitCommand interface {
|
||||||
|
GetRawBranches() (string, error)
|
||||||
|
CurrentBranchName() (string, string, error)
|
||||||
|
}
|
||||||
|
|
||||||
func NewBranchLoader(
|
func NewBranchLoader(
|
||||||
cmn *common.Common,
|
cmn *common.Common,
|
||||||
gitCommand *commands.GitCommand,
|
gitCommand BranchLoaderGitCommand,
|
||||||
reflogCommits []*models.Commit,
|
reflogCommits []*models.Commit,
|
||||||
) *BranchLoader {
|
) *BranchLoader {
|
||||||
return &BranchLoader{
|
return &BranchLoader{
|
||||||
@ -43,10 +47,10 @@ func NewBranchLoader(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load the list of branches for the current repo
|
// Load the list of branches for the current repo
|
||||||
func (b *BranchLoader) Load() []*models.Branch {
|
func (self *BranchLoader) Load() []*models.Branch {
|
||||||
branches := b.obtainBranches()
|
branches := self.obtainBranches()
|
||||||
|
|
||||||
reflogBranches := b.obtainReflogBranches()
|
reflogBranches := self.obtainReflogBranches()
|
||||||
|
|
||||||
// loop through reflog branches. If there is a match, merge them, then remove it from the branches and keep it in the reflog branches
|
// loop through reflog branches. If there is a match, merge them, then remove it from the branches and keep it in the reflog branches
|
||||||
branchesWithRecency := make([]*models.Branch, 0)
|
branchesWithRecency := make([]*models.Branch, 0)
|
||||||
@ -78,7 +82,7 @@ outer:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !foundHead {
|
if !foundHead {
|
||||||
currentBranchName, currentBranchDisplayName, err := b.getCurrentBranchName()
|
currentBranchName, currentBranchDisplayName, err := self.getCurrentBranchName()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -87,8 +91,8 @@ outer:
|
|||||||
return branches
|
return branches
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BranchLoader) obtainBranches() []*models.Branch {
|
func (self *BranchLoader) obtainBranches() []*models.Branch {
|
||||||
output, err := b.getRawBranches()
|
output, err := self.getRawBranches()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -150,11 +154,11 @@ func (b *BranchLoader) obtainBranches() []*models.Branch {
|
|||||||
|
|
||||||
// TODO: only look at the new reflog commits, and otherwise store the recencies in
|
// TODO: only look at the new reflog commits, and otherwise store the recencies in
|
||||||
// int form against the branch to recalculate the time ago
|
// int form against the branch to recalculate the time ago
|
||||||
func (b *BranchLoader) obtainReflogBranches() []*models.Branch {
|
func (self *BranchLoader) obtainReflogBranches() []*models.Branch {
|
||||||
foundBranchesMap := map[string]bool{}
|
foundBranchesMap := map[string]bool{}
|
||||||
re := regexp.MustCompile(`checkout: moving from ([\S]+) to ([\S]+)`)
|
re := regexp.MustCompile(`checkout: moving from ([\S]+) to ([\S]+)`)
|
||||||
reflogBranches := make([]*models.Branch, 0, len(b.reflogCommits))
|
reflogBranches := make([]*models.Branch, 0, len(self.reflogCommits))
|
||||||
for _, commit := range b.reflogCommits {
|
for _, commit := range self.reflogCommits {
|
||||||
if match := re.FindStringSubmatch(commit.Name); len(match) == 3 {
|
if match := re.FindStringSubmatch(commit.Name); len(match) == 3 {
|
||||||
recency := utils.UnixToTimeAgo(commit.UnixTimestamp)
|
recency := utils.UnixToTimeAgo(commit.UnixTimestamp)
|
||||||
for _, branchName := range match[1:] {
|
for _, branchName := range match[1:] {
|
||||||
|
57
pkg/commands/loaders/commit_files.go
Normal file
57
pkg/commands/loaders/commit_files.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package loaders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CommitFileLoader struct {
|
||||||
|
*common.Common
|
||||||
|
cmd oscommands.ICmdObjBuilder
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCommitFileLoader(common *common.Common, cmd oscommands.ICmdObjBuilder) *CommitFileLoader {
|
||||||
|
return &CommitFileLoader{
|
||||||
|
Common: common,
|
||||||
|
cmd: cmd,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFilesInDiff get the specified commit files
|
||||||
|
func (self *CommitFileLoader) GetFilesInDiff(from string, to string, reverse bool) ([]*models.CommitFile, error) {
|
||||||
|
reverseFlag := ""
|
||||||
|
if reverse {
|
||||||
|
reverseFlag = " -R "
|
||||||
|
}
|
||||||
|
|
||||||
|
filenames, err := self.cmd.New(fmt.Sprintf("git diff --submodule --no-ext-diff --name-status -z --no-renames %s %s %s", reverseFlag, from, to)).RunWithOutput()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.getCommitFilesFromFilenames(filenames), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// filenames string is something like "file1\nfile2\nfile3"
|
||||||
|
func (self *CommitFileLoader) getCommitFilesFromFilenames(filenames string) []*models.CommitFile {
|
||||||
|
commitFiles := make([]*models.CommitFile, 0)
|
||||||
|
|
||||||
|
lines := strings.Split(strings.TrimRight(filenames, "\x00"), "\x00")
|
||||||
|
n := len(lines)
|
||||||
|
for i := 0; i < n-1; i += 2 {
|
||||||
|
// typical result looks like 'A my_file' meaning my_file was added
|
||||||
|
changeStatus := lines[i]
|
||||||
|
name := lines[i+1]
|
||||||
|
|
||||||
|
commitFiles = append(commitFiles, &models.CommitFile{
|
||||||
|
Name: name,
|
||||||
|
ChangeStatus: changeStatus,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return commitFiles
|
||||||
|
}
|
@ -9,7 +9,6 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
|
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
|
||||||
@ -37,20 +36,26 @@ type CommitLoader struct {
|
|||||||
dotGitDir string
|
dotGitDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CommitLoaderGitCommand interface {
|
||||||
|
CurrentBranchName() (string, string, error)
|
||||||
|
RebaseMode() (enums.RebaseMode, error)
|
||||||
|
GetCmd() oscommands.ICmdObjBuilder
|
||||||
|
GetDotGitDir() string
|
||||||
|
}
|
||||||
|
|
||||||
// making our dependencies explicit for the sake of easier testing
|
// making our dependencies explicit for the sake of easier testing
|
||||||
func NewCommitLoader(
|
func NewCommitLoader(
|
||||||
cmn *common.Common,
|
cmn *common.Common,
|
||||||
gitCommand *commands.GitCommand,
|
gitCommand CommitLoaderGitCommand,
|
||||||
osCommand *oscommands.OSCommand,
|
|
||||||
) *CommitLoader {
|
) *CommitLoader {
|
||||||
return &CommitLoader{
|
return &CommitLoader{
|
||||||
Common: cmn,
|
Common: cmn,
|
||||||
cmd: gitCommand.Cmd,
|
cmd: gitCommand.GetCmd(),
|
||||||
getCurrentBranchName: gitCommand.CurrentBranchName,
|
getCurrentBranchName: gitCommand.CurrentBranchName,
|
||||||
getRebaseMode: gitCommand.RebaseMode,
|
getRebaseMode: gitCommand.RebaseMode,
|
||||||
readFile: ioutil.ReadFile,
|
readFile: ioutil.ReadFile,
|
||||||
walkFiles: filepath.Walk,
|
walkFiles: filepath.Walk,
|
||||||
dotGitDir: gitCommand.DotGitDir,
|
dotGitDir: gitCommand.GetDotGitDir(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,7 +189,7 @@ func TestGetCommits(t *testing.T) {
|
|||||||
t.Run(scenario.testName, func(t *testing.T) {
|
t.Run(scenario.testName, func(t *testing.T) {
|
||||||
builder := &CommitLoader{
|
builder := &CommitLoader{
|
||||||
Common: utils.NewDummyCommon(),
|
Common: utils.NewDummyCommon(),
|
||||||
cmd: oscommands.NewCmdObjBuilderDummy(scenario.runner),
|
cmd: oscommands.NewDummyCmdObjBuilder(scenario.runner),
|
||||||
getCurrentBranchName: func() (string, string, error) {
|
getCurrentBranchName: func() (string, string, error) {
|
||||||
return scenario.currentBranchName, scenario.currentBranchName, nil
|
return scenario.currentBranchName, scenario.currentBranchName, nil
|
||||||
},
|
},
|
||||||
|
@ -1,36 +1,54 @@
|
|||||||
package commands
|
package loaders
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/commands/git_config"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/common"
|
||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetStatusFiles git status files
|
type FileLoader struct {
|
||||||
|
*common.Common
|
||||||
|
cmd oscommands.ICmdObjBuilder
|
||||||
|
gitConfig git_config.IGitConfig
|
||||||
|
getFileType func(string) string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFileLoader(cmn *common.Common, cmd oscommands.ICmdObjBuilder, gitConfig git_config.IGitConfig) *FileLoader {
|
||||||
|
return &FileLoader{
|
||||||
|
Common: cmn,
|
||||||
|
cmd: cmd,
|
||||||
|
gitConfig: gitConfig,
|
||||||
|
getFileType: oscommands.FileType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type GetStatusFileOptions struct {
|
type GetStatusFileOptions struct {
|
||||||
NoRenames bool
|
NoRenames bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *GitCommand) GetStatusFiles(opts GetStatusFileOptions) []*models.File {
|
func (self *FileLoader) GetStatusFiles(opts GetStatusFileOptions) []*models.File {
|
||||||
// check if config wants us ignoring untracked files
|
// check if config wants us ignoring untracked files
|
||||||
untrackedFilesSetting := c.GitConfig.Get("status.showUntrackedFiles")
|
untrackedFilesSetting := self.gitConfig.Get("status.showUntrackedFiles")
|
||||||
|
|
||||||
if untrackedFilesSetting == "" {
|
if untrackedFilesSetting == "" {
|
||||||
untrackedFilesSetting = "all"
|
untrackedFilesSetting = "all"
|
||||||
}
|
}
|
||||||
untrackedFilesArg := fmt.Sprintf("--untracked-files=%s", untrackedFilesSetting)
|
untrackedFilesArg := fmt.Sprintf("--untracked-files=%s", untrackedFilesSetting)
|
||||||
|
|
||||||
statuses, err := c.GitStatus(GitStatusOptions{NoRenames: opts.NoRenames, UntrackedFilesArg: untrackedFilesArg})
|
statuses, err := self.GitStatus(GitStatusOptions{NoRenames: opts.NoRenames, UntrackedFilesArg: untrackedFilesArg})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Log.Error(err)
|
self.Log.Error(err)
|
||||||
}
|
}
|
||||||
files := []*models.File{}
|
files := []*models.File{}
|
||||||
|
|
||||||
for _, status := range statuses {
|
for _, status := range statuses {
|
||||||
if strings.HasPrefix(status.StatusString, "warning") {
|
if strings.HasPrefix(status.StatusString, "warning") {
|
||||||
c.Log.Warningf("warning when calling git status: %s", status.StatusString)
|
self.Log.Warningf("warning when calling git status: %s", status.StatusString)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
change := status.Change
|
change := status.Change
|
||||||
@ -52,7 +70,7 @@ func (c *GitCommand) GetStatusFiles(opts GetStatusFileOptions) []*models.File {
|
|||||||
Added: unstagedChange == "A" || untracked,
|
Added: unstagedChange == "A" || untracked,
|
||||||
HasMergeConflicts: hasMergeConflicts,
|
HasMergeConflicts: hasMergeConflicts,
|
||||||
HasInlineMergeConflicts: hasInlineMergeConflicts,
|
HasInlineMergeConflicts: hasInlineMergeConflicts,
|
||||||
Type: c.OSCommand.FileType(status.Name),
|
Type: self.getFileType(status.Name),
|
||||||
ShortStatus: change,
|
ShortStatus: change,
|
||||||
}
|
}
|
||||||
files = append(files, file)
|
files = append(files, file)
|
||||||
@ -74,13 +92,13 @@ type FileStatus struct {
|
|||||||
PreviousName string
|
PreviousName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *GitCommand) GitStatus(opts GitStatusOptions) ([]FileStatus, error) {
|
func (c *FileLoader) GitStatus(opts GitStatusOptions) ([]FileStatus, error) {
|
||||||
noRenamesFlag := ""
|
noRenamesFlag := ""
|
||||||
if opts.NoRenames {
|
if opts.NoRenames {
|
||||||
noRenamesFlag = "--no-renames"
|
noRenamesFlag = " --no-renames"
|
||||||
}
|
}
|
||||||
|
|
||||||
statusLines, err := c.Cmd.New(fmt.Sprintf("git status %s --porcelain -z %s", opts.UntrackedFilesArg, noRenamesFlag)).RunWithOutput()
|
statusLines, err := c.cmd.New(fmt.Sprintf("git status %s --porcelain -z%s", opts.UntrackedFilesArg, noRenamesFlag)).RunWithOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []FileStatus{}, err
|
return []FileStatus{}, err
|
||||||
}
|
}
|
203
pkg/commands/loaders/files_test.go
Normal file
203
pkg/commands/loaders/files_test.go
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
package loaders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/commands/git_config"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGitCommandGetStatusFiles(t *testing.T) {
|
||||||
|
type scenario struct {
|
||||||
|
testName string
|
||||||
|
runner oscommands.ICmdObjRunner
|
||||||
|
expectedFiles []*models.File
|
||||||
|
}
|
||||||
|
|
||||||
|
scenarios := []scenario{
|
||||||
|
{
|
||||||
|
"No files found",
|
||||||
|
oscommands.NewFakeRunner(t).
|
||||||
|
Expect(`git status --untracked-files=yes --porcelain -z`, "", nil),
|
||||||
|
[]*models.File{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Several files found",
|
||||||
|
oscommands.NewFakeRunner(t).
|
||||||
|
Expect(
|
||||||
|
`git status --untracked-files=yes --porcelain -z`,
|
||||||
|
"MM file1.txt\x00A file3.txt\x00AM file2.txt\x00?? file4.txt\x00UU file5.txt",
|
||||||
|
nil,
|
||||||
|
),
|
||||||
|
[]*models.File{
|
||||||
|
{
|
||||||
|
Name: "file1.txt",
|
||||||
|
HasStagedChanges: true,
|
||||||
|
HasUnstagedChanges: true,
|
||||||
|
Tracked: true,
|
||||||
|
Added: false,
|
||||||
|
Deleted: false,
|
||||||
|
HasMergeConflicts: false,
|
||||||
|
HasInlineMergeConflicts: false,
|
||||||
|
DisplayString: "MM file1.txt",
|
||||||
|
Type: "file",
|
||||||
|
ShortStatus: "MM",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "file3.txt",
|
||||||
|
HasStagedChanges: true,
|
||||||
|
HasUnstagedChanges: false,
|
||||||
|
Tracked: false,
|
||||||
|
Added: true,
|
||||||
|
Deleted: false,
|
||||||
|
HasMergeConflicts: false,
|
||||||
|
HasInlineMergeConflicts: false,
|
||||||
|
DisplayString: "A file3.txt",
|
||||||
|
Type: "file",
|
||||||
|
ShortStatus: "A ",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "file2.txt",
|
||||||
|
HasStagedChanges: true,
|
||||||
|
HasUnstagedChanges: true,
|
||||||
|
Tracked: false,
|
||||||
|
Added: true,
|
||||||
|
Deleted: false,
|
||||||
|
HasMergeConflicts: false,
|
||||||
|
HasInlineMergeConflicts: false,
|
||||||
|
DisplayString: "AM file2.txt",
|
||||||
|
Type: "file",
|
||||||
|
ShortStatus: "AM",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "file4.txt",
|
||||||
|
HasStagedChanges: false,
|
||||||
|
HasUnstagedChanges: true,
|
||||||
|
Tracked: false,
|
||||||
|
Added: true,
|
||||||
|
Deleted: false,
|
||||||
|
HasMergeConflicts: false,
|
||||||
|
HasInlineMergeConflicts: false,
|
||||||
|
DisplayString: "?? file4.txt",
|
||||||
|
Type: "file",
|
||||||
|
ShortStatus: "??",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "file5.txt",
|
||||||
|
HasStagedChanges: false,
|
||||||
|
HasUnstagedChanges: true,
|
||||||
|
Tracked: true,
|
||||||
|
Added: false,
|
||||||
|
Deleted: false,
|
||||||
|
HasMergeConflicts: true,
|
||||||
|
HasInlineMergeConflicts: true,
|
||||||
|
DisplayString: "UU file5.txt",
|
||||||
|
Type: "file",
|
||||||
|
ShortStatus: "UU",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"File with new line char",
|
||||||
|
oscommands.NewFakeRunner(t).
|
||||||
|
Expect(`git status --untracked-files=yes --porcelain -z`, "MM a\nb.txt", nil),
|
||||||
|
[]*models.File{
|
||||||
|
{
|
||||||
|
Name: "a\nb.txt",
|
||||||
|
HasStagedChanges: true,
|
||||||
|
HasUnstagedChanges: true,
|
||||||
|
Tracked: true,
|
||||||
|
Added: false,
|
||||||
|
Deleted: false,
|
||||||
|
HasMergeConflicts: false,
|
||||||
|
HasInlineMergeConflicts: false,
|
||||||
|
DisplayString: "MM a\nb.txt",
|
||||||
|
Type: "file",
|
||||||
|
ShortStatus: "MM",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Renamed files",
|
||||||
|
oscommands.NewFakeRunner(t).
|
||||||
|
Expect(
|
||||||
|
`git status --untracked-files=yes --porcelain -z`,
|
||||||
|
"R after1.txt\x00before1.txt\x00RM after2.txt\x00before2.txt",
|
||||||
|
nil,
|
||||||
|
),
|
||||||
|
[]*models.File{
|
||||||
|
{
|
||||||
|
Name: "after1.txt",
|
||||||
|
PreviousName: "before1.txt",
|
||||||
|
HasStagedChanges: true,
|
||||||
|
HasUnstagedChanges: false,
|
||||||
|
Tracked: true,
|
||||||
|
Added: false,
|
||||||
|
Deleted: false,
|
||||||
|
HasMergeConflicts: false,
|
||||||
|
HasInlineMergeConflicts: false,
|
||||||
|
DisplayString: "R before1.txt -> after1.txt",
|
||||||
|
Type: "file",
|
||||||
|
ShortStatus: "R ",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "after2.txt",
|
||||||
|
PreviousName: "before2.txt",
|
||||||
|
HasStagedChanges: true,
|
||||||
|
HasUnstagedChanges: true,
|
||||||
|
Tracked: true,
|
||||||
|
Added: false,
|
||||||
|
Deleted: false,
|
||||||
|
HasMergeConflicts: false,
|
||||||
|
HasInlineMergeConflicts: false,
|
||||||
|
DisplayString: "RM before2.txt -> after2.txt",
|
||||||
|
Type: "file",
|
||||||
|
ShortStatus: "RM",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"File with arrow in name",
|
||||||
|
oscommands.NewFakeRunner(t).
|
||||||
|
Expect(
|
||||||
|
`git status --untracked-files=yes --porcelain -z`,
|
||||||
|
`?? a -> b.txt`,
|
||||||
|
nil,
|
||||||
|
),
|
||||||
|
[]*models.File{
|
||||||
|
{
|
||||||
|
Name: "a -> b.txt",
|
||||||
|
HasStagedChanges: false,
|
||||||
|
HasUnstagedChanges: true,
|
||||||
|
Tracked: false,
|
||||||
|
Added: true,
|
||||||
|
Deleted: false,
|
||||||
|
HasMergeConflicts: false,
|
||||||
|
HasInlineMergeConflicts: false,
|
||||||
|
DisplayString: "?? a -> b.txt",
|
||||||
|
Type: "file",
|
||||||
|
ShortStatus: "??",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range scenarios {
|
||||||
|
t.Run(s.testName, func(t *testing.T) {
|
||||||
|
cmd := oscommands.NewDummyCmdObjBuilder(s.runner)
|
||||||
|
gitConfig := git_config.NewFakeGitConfig(map[string]string{"status.showUntrackedFiles": "yes"})
|
||||||
|
|
||||||
|
loader := &FileLoader{
|
||||||
|
Common: utils.NewDummyCommon(),
|
||||||
|
cmd: cmd,
|
||||||
|
gitConfig: gitConfig,
|
||||||
|
getFileType: func(string) string { return "file" },
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.EqualValues(t, s.expectedFiles, loader.GetStatusFiles(GetStatusFileOptions{}))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -1,43 +0,0 @@
|
|||||||
package commands
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GetFilesInDiff get the specified commit files
|
|
||||||
func (c *GitCommand) GetFilesInDiff(from string, to string, reverse bool) ([]*models.CommitFile, error) {
|
|
||||||
reverseFlag := ""
|
|
||||||
if reverse {
|
|
||||||
reverseFlag = " -R "
|
|
||||||
}
|
|
||||||
|
|
||||||
filenames, err := c.Cmd.New(fmt.Sprintf("git diff --submodule --no-ext-diff --name-status -z --no-renames %s %s %s", reverseFlag, from, to)).RunWithOutput()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.getCommitFilesFromFilenames(filenames), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// filenames string is something like "file1\nfile2\nfile3"
|
|
||||||
func (c *GitCommand) getCommitFilesFromFilenames(filenames string) []*models.CommitFile {
|
|
||||||
commitFiles := make([]*models.CommitFile, 0)
|
|
||||||
|
|
||||||
lines := strings.Split(strings.TrimRight(filenames, "\x00"), "\x00")
|
|
||||||
n := len(lines)
|
|
||||||
for i := 0; i < n-1; i += 2 {
|
|
||||||
// typical result looks like 'A my_file' meaning my_file was added
|
|
||||||
changeStatus := lines[i]
|
|
||||||
name := lines[i+1]
|
|
||||||
|
|
||||||
commitFiles = append(commitFiles, &models.CommitFile{
|
|
||||||
Name: name,
|
|
||||||
ChangeStatus: changeStatus,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return commitFiles
|
|
||||||
}
|
|
@ -1,227 +0,0 @@
|
|||||||
package commands
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os/exec"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/secureexec"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TestGitCommandGetStatusFiles is a function.
|
|
||||||
func TestGitCommandGetStatusFiles(t *testing.T) {
|
|
||||||
type scenario struct {
|
|
||||||
testName string
|
|
||||||
command func(string, ...string) *exec.Cmd
|
|
||||||
test func([]*models.File)
|
|
||||||
}
|
|
||||||
|
|
||||||
scenarios := []scenario{
|
|
||||||
{
|
|
||||||
"No files found",
|
|
||||||
func(cmd string, args ...string) *exec.Cmd {
|
|
||||||
return secureexec.Command("echo")
|
|
||||||
},
|
|
||||||
func(files []*models.File) {
|
|
||||||
assert.Len(t, files, 0)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Several files found",
|
|
||||||
func(cmd string, args ...string) *exec.Cmd {
|
|
||||||
return secureexec.Command(
|
|
||||||
"printf",
|
|
||||||
`MM file1.txt\0A file3.txt\0AM file2.txt\0?? file4.txt\0UU file5.txt`,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
func(files []*models.File) {
|
|
||||||
assert.Len(t, files, 5)
|
|
||||||
|
|
||||||
expected := []*models.File{
|
|
||||||
{
|
|
||||||
Name: "file1.txt",
|
|
||||||
HasStagedChanges: true,
|
|
||||||
HasUnstagedChanges: true,
|
|
||||||
Tracked: true,
|
|
||||||
Added: false,
|
|
||||||
Deleted: false,
|
|
||||||
HasMergeConflicts: false,
|
|
||||||
HasInlineMergeConflicts: false,
|
|
||||||
DisplayString: "MM file1.txt",
|
|
||||||
Type: "other",
|
|
||||||
ShortStatus: "MM",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "file3.txt",
|
|
||||||
HasStagedChanges: true,
|
|
||||||
HasUnstagedChanges: false,
|
|
||||||
Tracked: false,
|
|
||||||
Added: true,
|
|
||||||
Deleted: false,
|
|
||||||
HasMergeConflicts: false,
|
|
||||||
HasInlineMergeConflicts: false,
|
|
||||||
DisplayString: "A file3.txt",
|
|
||||||
Type: "other",
|
|
||||||
ShortStatus: "A ",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "file2.txt",
|
|
||||||
HasStagedChanges: true,
|
|
||||||
HasUnstagedChanges: true,
|
|
||||||
Tracked: false,
|
|
||||||
Added: true,
|
|
||||||
Deleted: false,
|
|
||||||
HasMergeConflicts: false,
|
|
||||||
HasInlineMergeConflicts: false,
|
|
||||||
DisplayString: "AM file2.txt",
|
|
||||||
Type: "other",
|
|
||||||
ShortStatus: "AM",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "file4.txt",
|
|
||||||
HasStagedChanges: false,
|
|
||||||
HasUnstagedChanges: true,
|
|
||||||
Tracked: false,
|
|
||||||
Added: true,
|
|
||||||
Deleted: false,
|
|
||||||
HasMergeConflicts: false,
|
|
||||||
HasInlineMergeConflicts: false,
|
|
||||||
DisplayString: "?? file4.txt",
|
|
||||||
Type: "other",
|
|
||||||
ShortStatus: "??",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "file5.txt",
|
|
||||||
HasStagedChanges: false,
|
|
||||||
HasUnstagedChanges: true,
|
|
||||||
Tracked: true,
|
|
||||||
Added: false,
|
|
||||||
Deleted: false,
|
|
||||||
HasMergeConflicts: true,
|
|
||||||
HasInlineMergeConflicts: true,
|
|
||||||
DisplayString: "UU file5.txt",
|
|
||||||
Type: "other",
|
|
||||||
ShortStatus: "UU",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.EqualValues(t, expected, files)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"File with new line char",
|
|
||||||
func(cmd string, args ...string) *exec.Cmd {
|
|
||||||
return secureexec.Command(
|
|
||||||
"printf",
|
|
||||||
`MM a\nb.txt`,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
func(files []*models.File) {
|
|
||||||
assert.Len(t, files, 1)
|
|
||||||
|
|
||||||
expected := []*models.File{
|
|
||||||
{
|
|
||||||
Name: "a\nb.txt",
|
|
||||||
HasStagedChanges: true,
|
|
||||||
HasUnstagedChanges: true,
|
|
||||||
Tracked: true,
|
|
||||||
Added: false,
|
|
||||||
Deleted: false,
|
|
||||||
HasMergeConflicts: false,
|
|
||||||
HasInlineMergeConflicts: false,
|
|
||||||
DisplayString: "MM a\nb.txt",
|
|
||||||
Type: "other",
|
|
||||||
ShortStatus: "MM",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.EqualValues(t, expected, files)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Renamed files",
|
|
||||||
func(cmd string, args ...string) *exec.Cmd {
|
|
||||||
return secureexec.Command(
|
|
||||||
"printf",
|
|
||||||
`R after1.txt\0before1.txt\0RM after2.txt\0before2.txt`,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
func(files []*models.File) {
|
|
||||||
assert.Len(t, files, 2)
|
|
||||||
|
|
||||||
expected := []*models.File{
|
|
||||||
{
|
|
||||||
Name: "after1.txt",
|
|
||||||
PreviousName: "before1.txt",
|
|
||||||
HasStagedChanges: true,
|
|
||||||
HasUnstagedChanges: false,
|
|
||||||
Tracked: true,
|
|
||||||
Added: false,
|
|
||||||
Deleted: false,
|
|
||||||
HasMergeConflicts: false,
|
|
||||||
HasInlineMergeConflicts: false,
|
|
||||||
DisplayString: "R before1.txt -> after1.txt",
|
|
||||||
Type: "other",
|
|
||||||
ShortStatus: "R ",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "after2.txt",
|
|
||||||
PreviousName: "before2.txt",
|
|
||||||
HasStagedChanges: true,
|
|
||||||
HasUnstagedChanges: true,
|
|
||||||
Tracked: true,
|
|
||||||
Added: false,
|
|
||||||
Deleted: false,
|
|
||||||
HasMergeConflicts: false,
|
|
||||||
HasInlineMergeConflicts: false,
|
|
||||||
DisplayString: "RM before2.txt -> after2.txt",
|
|
||||||
Type: "other",
|
|
||||||
ShortStatus: "RM",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.EqualValues(t, expected, files)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"File with arrow in name",
|
|
||||||
func(cmd string, args ...string) *exec.Cmd {
|
|
||||||
return secureexec.Command(
|
|
||||||
"printf",
|
|
||||||
`?? a -> b.txt`,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
func(files []*models.File) {
|
|
||||||
assert.Len(t, files, 1)
|
|
||||||
|
|
||||||
expected := []*models.File{
|
|
||||||
{
|
|
||||||
Name: "a -> b.txt",
|
|
||||||
HasStagedChanges: false,
|
|
||||||
HasUnstagedChanges: true,
|
|
||||||
Tracked: false,
|
|
||||||
Added: true,
|
|
||||||
Deleted: false,
|
|
||||||
HasMergeConflicts: false,
|
|
||||||
HasInlineMergeConflicts: false,
|
|
||||||
DisplayString: "?? a -> b.txt",
|
|
||||||
Type: "other",
|
|
||||||
ShortStatus: "??",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.EqualValues(t, expected, files)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, s := range scenarios {
|
|
||||||
t.Run(s.testName, func(t *testing.T) {
|
|
||||||
gitCmd := NewDummyGitCommand()
|
|
||||||
gitCmd.OSCommand.Command = s.command
|
|
||||||
|
|
||||||
s.test(gitCmd.GetStatusFiles(GetStatusFileOptions{}))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@ -10,7 +10,7 @@ func NewDummyOSCommand() *OSCommand {
|
|||||||
return NewOSCommand(utils.NewDummyCommon())
|
return NewOSCommand(utils.NewDummyCommon())
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCmdObjBuilderDummy(runner ICmdObjRunner) ICmdObjBuilder {
|
func NewDummyCmdObjBuilder(runner ICmdObjRunner) *CmdObjBuilder {
|
||||||
return &CmdObjBuilder{
|
return &CmdObjBuilder{
|
||||||
runner: runner,
|
runner: runner,
|
||||||
logCmdObj: func(ICmdObj) {},
|
logCmdObj: func(ICmdObj) {},
|
||||||
|
@ -36,9 +36,11 @@ func (self *FakeCmdObjRunner) RunWithOutput(cmdObj ICmdObj) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
expectedCmd := self.expectedCmds[self.expectedCmdIndex]
|
expectedCmd := self.expectedCmds[self.expectedCmdIndex]
|
||||||
|
output, err := expectedCmd(cmdObj)
|
||||||
|
|
||||||
self.expectedCmdIndex++
|
self.expectedCmdIndex++
|
||||||
|
|
||||||
return expectedCmd(cmdObj)
|
return output, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *FakeCmdObjRunner) RunAndProcessLines(cmdObj ICmdObj, onLine func(line string) (bool, error)) error {
|
func (self *FakeCmdObjRunner) RunAndProcessLines(cmdObj ICmdObj, onLine func(line string) (bool, error)) error {
|
||||||
@ -72,13 +74,29 @@ func (self *FakeCmdObjRunner) ExpectFunc(fn func(cmdObj ICmdObj) (string, error)
|
|||||||
func (self *FakeCmdObjRunner) Expect(expectedCmdStr string, output string, err error) *FakeCmdObjRunner {
|
func (self *FakeCmdObjRunner) Expect(expectedCmdStr string, output string, err error) *FakeCmdObjRunner {
|
||||||
self.ExpectFunc(func(cmdObj ICmdObj) (string, error) {
|
self.ExpectFunc(func(cmdObj ICmdObj) (string, error) {
|
||||||
cmdStr := cmdObj.ToString()
|
cmdStr := cmdObj.ToString()
|
||||||
if cmdStr != expectedCmdStr {
|
assert.Equal(self.t, expectedCmdStr, cmdStr, fmt.Sprintf("expected command %d to be %s, but was %s", self.expectedCmdIndex+1, expectedCmdStr, cmdStr))
|
||||||
assert.Equal(self.t, expectedCmdStr, cmdStr, fmt.Sprintf("expected command %d to be %s, but was %s", self.expectedCmdIndex+1, expectedCmdStr, cmdStr))
|
|
||||||
return "", errors.New("expected cmd")
|
|
||||||
}
|
|
||||||
|
|
||||||
return output, err
|
return output, err
|
||||||
})
|
})
|
||||||
|
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *FakeCmdObjRunner) ExpectArgs(expectedArgs []string, output string, err error) *FakeCmdObjRunner {
|
||||||
|
self.ExpectFunc(func(cmdObj ICmdObj) (string, error) {
|
||||||
|
args := cmdObj.GetCmd().Args
|
||||||
|
assert.EqualValues(self.t, expectedArgs, args, fmt.Sprintf("command %d did not match expectation", self.expectedCmdIndex+1))
|
||||||
|
|
||||||
|
return output, err
|
||||||
|
})
|
||||||
|
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *FakeCmdObjRunner) CheckForMissingCalls() {
|
||||||
|
if self.expectedCmdIndex < len(self.expectedCmds) {
|
||||||
|
self.t.Errorf("expected command %d to be called, but was not", self.expectedCmdIndex+1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
@ -137,7 +137,7 @@ func (c *OSCommand) SetRemoveFile(f func(string) error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FileType tells us if the file is a file, directory or other
|
// FileType tells us if the file is a file, directory or other
|
||||||
func (c *OSCommand) FileType(path string) string {
|
func FileType(path string) string {
|
||||||
fileInfo, err := os.Stat(path)
|
fileInfo, err := os.Stat(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "other"
|
return "other"
|
||||||
|
@ -164,7 +164,7 @@ func TestOSCommandFileType(t *testing.T) {
|
|||||||
|
|
||||||
for _, s := range scenarios {
|
for _, s := range scenarios {
|
||||||
s.setup()
|
s.setup()
|
||||||
s.test(NewDummyOSCommand().FileType(s.path))
|
s.test(FileType(s.path))
|
||||||
_ = os.RemoveAll(s.path)
|
_ = os.RemoveAll(s.path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
package commands
|
package commands
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/commands/loaders"
|
||||||
|
)
|
||||||
|
|
||||||
// StashDo modify stash
|
// StashDo modify stash
|
||||||
func (c *GitCommand) StashDo(index int, method string) error {
|
func (c *GitCommand) StashDo(index int, method string) error {
|
||||||
@ -45,7 +49,10 @@ func (c *GitCommand) StashSaveStagedChanges(message string) error {
|
|||||||
// if you had staged an untracked file, that will now appear as 'AD' in git status
|
// if you had staged an untracked file, that will now appear as 'AD' in git status
|
||||||
// meaning it's deleted in your working tree but added in your index. Given that it's
|
// meaning it's deleted in your working tree but added in your index. Given that it's
|
||||||
// now safely stashed, we need to remove it.
|
// now safely stashed, we need to remove it.
|
||||||
files := c.GetStatusFiles(GetStatusFileOptions{})
|
files := loaders.
|
||||||
|
NewFileLoader(c.Common, c.Cmd, c.GitConfig).
|
||||||
|
GetStatusFiles(loaders.GetStatusFileOptions{})
|
||||||
|
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
if file.ShortStatus == "AD" {
|
if file.ShortStatus == "AD" {
|
||||||
if err := c.UnStageFile(file.Names(), false); err != nil {
|
if err := c.UnStageFile(file.Names(), false); err != nil {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package gui
|
package gui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/commands/loaders"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/patch"
|
"github.com/jesseduffield/lazygit/pkg/commands/patch"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/filetree"
|
"github.com/jesseduffield/lazygit/pkg/gui/filetree"
|
||||||
@ -105,7 +106,7 @@ func (gui *Gui) refreshCommitFilesView() error {
|
|||||||
to := gui.State.Panels.CommitFiles.refName
|
to := gui.State.Panels.CommitFiles.refName
|
||||||
from, reverse := gui.getFromAndReverseArgsForDiff(to)
|
from, reverse := gui.getFromAndReverseArgsForDiff(to)
|
||||||
|
|
||||||
files, err := gui.GitCommand.GetFilesInDiff(from, to, reverse)
|
files, err := loaders.NewCommitFileLoader(gui.Common, gui.GitCommand.Cmd).GetFilesInDiff(from, to, reverse)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return gui.surfaceError(err)
|
return gui.surfaceError(err)
|
||||||
}
|
}
|
||||||
|
@ -119,7 +119,7 @@ func (gui *Gui) refreshCommitsWithLimit() error {
|
|||||||
gui.Mutexes.BranchCommitsMutex.Lock()
|
gui.Mutexes.BranchCommitsMutex.Lock()
|
||||||
defer gui.Mutexes.BranchCommitsMutex.Unlock()
|
defer gui.Mutexes.BranchCommitsMutex.Unlock()
|
||||||
|
|
||||||
loader := loaders.NewCommitLoader(gui.Common, gui.GitCommand, gui.OSCommand)
|
loader := loaders.NewCommitLoader(gui.Common, gui.GitCommand)
|
||||||
|
|
||||||
commits, err := loader.GetCommits(
|
commits, err := loader.GetCommits(
|
||||||
loaders.GetCommitsOptions{
|
loaders.GetCommitsOptions{
|
||||||
@ -142,7 +142,7 @@ func (gui *Gui) refreshRebaseCommits() error {
|
|||||||
gui.Mutexes.BranchCommitsMutex.Lock()
|
gui.Mutexes.BranchCommitsMutex.Lock()
|
||||||
defer gui.Mutexes.BranchCommitsMutex.Unlock()
|
defer gui.Mutexes.BranchCommitsMutex.Unlock()
|
||||||
|
|
||||||
loader := loaders.NewCommitLoader(gui.Common, gui.GitCommand, gui.OSCommand)
|
loader := loaders.NewCommitLoader(gui.Common, gui.GitCommand)
|
||||||
|
|
||||||
updatedCommits, err := loader.MergeRebasingCommits(gui.State.Commits)
|
updatedCommits, err := loader.MergeRebasingCommits(gui.State.Commits)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/jesseduffield/gocui"
|
"github.com/jesseduffield/gocui"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands"
|
"github.com/jesseduffield/lazygit/pkg/commands"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/commands/loaders"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
"github.com/jesseduffield/lazygit/pkg/config"
|
"github.com/jesseduffield/lazygit/pkg/config"
|
||||||
@ -553,7 +554,9 @@ func (gui *Gui) refreshStateFiles() error {
|
|||||||
prevNodes := gui.State.FileManager.GetAllItems()
|
prevNodes := gui.State.FileManager.GetAllItems()
|
||||||
prevSelectedLineIdx := gui.State.Panels.Files.SelectedLineIdx
|
prevSelectedLineIdx := gui.State.Panels.Files.SelectedLineIdx
|
||||||
|
|
||||||
files := gui.GitCommand.GetStatusFiles(commands.GetStatusFileOptions{})
|
files := loaders.
|
||||||
|
NewFileLoader(gui.Common, gui.GitCommand.Cmd, gui.GitCommand.GitConfig).
|
||||||
|
GetStatusFiles(loaders.GetStatusFileOptions{})
|
||||||
|
|
||||||
// for when you stage the old file of a rename and the new file is in a collapsed dir
|
// for when you stage the old file of a rename and the new file is in a collapsed dir
|
||||||
state.FileManager.RWMutex.Lock()
|
state.FileManager.RWMutex.Lock()
|
||||||
|
@ -75,7 +75,7 @@ func (gui *Gui) handleViewSubCommitFiles() error {
|
|||||||
|
|
||||||
func (gui *Gui) switchToSubCommitsContext(refName string) error {
|
func (gui *Gui) switchToSubCommitsContext(refName string) error {
|
||||||
// need to populate my sub commits
|
// need to populate my sub commits
|
||||||
loader := loaders.NewCommitLoader(gui.Common, gui.GitCommand, gui.OSCommand)
|
loader := loaders.NewCommitLoader(gui.Common, gui.GitCommand)
|
||||||
|
|
||||||
commits, err := loader.GetCommits(
|
commits, err := loader.GetCommits(
|
||||||
loaders.GetCommitsOptions{
|
loaders.GetCommitsOptions{
|
||||||
|
Reference in New Issue
Block a user