mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-03-05 15:15:49 +02:00
refactor
This commit is contained in:
parent
9e67f74ca3
commit
d5639e6e95
@ -9,6 +9,7 @@ import (
|
||||
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/filetree"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/mgutz/str"
|
||||
)
|
||||
@ -137,12 +138,12 @@ func (c *GitCommand) DiscardAllFileChanges(file *models.File) error {
|
||||
return c.DiscardUnstagedFileChanges(file)
|
||||
}
|
||||
|
||||
func (c *GitCommand) DiscardAllDirChanges(node *models.FileChangeNode) error {
|
||||
func (c *GitCommand) DiscardAllDirChanges(node *filetree.FileChangeNode) error {
|
||||
// this could be more efficient but we would need to handle all the edge cases
|
||||
return node.ForEachFile(c.DiscardAllFileChanges)
|
||||
}
|
||||
|
||||
func (c *GitCommand) DiscardUnstagedDirChanges(node *models.FileChangeNode) error {
|
||||
func (c *GitCommand) DiscardUnstagedDirChanges(node *filetree.FileChangeNode) error {
|
||||
if err := c.RemoveUntrackedDirFiles(node); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -155,9 +156,9 @@ func (c *GitCommand) DiscardUnstagedDirChanges(node *models.FileChangeNode) erro
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *GitCommand) RemoveUntrackedDirFiles(node *models.FileChangeNode) error {
|
||||
func (c *GitCommand) RemoveUntrackedDirFiles(node *filetree.FileChangeNode) error {
|
||||
untrackedFilePaths := node.GetPathsMatching(
|
||||
func(n *models.FileChangeNode) bool { return n.File != nil && !n.File.GetIsTracked() },
|
||||
func(n *filetree.FileChangeNode) bool { return n.File != nil && !n.File.GetIsTracked() },
|
||||
)
|
||||
|
||||
for _, path := range untrackedFilePaths {
|
||||
|
@ -21,6 +21,14 @@ type File struct {
|
||||
ShortStatus string // e.g. 'AD', ' A', 'M ', '??'
|
||||
}
|
||||
|
||||
// sometimes we need to deal with either a node (which contains a file) or an actual file
|
||||
type IFileChange interface {
|
||||
GetHasUnstagedChanges() bool
|
||||
GetHasStagedChanges() bool
|
||||
GetIsTracked() bool
|
||||
GetPath() string
|
||||
}
|
||||
|
||||
const RENAME_SEPARATOR = " -> "
|
||||
|
||||
func (f *File) IsRename() bool {
|
||||
|
@ -1,9 +0,0 @@
|
||||
package models
|
||||
|
||||
// sometimes we need to deal with either a node (which contains a file) or an actual file
|
||||
type IFileChange interface {
|
||||
GetHasUnstagedChanges() bool
|
||||
GetHasStagedChanges() bool
|
||||
GetIsTracked() bool
|
||||
GetPath() string
|
||||
}
|
@ -15,13 +15,14 @@ import (
|
||||
"github.com/jesseduffield/lazygit/pkg/commands"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/filetree"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/mgutz/str"
|
||||
)
|
||||
|
||||
// list panel functions
|
||||
|
||||
func (gui *Gui) getSelectedFileChangeNode() *models.FileChangeNode {
|
||||
func (gui *Gui) getSelectedFileChangeNode() *filetree.FileChangeNode {
|
||||
selectedLine := gui.State.Panels.Files.SelectedLineIdx
|
||||
if selectedLine == -1 {
|
||||
return nil
|
||||
@ -557,8 +558,8 @@ func (gui *Gui) refreshStateFiles() error {
|
||||
// nodes until we find one that exists in the new set of nodes, then move the cursor
|
||||
// to that.
|
||||
// prevNodes starts from our previously selected node because we don't need to consider anything above that
|
||||
func (gui *Gui) findNewSelectedIdx(prevNodes []*models.FileChangeNode, currNodes []*models.FileChangeNode) int {
|
||||
getPaths := func(node *models.FileChangeNode) []string {
|
||||
func (gui *Gui) findNewSelectedIdx(prevNodes []*filetree.FileChangeNode, currNodes []*filetree.FileChangeNode) int {
|
||||
getPaths := func(node *filetree.FileChangeNode) []string {
|
||||
if node == nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -9,10 +9,10 @@ import (
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
)
|
||||
|
||||
func BuildTreeFromFiles(files []*models.File) *models.FileChangeNode {
|
||||
root := &models.FileChangeNode{}
|
||||
func BuildTreeFromFiles(files []*models.File) *FileChangeNode {
|
||||
root := &FileChangeNode{}
|
||||
|
||||
var curr *models.FileChangeNode
|
||||
var curr *FileChangeNode
|
||||
for _, file := range files {
|
||||
split := strings.Split(file.Name, string(os.PathSeparator))
|
||||
curr = root
|
||||
@ -33,7 +33,7 @@ func BuildTreeFromFiles(files []*models.File) *models.FileChangeNode {
|
||||
}
|
||||
}
|
||||
|
||||
newChild := &models.FileChangeNode{
|
||||
newChild := &FileChangeNode{
|
||||
Path: path,
|
||||
File: setFile,
|
||||
}
|
||||
@ -49,7 +49,7 @@ func BuildTreeFromFiles(files []*models.File) *models.FileChangeNode {
|
||||
return root
|
||||
}
|
||||
|
||||
func BuildFlatTreeFromFiles(files []*models.File) *models.FileChangeNode {
|
||||
func BuildFlatTreeFromFiles(files []*models.File) *FileChangeNode {
|
||||
rootAux := BuildTreeFromFiles(files)
|
||||
sortedFiles := rootAux.GetLeaves()
|
||||
|
||||
@ -59,5 +59,5 @@ func BuildFlatTreeFromFiles(files []*models.File) *models.FileChangeNode {
|
||||
return sortedFiles[i].File != nil && sortedFiles[i].File.HasMergeConflicts && !(sortedFiles[j].File != nil && sortedFiles[j].File.HasMergeConflicts)
|
||||
})
|
||||
|
||||
return &models.FileChangeNode{Children: sortedFiles}
|
||||
return &FileChangeNode{Children: sortedFiles}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ const NOTHING = " "
|
||||
|
||||
type FileChangeManager struct {
|
||||
files []*models.File
|
||||
tree *models.FileChangeNode
|
||||
tree *FileChangeNode
|
||||
showTree bool
|
||||
log *logrus.Entry
|
||||
collapsedPaths map[string]bool
|
||||
@ -39,7 +39,7 @@ func (m *FileChangeManager) ToggleShowTree() {
|
||||
m.SetTree()
|
||||
}
|
||||
|
||||
func (m *FileChangeManager) GetItemAtIndex(index int) *models.FileChangeNode {
|
||||
func (m *FileChangeManager) GetItemAtIndex(index int) *FileChangeNode {
|
||||
// need to traverse the three depth first until we get to the index.
|
||||
return m.tree.GetNodeAtIndex(index+1, m.collapsedPaths) // ignoring root
|
||||
}
|
||||
@ -49,7 +49,7 @@ func (m *FileChangeManager) GetIndexForPath(path string) (int, bool) {
|
||||
return index - 1, found
|
||||
}
|
||||
|
||||
func (m *FileChangeManager) GetAllItems() []*models.FileChangeNode {
|
||||
func (m *FileChangeManager) GetAllItems() []*FileChangeNode {
|
||||
if m.tree == nil {
|
||||
return nil
|
||||
}
|
||||
@ -83,15 +83,15 @@ func (m *FileChangeManager) Render(diffName string, submoduleConfigs []*models.S
|
||||
return m.renderAux(m.tree, "", -1, diffName, submoduleConfigs)
|
||||
}
|
||||
|
||||
func (m *FileChangeManager) IsCollapsed(s *models.FileChangeNode) bool {
|
||||
func (m *FileChangeManager) IsCollapsed(s *FileChangeNode) bool {
|
||||
return m.collapsedPaths[s.GetPath()]
|
||||
}
|
||||
|
||||
func (m *FileChangeManager) ToggleCollapsed(s *models.FileChangeNode) {
|
||||
func (m *FileChangeManager) ToggleCollapsed(s *FileChangeNode) {
|
||||
m.collapsedPaths[s.GetPath()] = !m.collapsedPaths[s.GetPath()]
|
||||
}
|
||||
|
||||
func (m *FileChangeManager) renderAux(s *models.FileChangeNode, prefix string, depth int, diffName string, submoduleConfigs []*models.SubmoduleConfig) []string {
|
||||
func (m *FileChangeManager) renderAux(s *FileChangeNode, prefix string, depth int, diffName string, submoduleConfigs []*models.SubmoduleConfig) []string {
|
||||
isRoot := depth == -1
|
||||
if s == nil {
|
||||
return []string{}
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
func TestRender(t *testing.T) {
|
||||
scenarios := []struct {
|
||||
name string
|
||||
root *models.FileChangeNode
|
||||
root *FileChangeNode
|
||||
collapsedPaths map[string]bool
|
||||
expected []string
|
||||
}{
|
||||
@ -21,9 +21,9 @@ func TestRender(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "leaf node",
|
||||
root: &models.FileChangeNode{
|
||||
root: &FileChangeNode{
|
||||
Path: "",
|
||||
Children: []*models.FileChangeNode{
|
||||
Children: []*FileChangeNode{
|
||||
{File: &models.File{Name: "test", ShortStatus: " M", HasStagedChanges: true}, Path: "test"},
|
||||
},
|
||||
},
|
||||
@ -31,12 +31,12 @@ func TestRender(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "big example",
|
||||
root: &models.FileChangeNode{
|
||||
root: &FileChangeNode{
|
||||
Path: "",
|
||||
Children: []*models.FileChangeNode{
|
||||
Children: []*FileChangeNode{
|
||||
{
|
||||
Path: "dir1",
|
||||
Children: []*models.FileChangeNode{
|
||||
Children: []*FileChangeNode{
|
||||
{
|
||||
File: &models.File{Name: "dir1/file2", ShortStatus: "M ", HasUnstagedChanges: true},
|
||||
Path: "dir1/file2",
|
||||
@ -49,10 +49,10 @@ func TestRender(t *testing.T) {
|
||||
},
|
||||
{
|
||||
Path: "dir2",
|
||||
Children: []*models.FileChangeNode{
|
||||
Children: []*FileChangeNode{
|
||||
{
|
||||
Path: "dir2/dir2",
|
||||
Children: []*models.FileChangeNode{
|
||||
Children: []*FileChangeNode{
|
||||
{
|
||||
File: &models.File{Name: "dir2/dir2/file3", ShortStatus: " M", HasStagedChanges: true},
|
||||
Path: "dir2/dir2/file3",
|
||||
|
@ -1,4 +1,4 @@
|
||||
package models
|
||||
package filetree
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -6,28 +6,30 @@ import (
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
)
|
||||
|
||||
type FileChangeNode struct {
|
||||
Children []*FileChangeNode
|
||||
File *File
|
||||
File *models.File
|
||||
Path string // e.g. '/path/to/mydir'
|
||||
CompressionLevel int // equal to the number of forward slashes you'll see in the path when it's rendered in tree mode
|
||||
}
|
||||
|
||||
func (s *FileChangeNode) GetHasUnstagedChanges() bool {
|
||||
return s.AnyFile(func(file *File) bool { return file.HasUnstagedChanges })
|
||||
return s.AnyFile(func(file *models.File) bool { return file.HasUnstagedChanges })
|
||||
}
|
||||
|
||||
func (s *FileChangeNode) GetHasStagedChanges() bool {
|
||||
return s.AnyFile(func(file *File) bool { return file.HasStagedChanges })
|
||||
return s.AnyFile(func(file *models.File) bool { return file.HasStagedChanges })
|
||||
}
|
||||
|
||||
func (s *FileChangeNode) GetHasInlineMergeConflicts() bool {
|
||||
return s.AnyFile(func(file *File) bool { return file.HasInlineMergeConflicts })
|
||||
return s.AnyFile(func(file *models.File) bool { return file.HasInlineMergeConflicts })
|
||||
}
|
||||
|
||||
func (s *FileChangeNode) AnyFile(test func(file *File) bool) bool {
|
||||
func (s *FileChangeNode) AnyFile(test func(file *models.File) bool) bool {
|
||||
return s.Any(func(node *FileChangeNode) bool {
|
||||
return node.IsLeaf() && test(node.File)
|
||||
})
|
||||
@ -39,7 +41,7 @@ func (s *FileChangeNode) Any(test func(node *FileChangeNode) bool) bool {
|
||||
}
|
||||
|
||||
for _, child := range s.Children {
|
||||
if test(child) {
|
||||
if child.Any(test) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -231,7 +233,7 @@ func (s *FileChangeNode) Description() string {
|
||||
return s.GetPath()
|
||||
}
|
||||
|
||||
func (s *FileChangeNode) ForEachFile(cb func(*File) error) error {
|
||||
func (s *FileChangeNode) ForEachFile(cb func(*models.File) error) error {
|
||||
if s.File != nil {
|
||||
if err := cb(s.File); err != nil {
|
||||
return err
|
@ -1,8 +1,9 @@
|
||||
package models
|
||||
package filetree
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@ -22,13 +23,13 @@ func TestCompress(t *testing.T) {
|
||||
root: &FileChangeNode{
|
||||
Path: "",
|
||||
Children: []*FileChangeNode{
|
||||
{File: &File{Name: "test", ShortStatus: " M", HasStagedChanges: true}, Path: "test"},
|
||||
{File: &models.File{Name: "test", ShortStatus: " M", HasStagedChanges: true}, Path: "test"},
|
||||
},
|
||||
},
|
||||
expected: &FileChangeNode{
|
||||
Path: "",
|
||||
Children: []*FileChangeNode{
|
||||
{File: &File{Name: "test", ShortStatus: " M", HasStagedChanges: true}, Path: "test"},
|
||||
{File: &models.File{Name: "test", ShortStatus: " M", HasStagedChanges: true}, Path: "test"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -41,7 +42,7 @@ func TestCompress(t *testing.T) {
|
||||
Path: "dir1",
|
||||
Children: []*FileChangeNode{
|
||||
{
|
||||
File: &File{Name: "file2", ShortStatus: "M ", HasUnstagedChanges: true},
|
||||
File: &models.File{Name: "file2", ShortStatus: "M ", HasUnstagedChanges: true},
|
||||
Path: "dir1/file2",
|
||||
},
|
||||
},
|
||||
@ -50,11 +51,11 @@ func TestCompress(t *testing.T) {
|
||||
Path: "dir2",
|
||||
Children: []*FileChangeNode{
|
||||
{
|
||||
File: &File{Name: "file3", ShortStatus: " M", HasStagedChanges: true},
|
||||
File: &models.File{Name: "file3", ShortStatus: " M", HasStagedChanges: true},
|
||||
Path: "dir2/file3",
|
||||
},
|
||||
{
|
||||
File: &File{Name: "file4", ShortStatus: "M ", HasUnstagedChanges: true},
|
||||
File: &models.File{Name: "file4", ShortStatus: "M ", HasUnstagedChanges: true},
|
||||
Path: "dir2/file4",
|
||||
},
|
||||
},
|
||||
@ -66,7 +67,7 @@ func TestCompress(t *testing.T) {
|
||||
Path: "dir3/dir3-1",
|
||||
Children: []*FileChangeNode{
|
||||
{
|
||||
File: &File{Name: "file5", ShortStatus: "M ", HasUnstagedChanges: true},
|
||||
File: &models.File{Name: "file5", ShortStatus: "M ", HasUnstagedChanges: true},
|
||||
Path: "dir3/dir3-1/file5",
|
||||
},
|
||||
},
|
||||
@ -74,7 +75,7 @@ func TestCompress(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
File: &File{Name: "file1", ShortStatus: "M ", HasUnstagedChanges: true},
|
||||
File: &models.File{Name: "file1", ShortStatus: "M ", HasUnstagedChanges: true},
|
||||
Path: "file1",
|
||||
},
|
||||
},
|
||||
@ -84,29 +85,29 @@ func TestCompress(t *testing.T) {
|
||||
Children: []*FileChangeNode{
|
||||
{
|
||||
Path: "dir1/file2",
|
||||
File: &File{Name: "file2", ShortStatus: "M ", HasUnstagedChanges: true},
|
||||
File: &models.File{Name: "file2", ShortStatus: "M ", HasUnstagedChanges: true},
|
||||
CompressionLevel: 1,
|
||||
},
|
||||
{
|
||||
Path: "dir2",
|
||||
Children: []*FileChangeNode{
|
||||
{
|
||||
File: &File{Name: "file3", ShortStatus: " M", HasStagedChanges: true},
|
||||
File: &models.File{Name: "file3", ShortStatus: " M", HasStagedChanges: true},
|
||||
Path: "dir2/file3",
|
||||
},
|
||||
{
|
||||
File: &File{Name: "file4", ShortStatus: "M ", HasUnstagedChanges: true},
|
||||
File: &models.File{Name: "file4", ShortStatus: "M ", HasUnstagedChanges: true},
|
||||
Path: "dir2/file4",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Path: "dir3/dir3-1/file5",
|
||||
File: &File{Name: "file5", ShortStatus: "M ", HasUnstagedChanges: true},
|
||||
File: &models.File{Name: "file5", ShortStatus: "M ", HasUnstagedChanges: true},
|
||||
CompressionLevel: 2,
|
||||
},
|
||||
{
|
||||
File: &File{Name: "file1", ShortStatus: "M ", HasUnstagedChanges: true},
|
||||
File: &models.File{Name: "file1", ShortStatus: "M ", HasUnstagedChanges: true},
|
||||
Path: "file1",
|
||||
},
|
||||
},
|
Loading…
x
Reference in New Issue
Block a user