diff options
author | Jesse Duffield <jessedduffield@gmail.com> | 2021-03-21 08:41:06 +1100 |
---|---|---|
committer | Jesse Duffield <jessedduffield@gmail.com> | 2021-03-30 21:57:00 +1100 |
commit | da6fe01eca531635c09627c60bd38d49bb092906 (patch) | |
tree | 79ecf551adaee34fccabaa60f3d083c7792a25a0 /pkg/commands | |
parent | c27cea6f30c35328a24bb4fb7db4f002ab544ad3 (diff) |
allow toggling on/off file tree mode
Diffstat (limited to 'pkg/commands')
-rw-r--r-- | pkg/commands/files.go | 24 | ||||
-rw-r--r-- | pkg/commands/git_test.go | 4 | ||||
-rw-r--r-- | pkg/commands/loading_files.go | 17 | ||||
-rw-r--r-- | pkg/commands/models/file.go | 15 | ||||
-rw-r--r-- | pkg/commands/models/status_line_node.go | 49 | ||||
-rw-r--r-- | pkg/commands/stash_entries.go | 2 |
6 files changed, 83 insertions, 28 deletions
diff --git a/pkg/commands/files.go b/pkg/commands/files.go index 8244408cc..163e006e1 100644 --- a/pkg/commands/files.go +++ b/pkg/commands/files.go @@ -5,7 +5,6 @@ import ( "os" "os/exec" "path/filepath" - "strings" "time" "github.com/go-errors/errors" @@ -21,9 +20,7 @@ func (c *GitCommand) CatFile(fileName string) (string, error) { // StageFile stages a file func (c *GitCommand) StageFile(fileName string) error { - // renamed files look like "file1 -> file2" - fileNames := strings.Split(fileName, models.RENAME_SEPARATOR) - return c.OSCommand.RunCommand("git add -- %s", c.OSCommand.Quote(fileNames[len(fileNames)-1])) + return c.OSCommand.RunCommand("git add -- %s", c.OSCommand.Quote(fileName)) } // StageAll stages all files @@ -37,14 +34,14 @@ func (c *GitCommand) UnstageAll() error { } // UnStageFile unstages a file -func (c *GitCommand) UnStageFile(fileName string, tracked bool) error { +// we accept an array of filenames for the cases where a file has been renamed i.e. +// we accept the current name and the previous name +func (c *GitCommand) UnStageFile(fileNames []string, reset bool) error { command := "git rm --cached --force -- %s" - if tracked { + if reset { command = "git reset HEAD -- %s" } - // renamed files look like "file1 -> file2" - fileNames := strings.Split(fileName, models.RENAME_SEPARATOR) for _, name := range fileNames { if err := c.OSCommand.RunCommand(command, c.OSCommand.Quote(name)); err != nil { return err @@ -59,20 +56,19 @@ func (c *GitCommand) BeforeAndAfterFileForRename(file *models.File) (*models.Fil return nil, nil, errors.New("Expected renamed file") } - // we've got a file that represents a rename from one file to another. Unfortunately - // our File abstraction fails to consider this case, so here we will refetch + // we've got a file that represents a rename from one file to another. Here we will refetch // all files, passing the --no-renames flag and then recursively call the function - // again for the before file and after file. At some point we should fix the abstraction itself + // again for the before file and after file. - split := strings.Split(file.Name, models.RENAME_SEPARATOR) filesWithoutRenames := c.GetStatusFiles(GetStatusFileOptions{NoRenames: true}) var beforeFile *models.File var afterFile *models.File for _, f := range filesWithoutRenames { - if f.Name == split[0] { + if f.Name == file.PreviousName { beforeFile = f } - if f.Name == split[1] { + + if f.Name == file.Name { afterFile = f } } diff --git a/pkg/commands/git_test.go b/pkg/commands/git_test.go index 9eea0c34c..e0955932f 100644 --- a/pkg/commands/git_test.go +++ b/pkg/commands/git_test.go @@ -1056,7 +1056,7 @@ func TestGitCommandUnstageFile(t *testing.T) { testName string command func(string, ...string) *exec.Cmd test func(error) - tracked bool + reset bool } scenarios := []scenario{ @@ -1092,7 +1092,7 @@ func TestGitCommandUnstageFile(t *testing.T) { t.Run(s.testName, func(t *testing.T) { gitCmd := NewDummyGitCommand() gitCmd.OSCommand.Command = s.command - s.test(gitCmd.UnStageFile("test.txt", s.tracked)) + s.test(gitCmd.UnStageFile([]string{"test.txt"}, s.reset)) }) } } diff --git a/pkg/commands/loading_files.go b/pkg/commands/loading_files.go index 411c0251a..ba3244999 100644 --- a/pkg/commands/loading_files.go +++ b/pkg/commands/loading_files.go @@ -8,6 +8,8 @@ import ( "github.com/jesseduffield/lazygit/pkg/utils" ) +const RENAME_SEPARATOR = " -> " + // GetStatusFiles git status files type GetStatusFileOptions struct { NoRenames bool @@ -37,14 +39,21 @@ func (c *GitCommand) GetStatusFiles(opts GetStatusFileOptions) []*models.File { change := statusString[0:2] stagedChange := change[0:1] unstagedChange := statusString[1:2] - filename := statusString[3:] + name := statusString[3:] untracked := utils.IncludesString([]string{"??", "A ", "AM"}, change) hasNoStagedChanges := utils.IncludesString([]string{" ", "U", "?"}, stagedChange) hasMergeConflicts := utils.IncludesString([]string{"DD", "AA", "UU", "AU", "UA", "UD", "DU"}, change) hasInlineMergeConflicts := utils.IncludesString([]string{"UU", "AA"}, change) + previousName := "" + if strings.Contains(name, RENAME_SEPARATOR) { + split := strings.Split(name, RENAME_SEPARATOR) + name = split[1] + previousName = split[0] + } file := &models.File{ - Name: filename, + Name: name, + PreviousName: previousName, DisplayString: statusString, HasStagedChanges: !hasNoStagedChanges, HasUnstagedChanges: unstagedChange != " ", @@ -53,7 +62,7 @@ func (c *GitCommand) GetStatusFiles(opts GetStatusFileOptions) []*models.File { Added: unstagedChange == "A" || untracked, HasMergeConflicts: hasMergeConflicts, HasInlineMergeConflicts: hasInlineMergeConflicts, - Type: c.OSCommand.FileType(filename), + Type: c.OSCommand.FileType(name), ShortStatus: change, } files = append(files, file) @@ -85,7 +94,7 @@ func (c *GitCommand) GitStatus(opts GitStatusOptions) (string, error) { original := splitLines[i] if strings.HasPrefix(original, "R ") { next := splitLines[i+1] - updated := "R " + next + models.RENAME_SEPARATOR + strings.TrimPrefix(original, "R ") + updated := "R " + next + RENAME_SEPARATOR + strings.TrimPrefix(original, "R ") splitLines[i] = updated splitLines = append(splitLines[0:i+1], splitLines[i+2:]...) } diff --git a/pkg/commands/models/file.go b/pkg/commands/models/file.go index 32e90f718..3e28ca46f 100644 --- a/pkg/commands/models/file.go +++ b/pkg/commands/models/file.go @@ -1,8 +1,6 @@ package models import ( - "strings" - "github.com/jesseduffield/lazygit/pkg/utils" ) @@ -10,6 +8,7 @@ import ( // duplicating this for now type File struct { Name string + PreviousName string HasStagedChanges bool HasUnstagedChanges bool Tracked bool @@ -25,12 +24,16 @@ type File struct { const RENAME_SEPARATOR = " -> " func (f *File) IsRename() bool { - return strings.Contains(f.Name, RENAME_SEPARATOR) + return f.PreviousName != "" } // Names returns an array containing just the filename, or in the case of a rename, the after filename and the before filename func (f *File) Names() []string { - return strings.Split(f.Name, RENAME_SEPARATOR) + result := []string{f.Name} + if f.PreviousName != "" { + result = append(result, f.PreviousName) + } + return result } // returns true if the file names are the same or if a a file rename includes the filename of the other @@ -73,6 +76,6 @@ func (f *File) GetIsTracked() bool { } func (f *File) GetPath() string { - names := f.Names() - return names[len(names)-1] + // TODO: remove concept of name; just use path + return f.Name } diff --git a/pkg/commands/models/status_line_node.go b/pkg/commands/models/status_line_node.go index 3962e0c42..84dc638ba 100644 --- a/pkg/commands/models/status_line_node.go +++ b/pkg/commands/models/status_line_node.go @@ -2,7 +2,10 @@ package models import ( "fmt" + "os" + "path/filepath" "sort" + "strings" ) type StatusLineNode struct { @@ -67,6 +70,30 @@ func (s *StatusLineNode) getNodeAtIndexAux(index int, collapsedPaths map[string] return nil, offset } +func (s *StatusLineNode) GetIndexForPath(path string, collapsedPaths map[string]bool) (int, bool) { + return s.getIndexForPathAux(path, collapsedPaths) +} + +func (s *StatusLineNode) getIndexForPathAux(path string, collapsedPaths map[string]bool) (int, bool) { + offset := 0 + + if s.Path == path { + return offset, true + } + + if !collapsedPaths[s.GetPath()] { + for _, child := range s.Children { + offsetChange, found := child.getIndexForPathAux(path, collapsedPaths) + offset += offsetChange + 1 + if found { + return offset, true + } + } + } + + return offset, false +} + func (s *StatusLineNode) IsLeaf() bool { return len(s.Children) == 0 } @@ -161,7 +188,6 @@ func (s *StatusLineNode) compressAux() *StatusLineNode { for i := range s.Children { for s.Children[i].HasExactlyOneChild() { grandchild := s.Children[i].Children[0] - grandchild.Name = fmt.Sprintf("%s/%s", s.Children[i].Name, grandchild.Name) s.Children[i] = grandchild } } @@ -215,3 +241,24 @@ func (s *StatusLineNode) ForEachFile(cb func(*File) error) error { return nil } + +func (s *StatusLineNode) NameAtDepth(depth int) string { + splitName := strings.Split(s.Name, string(os.PathSeparator)) + name := filepath.Join(splitName[depth:]...) + + if s.File != nil && s.File.IsRename() { + splitPrevName := strings.Split(s.File.PreviousName, string(os.PathSeparator)) + + prevName := s.File.PreviousName + // if the file has just been renamed inside the same directory, we can shave off + // the prefix for the previous path too. Otherwise we'll keep it unchanged + sameParentDir := filepath.Join(splitName[0:depth]...) == filepath.Join(splitPrevName[0:depth]...) + if sameParentDir { + prevName = filepath.Join(splitPrevName[depth:]...) + } + + return fmt.Sprintf("%s%s%s", prevName, " -> ", name) + } + + return name +} diff --git a/pkg/commands/stash_entries.go b/pkg/commands/stash_entries.go index 1bc957130..4fad9ffab 100644 --- a/pkg/commands/stash_entries.go +++ b/pkg/commands/stash_entries.go @@ -48,7 +48,7 @@ func (c *GitCommand) StashSaveStagedChanges(message string) error { files := c.GetStatusFiles(GetStatusFileOptions{}) for _, file := range files { if file.ShortStatus == "AD" { - if err := c.UnStageFile(file.Name, false); err != nil { + if err := c.UnStageFile(file.Names(), false); err != nil { return err } } |