mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-08-07 22:02:56 +03:00
stash and tags loaders
This commit is contained in:
80
pkg/commands/loaders/stash.go
Normal file
80
pkg/commands/loaders/stash.go
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
package loaders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"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"
|
||||||
|
)
|
||||||
|
|
||||||
|
type StashLoader struct {
|
||||||
|
*common.Common
|
||||||
|
cmd oscommands.ICmdObjBuilder
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewStashLoader(
|
||||||
|
common *common.Common,
|
||||||
|
cmd oscommands.ICmdObjBuilder,
|
||||||
|
) *StashLoader {
|
||||||
|
return &StashLoader{
|
||||||
|
Common: common,
|
||||||
|
cmd: cmd,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *StashLoader) GetStashEntries(filterPath string) []*models.StashEntry {
|
||||||
|
if filterPath == "" {
|
||||||
|
return self.getUnfilteredStashEntries()
|
||||||
|
}
|
||||||
|
|
||||||
|
rawString, err := self.cmd.New("git stash list --name-only").RunWithOutput()
|
||||||
|
if err != nil {
|
||||||
|
return self.getUnfilteredStashEntries()
|
||||||
|
}
|
||||||
|
stashEntries := []*models.StashEntry{}
|
||||||
|
var currentStashEntry *models.StashEntry
|
||||||
|
lines := utils.SplitLines(rawString)
|
||||||
|
isAStash := func(line string) bool { return strings.HasPrefix(line, "stash@{") }
|
||||||
|
re := regexp.MustCompile(`stash@\{(\d+)\}`)
|
||||||
|
|
||||||
|
outer:
|
||||||
|
for i := 0; i < len(lines); i++ {
|
||||||
|
if !isAStash(lines[i]) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
match := re.FindStringSubmatch(lines[i])
|
||||||
|
idx, err := strconv.Atoi(match[1])
|
||||||
|
if err != nil {
|
||||||
|
return self.getUnfilteredStashEntries()
|
||||||
|
}
|
||||||
|
currentStashEntry = self.stashEntryFromLine(lines[i], idx)
|
||||||
|
for i+1 < len(lines) && !isAStash(lines[i+1]) {
|
||||||
|
i++
|
||||||
|
if lines[i] == filterPath {
|
||||||
|
stashEntries = append(stashEntries, currentStashEntry)
|
||||||
|
continue outer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stashEntries
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *StashLoader) getUnfilteredStashEntries() []*models.StashEntry {
|
||||||
|
rawString, _ := self.cmd.New("git stash list --pretty='%gs'").RunWithOutput()
|
||||||
|
stashEntries := []*models.StashEntry{}
|
||||||
|
for i, line := range utils.SplitLines(rawString) {
|
||||||
|
stashEntries = append(stashEntries, self.stashEntryFromLine(line, i))
|
||||||
|
}
|
||||||
|
return stashEntries
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *StashLoader) stashEntryFromLine(line string, index int) *models.StashEntry {
|
||||||
|
return &models.StashEntry{
|
||||||
|
Name: line,
|
||||||
|
Index: index,
|
||||||
|
}
|
||||||
|
}
|
59
pkg/commands/loaders/stash_test.go
Normal file
59
pkg/commands/loaders/stash_test.go
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
package loaders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"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 TestGitCommandGetStashEntries(t *testing.T) {
|
||||||
|
type scenario struct {
|
||||||
|
testName string
|
||||||
|
filterPath string
|
||||||
|
runner oscommands.ICmdObjRunner
|
||||||
|
expectedStashEntries []*models.StashEntry
|
||||||
|
}
|
||||||
|
|
||||||
|
scenarios := []scenario{
|
||||||
|
{
|
||||||
|
"No stash entries found",
|
||||||
|
"",
|
||||||
|
oscommands.NewFakeRunner(t).
|
||||||
|
Expect(`git stash list --pretty='%gs'`, "", nil),
|
||||||
|
[]*models.StashEntry{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Several stash entries found",
|
||||||
|
"",
|
||||||
|
oscommands.NewFakeRunner(t).
|
||||||
|
Expect(
|
||||||
|
`git stash list --pretty='%gs'`,
|
||||||
|
"WIP on add-pkg-commands-test: 55c6af2 increase parallel build\nWIP on master: bb86a3f update github template",
|
||||||
|
nil,
|
||||||
|
),
|
||||||
|
[]*models.StashEntry{
|
||||||
|
{
|
||||||
|
Index: 0,
|
||||||
|
Name: "WIP on add-pkg-commands-test: 55c6af2 increase parallel build",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Index: 1,
|
||||||
|
Name: "WIP on master: bb86a3f update github template",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range scenarios {
|
||||||
|
t.Run(s.testName, func(t *testing.T) {
|
||||||
|
cmd := oscommands.NewDummyCmdObjBuilder(s.runner)
|
||||||
|
|
||||||
|
loader := NewStashLoader(utils.NewDummyCommon(), cmd)
|
||||||
|
|
||||||
|
assert.EqualValues(t, s.expectedStashEntries, loader.GetStashEntries(""))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@@ -1,16 +1,33 @@
|
|||||||
package commands
|
package loaders
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"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"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *GitCommand) GetTags() ([]*models.Tag, error) {
|
type TagLoader struct {
|
||||||
|
*common.Common
|
||||||
|
cmd oscommands.ICmdObjBuilder
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTagLoader(
|
||||||
|
common *common.Common,
|
||||||
|
cmd oscommands.ICmdObjBuilder,
|
||||||
|
) *TagLoader {
|
||||||
|
return &TagLoader{
|
||||||
|
Common: common,
|
||||||
|
cmd: cmd,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *TagLoader) GetTags() ([]*models.Tag, error) {
|
||||||
// get remote branches, sorted by creation date (descending)
|
// get remote branches, sorted by creation date (descending)
|
||||||
// see: https://git-scm.com/docs/git-tag#Documentation/git-tag.txt---sortltkeygt
|
// see: https://git-scm.com/docs/git-tag#Documentation/git-tag.txt---sortltkeygt
|
||||||
remoteBranchesStr, err := c.Cmd.New(`git tag --list --sort=-creatordate`).RunWithOutput()
|
remoteBranchesStr, err := self.cmd.New(`git tag --list --sort=-creatordate`).RunWithOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
@@ -1,64 +0,0 @@
|
|||||||
package commands
|
|
||||||
|
|
||||||
import (
|
|
||||||
"regexp"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *GitCommand) getUnfilteredStashEntries() []*models.StashEntry {
|
|
||||||
rawString, _ := c.Cmd.New("git stash list --pretty='%gs'").RunWithOutput()
|
|
||||||
stashEntries := []*models.StashEntry{}
|
|
||||||
for i, line := range utils.SplitLines(rawString) {
|
|
||||||
stashEntries = append(stashEntries, stashEntryFromLine(line, i))
|
|
||||||
}
|
|
||||||
return stashEntries
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetStashEntries stash entries
|
|
||||||
func (c *GitCommand) GetStashEntries(filterPath string) []*models.StashEntry {
|
|
||||||
if filterPath == "" {
|
|
||||||
return c.getUnfilteredStashEntries()
|
|
||||||
}
|
|
||||||
|
|
||||||
rawString, err := c.Cmd.New("git stash list --name-only").RunWithOutput()
|
|
||||||
if err != nil {
|
|
||||||
return c.getUnfilteredStashEntries()
|
|
||||||
}
|
|
||||||
stashEntries := []*models.StashEntry{}
|
|
||||||
var currentStashEntry *models.StashEntry
|
|
||||||
lines := utils.SplitLines(rawString)
|
|
||||||
isAStash := func(line string) bool { return strings.HasPrefix(line, "stash@{") }
|
|
||||||
re := regexp.MustCompile(`stash@\{(\d+)\}`)
|
|
||||||
|
|
||||||
outer:
|
|
||||||
for i := 0; i < len(lines); i++ {
|
|
||||||
if !isAStash(lines[i]) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
match := re.FindStringSubmatch(lines[i])
|
|
||||||
idx, err := strconv.Atoi(match[1])
|
|
||||||
if err != nil {
|
|
||||||
return c.getUnfilteredStashEntries()
|
|
||||||
}
|
|
||||||
currentStashEntry = stashEntryFromLine(lines[i], idx)
|
|
||||||
for i+1 < len(lines) && !isAStash(lines[i+1]) {
|
|
||||||
i++
|
|
||||||
if lines[i] == filterPath {
|
|
||||||
stashEntries = append(stashEntries, currentStashEntry)
|
|
||||||
continue outer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return stashEntries
|
|
||||||
}
|
|
||||||
|
|
||||||
func stashEntryFromLine(line string, index int) *models.StashEntry {
|
|
||||||
return &models.StashEntry{
|
|
||||||
Name: line,
|
|
||||||
Index: index,
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,61 +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"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TestGitCommandGetStashEntries is a function.
|
|
||||||
func TestGitCommandGetStashEntries(t *testing.T) {
|
|
||||||
type scenario struct {
|
|
||||||
testName string
|
|
||||||
command func(string, ...string) *exec.Cmd
|
|
||||||
test func([]*models.StashEntry)
|
|
||||||
}
|
|
||||||
|
|
||||||
scenarios := []scenario{
|
|
||||||
{
|
|
||||||
"No stash entries found",
|
|
||||||
func(string, ...string) *exec.Cmd {
|
|
||||||
return secureexec.Command("echo")
|
|
||||||
},
|
|
||||||
func(entries []*models.StashEntry) {
|
|
||||||
assert.Len(t, entries, 0)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Several stash entries found",
|
|
||||||
func(string, ...string) *exec.Cmd {
|
|
||||||
return secureexec.Command("echo", "WIP on add-pkg-commands-test: 55c6af2 increase parallel build\nWIP on master: bb86a3f update github template")
|
|
||||||
},
|
|
||||||
func(entries []*models.StashEntry) {
|
|
||||||
expected := []*models.StashEntry{
|
|
||||||
{
|
|
||||||
Index: 0,
|
|
||||||
Name: "WIP on add-pkg-commands-test: 55c6af2 increase parallel build",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Index: 1,
|
|
||||||
Name: "WIP on master: bb86a3f update github template",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.Len(t, entries, 2)
|
|
||||||
assert.EqualValues(t, expected, entries)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, s := range scenarios {
|
|
||||||
t.Run(s.testName, func(t *testing.T) {
|
|
||||||
gitCmd := NewDummyGitCommand()
|
|
||||||
gitCmd.OSCommand.Command = s.command
|
|
||||||
|
|
||||||
s.test(gitCmd.GetStashEntries(""))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@@ -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/utils"
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
)
|
)
|
||||||
@@ -37,7 +38,9 @@ func (gui *Gui) stashRenderToMain() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) refreshStashEntries() error {
|
func (gui *Gui) refreshStashEntries() error {
|
||||||
gui.State.StashEntries = gui.GitCommand.GetStashEntries(gui.State.Modes.Filtering.GetPath())
|
gui.State.StashEntries = loaders.
|
||||||
|
NewStashLoader(gui.Common, gui.GitCommand.Cmd).
|
||||||
|
GetStashEntries(gui.State.Modes.Filtering.GetPath())
|
||||||
|
|
||||||
return gui.State.Contexts.Stash.HandleRender()
|
return gui.State.Contexts.Stash.HandleRender()
|
||||||
}
|
}
|
||||||
|
@@ -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/utils"
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
)
|
)
|
||||||
@@ -39,7 +40,7 @@ func (gui *Gui) tagsRenderToMain() error {
|
|||||||
|
|
||||||
// this is a controller: it can't access tags directly. Or can it? It should be able to get but not set. But that's exactly what I'm doing here, setting it. but through a mutator which encapsulates the event.
|
// this is a controller: it can't access tags directly. Or can it? It should be able to get but not set. But that's exactly what I'm doing here, setting it. but through a mutator which encapsulates the event.
|
||||||
func (gui *Gui) refreshTags() error {
|
func (gui *Gui) refreshTags() error {
|
||||||
tags, err := gui.GitCommand.GetTags()
|
tags, err := loaders.NewTagLoader(gui.Common, gui.GitCommand.Cmd).GetTags()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return gui.surfaceError(err)
|
return gui.surfaceError(err)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user