diff --git a/pkg/commands/git_commands/commit_file_loader.go b/pkg/commands/git_commands/commit_file_loader.go index 68faf31ca..33bd40e13 100644 --- a/pkg/commands/git_commands/commit_file_loader.go +++ b/pkg/commands/git_commands/commit_file_loader.go @@ -55,7 +55,7 @@ func getCommitFilesFromFilenames(filenames string) []*models.CommitFile { return lo.Map(lo.Chunk(lines, 2), func(chunk []string, _ int) *models.CommitFile { return &models.CommitFile{ ChangeStatus: chunk[0], - Name: chunk[1], + Path: chunk[1], } }) } diff --git a/pkg/commands/git_commands/commit_file_loader_test.go b/pkg/commands/git_commands/commit_file_loader_test.go index 8928f5204..ec91ec22e 100644 --- a/pkg/commands/git_commands/commit_file_loader_test.go +++ b/pkg/commands/git_commands/commit_file_loader_test.go @@ -23,7 +23,7 @@ func TestGetCommitFilesFromFilenames(t *testing.T) { input: "MM\x00Myfile\x00", output: []*models.CommitFile{ { - Name: "Myfile", + Path: "Myfile", ChangeStatus: "MM", }, }, @@ -33,11 +33,11 @@ func TestGetCommitFilesFromFilenames(t *testing.T) { input: "MM\x00Myfile\x00M \x00MyOtherFile\x00", output: []*models.CommitFile{ { - Name: "Myfile", + Path: "Myfile", ChangeStatus: "MM", }, { - Name: "MyOtherFile", + Path: "MyOtherFile", ChangeStatus: "M ", }, }, @@ -47,15 +47,15 @@ func TestGetCommitFilesFromFilenames(t *testing.T) { input: "MM\x00Myfile\x00M \x00MyOtherFile\x00 M\x00YetAnother\x00", output: []*models.CommitFile{ { - Name: "Myfile", + Path: "Myfile", ChangeStatus: "MM", }, { - Name: "MyOtherFile", + Path: "MyOtherFile", ChangeStatus: "M ", }, { - Name: "YetAnother", + Path: "YetAnother", ChangeStatus: " M", }, }, diff --git a/pkg/commands/git_commands/file_loader.go b/pkg/commands/git_commands/file_loader.go index dcc1615a7..bb898d06a 100644 --- a/pkg/commands/git_commands/file_loader.go +++ b/pkg/commands/git_commands/file_loader.go @@ -68,12 +68,12 @@ func (self *FileLoader) GetStatusFiles(opts GetStatusFileOptions) []*models.File } file := &models.File{ - Name: status.Name, - PreviousName: status.PreviousName, + Path: status.Path, + PreviousPath: status.PreviousPath, DisplayString: status.StatusString, } - if diff, ok := fileDiffs[status.Name]; ok { + if diff, ok := fileDiffs[status.Path]; ok { file.LinesAdded = diff.LinesAdded file.LinesDeleted = diff.LinesDeleted } @@ -87,7 +87,7 @@ func (self *FileLoader) GetStatusFiles(opts GetStatusFileOptions) []*models.File worktreePaths := linkedWortkreePaths(self.Fs, self.repoPaths.RepoGitDirPath()) for _, file := range files { for _, worktreePath := range worktreePaths { - absFilePath, err := filepath.Abs(file.Name) + absFilePath, err := filepath.Abs(file.Path) if err != nil { self.Log.Error(err) continue @@ -96,7 +96,7 @@ func (self *FileLoader) GetStatusFiles(opts GetStatusFileOptions) []*models.File file.IsWorktree = true // `git status` renders this worktree as a folder with a trailing slash but we'll represent it as a singular worktree // If we include the slash, it will be rendered as a folder with a null file inside. - file.Name = strings.TrimSuffix(file.Name, "/") + file.Path = strings.TrimSuffix(file.Path, "/") break } } @@ -153,8 +153,8 @@ type GitStatusOptions struct { type FileStatus struct { StatusString string Change string // ??, MM, AM, ... - Name string - PreviousName string + Path string + PreviousPath string } func (fileLoader *FileLoader) gitDiffNumStat() (string, error) { @@ -197,14 +197,14 @@ func (self *FileLoader) gitStatus(opts GitStatusOptions) ([]FileStatus, error) { status := FileStatus{ StatusString: original, Change: original[:2], - Name: original[3:], - PreviousName: "", + Path: original[3:], + PreviousPath: "", } if strings.HasPrefix(status.Change, "R") { // if a line starts with 'R' then the next line is the original file. - status.PreviousName = splitLines[i+1] - status.StatusString = fmt.Sprintf("%s %s -> %s", status.Change, status.PreviousName, status.Name) + status.PreviousPath = splitLines[i+1] + status.StatusString = fmt.Sprintf("%s %s -> %s", status.Change, status.PreviousPath, status.Path) i++ } diff --git a/pkg/commands/git_commands/file_loader_test.go b/pkg/commands/git_commands/file_loader_test.go index cc4bbaa07..233bfb855 100644 --- a/pkg/commands/git_commands/file_loader_test.go +++ b/pkg/commands/git_commands/file_loader_test.go @@ -41,7 +41,7 @@ func TestFileGetStatusFiles(t *testing.T) { showNumstatInFilesView: true, expectedFiles: []*models.File{ { - Name: "file1.txt", + Path: "file1.txt", HasStagedChanges: true, HasUnstagedChanges: true, Tracked: true, @@ -55,7 +55,7 @@ func TestFileGetStatusFiles(t *testing.T) { LinesDeleted: 1, }, { - Name: "file3.txt", + Path: "file3.txt", HasStagedChanges: true, HasUnstagedChanges: false, Tracked: false, @@ -69,7 +69,7 @@ func TestFileGetStatusFiles(t *testing.T) { LinesDeleted: 2, }, { - Name: "file2.txt", + Path: "file2.txt", HasStagedChanges: true, HasUnstagedChanges: true, Tracked: false, @@ -83,7 +83,7 @@ func TestFileGetStatusFiles(t *testing.T) { LinesDeleted: 0, }, { - Name: "file4.txt", + Path: "file4.txt", HasStagedChanges: false, HasUnstagedChanges: true, Tracked: false, @@ -97,7 +97,7 @@ func TestFileGetStatusFiles(t *testing.T) { LinesDeleted: 2, }, { - Name: "file5.txt", + Path: "file5.txt", HasStagedChanges: false, HasUnstagedChanges: true, Tracked: true, @@ -119,7 +119,7 @@ func TestFileGetStatusFiles(t *testing.T) { ExpectGitArgs([]string{"status", "--untracked-files=yes", "--porcelain", "-z", "--find-renames=50%"}, "MM a\nb.txt", nil), expectedFiles: []*models.File{ { - Name: "a\nb.txt", + Path: "a\nb.txt", HasStagedChanges: true, HasUnstagedChanges: true, Tracked: true, @@ -142,8 +142,8 @@ func TestFileGetStatusFiles(t *testing.T) { ), expectedFiles: []*models.File{ { - Name: "after1.txt", - PreviousName: "before1.txt", + Path: "after1.txt", + PreviousPath: "before1.txt", HasStagedChanges: true, HasUnstagedChanges: false, Tracked: true, @@ -155,8 +155,8 @@ func TestFileGetStatusFiles(t *testing.T) { ShortStatus: "R ", }, { - Name: "after2.txt", - PreviousName: "before2.txt", + Path: "after2.txt", + PreviousPath: "before2.txt", HasStagedChanges: true, HasUnstagedChanges: true, Tracked: true, @@ -179,7 +179,7 @@ func TestFileGetStatusFiles(t *testing.T) { ), expectedFiles: []*models.File{ { - Name: "a -> b.txt", + Path: "a -> b.txt", HasStagedChanges: false, HasUnstagedChanges: true, Tracked: false, diff --git a/pkg/commands/git_commands/working_tree.go b/pkg/commands/git_commands/working_tree.go index 7ed257536..e1339ee56 100644 --- a/pkg/commands/git_commands/working_tree.go +++ b/pkg/commands/git_commands/working_tree.go @@ -92,11 +92,11 @@ func (self *WorkingTreeCommands) BeforeAndAfterFileForRename(file *models.File) var beforeFile *models.File var afterFile *models.File for _, f := range filesWithoutRenames { - if f.Name == file.PreviousName { + if f.Path == file.PreviousPath { beforeFile = f } - if f.Name == file.Name { + if f.Path == file.Path { afterFile = f } } @@ -134,13 +134,13 @@ func (self *WorkingTreeCommands) DiscardAllFileChanges(file *models.File) error if file.ShortStatus == "AA" { if err := self.cmd.New( - NewGitCmd("checkout").Arg("--ours", "--", file.Name).ToArgv(), + NewGitCmd("checkout").Arg("--ours", "--", file.Path).ToArgv(), ).Run(); err != nil { return err } if err := self.cmd.New( - NewGitCmd("add").Arg("--", file.Name).ToArgv(), + NewGitCmd("add").Arg("--", file.Path).ToArgv(), ).Run(); err != nil { return err } @@ -149,14 +149,14 @@ func (self *WorkingTreeCommands) DiscardAllFileChanges(file *models.File) error if file.ShortStatus == "DU" { return self.cmd.New( - NewGitCmd("rm").Arg("--", file.Name).ToArgv(), + NewGitCmd("rm").Arg("--", file.Path).ToArgv(), ).Run() } // if the file isn't tracked, we assume you want to delete it if file.HasStagedChanges || file.HasMergeConflicts { if err := self.cmd.New( - NewGitCmd("reset").Arg("--", file.Name).ToArgv(), + NewGitCmd("reset").Arg("--", file.Path).ToArgv(), ).Run(); err != nil { return err } @@ -167,7 +167,7 @@ func (self *WorkingTreeCommands) DiscardAllFileChanges(file *models.File) error } if file.Added { - return self.os.RemoveFile(file.Name) + return self.os.RemoveFile(file.Path) } return self.DiscardUnstagedFileChanges(file) @@ -199,7 +199,7 @@ func (self *WorkingTreeCommands) DiscardUnstagedDirChanges(node IFileNode) error } } else { if file.Added && !file.HasStagedChanges { - return self.os.RemoveFile(file.Name) + return self.os.RemoveFile(file.Path) } if err := self.DiscardUnstagedFileChanges(file); err != nil { @@ -226,7 +226,7 @@ func (self *WorkingTreeCommands) RemoveUntrackedDirFiles(node IFileNode) error { } func (self *WorkingTreeCommands) DiscardUnstagedFileChanges(file *models.File) error { - cmdArgs := NewGitCmd("checkout").Arg("--", file.Name).ToArgv() + cmdArgs := NewGitCmd("checkout").Arg("--", file.Path).ToArgv() return self.cmd.New(cmdArgs).Run() } diff --git a/pkg/commands/git_commands/working_tree_test.go b/pkg/commands/git_commands/working_tree_test.go index fb5463a6d..bbe3d7720 100644 --- a/pkg/commands/git_commands/working_tree_test.go +++ b/pkg/commands/git_commands/working_tree_test.go @@ -83,7 +83,7 @@ func TestWorkingTreeDiscardAllFileChanges(t *testing.T) { { testName: "An error occurred when resetting", file: &models.File{ - Name: "test", + Path: "test", HasStagedChanges: true, }, removeFile: func(string) error { return nil }, @@ -94,7 +94,7 @@ func TestWorkingTreeDiscardAllFileChanges(t *testing.T) { { testName: "An error occurred when removing file", file: &models.File{ - Name: "test", + Path: "test", Tracked: false, Added: true, }, @@ -107,7 +107,7 @@ func TestWorkingTreeDiscardAllFileChanges(t *testing.T) { { testName: "An error occurred with checkout", file: &models.File{ - Name: "test", + Path: "test", Tracked: true, HasStagedChanges: false, }, @@ -119,7 +119,7 @@ func TestWorkingTreeDiscardAllFileChanges(t *testing.T) { { testName: "Checkout only", file: &models.File{ - Name: "test", + Path: "test", Tracked: true, HasStagedChanges: false, }, @@ -131,7 +131,7 @@ func TestWorkingTreeDiscardAllFileChanges(t *testing.T) { { testName: "Reset and checkout staged changes", file: &models.File{ - Name: "test", + Path: "test", Tracked: true, HasStagedChanges: true, }, @@ -144,7 +144,7 @@ func TestWorkingTreeDiscardAllFileChanges(t *testing.T) { { testName: "Reset and checkout merge conflicts", file: &models.File{ - Name: "test", + Path: "test", Tracked: true, HasMergeConflicts: true, }, @@ -157,7 +157,7 @@ func TestWorkingTreeDiscardAllFileChanges(t *testing.T) { { testName: "Reset and remove", file: &models.File{ - Name: "test", + Path: "test", Tracked: false, Added: true, HasStagedChanges: true, @@ -173,7 +173,7 @@ func TestWorkingTreeDiscardAllFileChanges(t *testing.T) { { testName: "Remove only", file: &models.File{ - Name: "test", + Path: "test", Tracked: false, Added: true, HasStagedChanges: false, @@ -220,7 +220,7 @@ func TestWorkingTreeDiff(t *testing.T) { { testName: "Default case", file: &models.File{ - Name: "test.txt", + Path: "test.txt", HasStagedChanges: false, Tracked: true, }, @@ -235,7 +235,7 @@ func TestWorkingTreeDiff(t *testing.T) { { testName: "cached", file: &models.File{ - Name: "test.txt", + Path: "test.txt", HasStagedChanges: false, Tracked: true, }, @@ -250,7 +250,7 @@ func TestWorkingTreeDiff(t *testing.T) { { testName: "plain", file: &models.File{ - Name: "test.txt", + Path: "test.txt", HasStagedChanges: false, Tracked: true, }, @@ -265,7 +265,7 @@ func TestWorkingTreeDiff(t *testing.T) { { testName: "File not tracked and file has no staged changes", file: &models.File{ - Name: "test.txt", + Path: "test.txt", HasStagedChanges: false, Tracked: false, }, @@ -280,7 +280,7 @@ func TestWorkingTreeDiff(t *testing.T) { { testName: "Default case (ignore whitespace)", file: &models.File{ - Name: "test.txt", + Path: "test.txt", HasStagedChanges: false, Tracked: true, }, @@ -295,7 +295,7 @@ func TestWorkingTreeDiff(t *testing.T) { { testName: "Show diff with custom context size", file: &models.File{ - Name: "test.txt", + Path: "test.txt", HasStagedChanges: false, Tracked: true, }, @@ -310,7 +310,7 @@ func TestWorkingTreeDiff(t *testing.T) { { testName: "Show diff with custom similarity threshold", file: &models.File{ - Name: "test.txt", + Path: "test.txt", HasStagedChanges: false, Tracked: true, }, @@ -466,7 +466,7 @@ func TestWorkingTreeDiscardUnstagedFileChanges(t *testing.T) { scenarios := []scenario{ { testName: "valid case", - file: &models.File{Name: "test.txt"}, + file: &models.File{Path: "test.txt"}, runner: oscommands.NewFakeRunner(t). ExpectGitArgs([]string{"checkout", "--", "test.txt"}, "", nil), test: func(err error) { diff --git a/pkg/commands/models/commit_file.go b/pkg/commands/models/commit_file.go index d05b5b3fd..90ffd6365 100644 --- a/pkg/commands/models/commit_file.go +++ b/pkg/commands/models/commit_file.go @@ -2,18 +2,17 @@ package models // CommitFile : A git commit file type CommitFile struct { - // TODO: rename this to Path - Name string + Path string ChangeStatus string // e.g. 'A' for added or 'M' for modified. This is based on the result from git diff --name-status } func (f *CommitFile) ID() string { - return f.Name + return f.Path } func (f *CommitFile) Description() string { - return f.Name + return f.Path } func (f *CommitFile) Added() bool { @@ -25,5 +24,5 @@ func (f *CommitFile) Deleted() bool { } func (f *CommitFile) GetPath() string { - return f.Name + return f.Path } diff --git a/pkg/commands/models/file.go b/pkg/commands/models/file.go index 4be424e22..561399820 100644 --- a/pkg/commands/models/file.go +++ b/pkg/commands/models/file.go @@ -8,8 +8,8 @@ import ( // File : A file from git status // duplicating this for now type File struct { - Name string - PreviousName string + Path string + PreviousPath string HasStagedChanges bool HasUnstagedChanges bool Tracked bool @@ -37,14 +37,14 @@ type IFile interface { } func (f *File) IsRename() bool { - return f.PreviousName != "" + return f.PreviousPath != "" } // 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 { - result := []string{f.Name} - if f.PreviousName != "" { - result = append(result, f.PreviousName) + result := []string{f.Path} + if f.PreviousPath != "" { + result = append(result, f.PreviousPath) } return result } @@ -55,11 +55,11 @@ func (f *File) Matches(f2 *File) bool { } func (f *File) ID() string { - return f.Name + return f.Path } func (f *File) Description() string { - return f.Name + return f.Path } func (f *File) IsSubmodule(configs []*SubmoduleConfig) bool { @@ -68,7 +68,7 @@ func (f *File) IsSubmodule(configs []*SubmoduleConfig) bool { func (f *File) SubmoduleConfig(configs []*SubmoduleConfig) *SubmoduleConfig { for _, config := range configs { - if f.Name == config.Path { + if f.Path == config.Path { return config } } @@ -90,11 +90,11 @@ func (f *File) GetIsTracked() bool { func (f *File) GetPath() string { // TODO: remove concept of name; just use path - return f.Name + return f.Path } func (f *File) GetPreviousPath() string { - return f.PreviousName + return f.PreviousPath } func (f *File) GetIsFile() bool { diff --git a/pkg/gui/controllers/commits_files_controller.go b/pkg/gui/controllers/commits_files_controller.go index 69be8ae5d..a9db34b7e 100644 --- a/pkg/gui/controllers/commits_files_controller.go +++ b/pkg/gui/controllers/commits_files_controller.go @@ -231,7 +231,7 @@ func (self *CommitFilesController) openCopyMenu() error { copyPathItem := &types.MenuItem{ Label: self.c.Tr.CopyFilePath, OnPress: func() error { - if err := self.c.OS().CopyToClipboard(node.Path); err != nil { + if err := self.c.OS().CopyToClipboard(node.GetPath()); err != nil { return err } self.c.Toast(self.c.Tr.FilePathCopiedToast) @@ -402,7 +402,7 @@ func (self *CommitFilesController) toggleForPatch(selectedNodes []*filetree.Comm // Find if any file in the selection is unselected or partially added adding := lo.SomeBy(selectedNodes, func(node *filetree.CommitFileNode) bool { return node.SomeFile(func(file *models.CommitFile) bool { - fileStatus := self.c.Git().Patch.PatchBuilder.GetFileStatus(file.Name, self.context().GetRef().RefName()) + fileStatus := self.c.Git().Patch.PatchBuilder.GetFileStatus(file.Path, self.context().GetRef().RefName()) return fileStatus == patch.PART || fileStatus == patch.UNSELECTED }) }) @@ -415,7 +415,7 @@ func (self *CommitFilesController) toggleForPatch(selectedNodes []*filetree.Comm for _, node := range selectedNodes { err := node.ForEachFile(func(file *models.CommitFile) error { - return patchOperationFunction(file.Name) + return patchOperationFunction(file.Path) }) if err != nil { return err @@ -509,7 +509,7 @@ func (self *CommitFilesController) enterCommitFile(node *filetree.CommitFileNode } func (self *CommitFilesController) handleToggleCommitFileDirCollapsed(node *filetree.CommitFileNode) error { - self.context().CommitFileTreeViewModel.ToggleCollapsed(node.GetPath()) + self.context().CommitFileTreeViewModel.ToggleCollapsed(node.GetInternalPath()) self.c.PostRefreshUpdate(self.context()) diff --git a/pkg/gui/controllers/files_controller.go b/pkg/gui/controllers/files_controller.go index 723c16681..3c25543dd 100644 --- a/pkg/gui/controllers/files_controller.go +++ b/pkg/gui/controllers/files_controller.go @@ -372,7 +372,7 @@ func (self *FilesController) optimisticChange(nodes []*filetree.FileNode, optimi err := node.ForEachFile(func(f *models.File) error { // can't act on the file itself: we need to update the original model file for _, modelFile := range self.c.Model().Files { - if modelFile.Name == f.Name { + if modelFile.Path == f.Path { if optimisticChangeFn(modelFile) { rerender = true } @@ -410,7 +410,7 @@ func (self *FilesController) pressWithLock(selectedNodes []*filetree.FileNode) e toPaths := func(nodes []*filetree.FileNode) []string { return lo.Map(nodes, func(node *filetree.FileNode, _ int) string { - return node.Path + return node.GetPath() }) } @@ -881,7 +881,7 @@ func (self *FilesController) openDiffTool(node *filetree.FileNode) error { return self.c.RunSubprocessAndRefresh( self.c.Git().Diff.OpenDiffToolCmdObj( git_commands.DiffToolCmdOptions{ - Filepath: node.Path, + Filepath: node.GetPath(), FromCommit: fromCommit, ToCommit: "", Reverse: reverse, @@ -897,7 +897,7 @@ func (self *FilesController) switchToMerge() error { return nil } - return self.c.Helpers().MergeConflicts.SwitchToMerge(file.Name) + return self.c.Helpers().MergeConflicts.SwitchToMerge(file.Path) } func (self *FilesController) createStashMenu() error { @@ -979,7 +979,7 @@ func (self *FilesController) openCopyMenu() error { copyPathItem := &types.MenuItem{ Label: self.c.Tr.CopyFilePath, OnPress: func() error { - if err := self.c.OS().CopyToClipboard(node.Path); err != nil { + if err := self.c.OS().CopyToClipboard(node.GetPath()); err != nil { return err } self.c.Toast(self.c.Tr.FilePathCopiedToast) @@ -1078,7 +1078,7 @@ func (self *FilesController) handleToggleDirCollapsed() error { return nil } - self.context().FileTreeViewModel.ToggleCollapsed(node.GetPath()) + self.context().FileTreeViewModel.ToggleCollapsed(node.GetInternalPath()) self.c.PostRefreshUpdate(self.c.Contexts().Files) diff --git a/pkg/gui/controllers/helpers/refresh_helper.go b/pkg/gui/controllers/helpers/refresh_helper.go index e267f8360..33347a363 100644 --- a/pkg/gui/controllers/helpers/refresh_helper.go +++ b/pkg/gui/controllers/helpers/refresh_helper.go @@ -554,11 +554,11 @@ func (self *RefreshHelper) refreshStateFiles() error { prevConflictFileCount++ } if file.HasInlineMergeConflicts { - hasConflicts, err := mergeconflicts.FileHasConflictMarkers(file.Name) + hasConflicts, err := mergeconflicts.FileHasConflictMarkers(file.Path) if err != nil { self.c.Log.Error(err) } else if !hasConflicts { - pathsToStage = append(pathsToStage, file.Name) + pathsToStage = append(pathsToStage, file.Path) } } } diff --git a/pkg/gui/filetree/build_tree.go b/pkg/gui/filetree/build_tree.go index 0193ba45c..1168b1a3d 100644 --- a/pkg/gui/filetree/build_tree.go +++ b/pkg/gui/filetree/build_tree.go @@ -14,7 +14,7 @@ func BuildTreeFromFiles(files []*models.File) *Node[models.File] { var curr *Node[models.File] for _, file := range files { - splitPath := split(file.Name) + splitPath := split("./" + file.Path) curr = root outer: for i := range splitPath { @@ -40,8 +40,13 @@ func BuildTreeFromFiles(files []*models.File) *Node[models.File] { continue outer } + if i == 0 && len(files) == 1 && len(splitPath) == 2 { + // skip the root item when there's only one file at top level; we don't need it in that case + continue outer + } + newChild := &Node[models.File]{ - Path: path, + path: path, File: setFile, } curr.Children = append(curr.Children, newChild) @@ -70,7 +75,7 @@ func BuildTreeFromCommitFiles(files []*models.CommitFile) *Node[models.CommitFil var curr *Node[models.CommitFile] for _, file := range files { - splitPath := split(file.Name) + splitPath := split("./" + file.Path) curr = root outer: for i := range splitPath { @@ -83,14 +88,19 @@ func BuildTreeFromCommitFiles(files []*models.CommitFile) *Node[models.CommitFil path := join(splitPath[:i+1]) for _, existingChild := range curr.Children { - if existingChild.Path == path { + if existingChild.path == path { curr = existingChild continue outer } } + if i == 0 && len(files) == 1 && len(splitPath) == 2 { + // skip the root item when there's only one file at top level; we don't need it in that case + continue outer + } + newChild := &Node[models.CommitFile]{ - Path: path, + path: path, File: setFile, } curr.Children = append(curr.Children, newChild) diff --git a/pkg/gui/filetree/build_tree_test.go b/pkg/gui/filetree/build_tree_test.go index eab8babc2..ca69a33cc 100644 --- a/pkg/gui/filetree/build_tree_test.go +++ b/pkg/gui/filetree/build_tree_test.go @@ -17,7 +17,7 @@ func TestBuildTreeFromFiles(t *testing.T) { name: "no files", files: []*models.File{}, expected: &Node[models.File]{ - Path: "", + path: "", Children: nil, }, }, @@ -25,25 +25,26 @@ func TestBuildTreeFromFiles(t *testing.T) { name: "files in same directory", files: []*models.File{ { - Name: "dir1/a", + Path: "dir1/a", }, { - Name: "dir1/b", + Path: "dir1/b", }, }, expected: &Node[models.File]{ - Path: "", + path: "", Children: []*Node[models.File]{ { - Path: "dir1", + path: "./dir1", + CompressionLevel: 1, Children: []*Node[models.File]{ { - File: &models.File{Name: "dir1/a"}, - Path: "dir1/a", + File: &models.File{Path: "dir1/a"}, + path: "./dir1/a", }, { - File: &models.File{Name: "dir1/b"}, - Path: "dir1/b", + File: &models.File{Path: "dir1/b"}, + path: "./dir1/b", }, }, }, @@ -54,34 +55,39 @@ func TestBuildTreeFromFiles(t *testing.T) { name: "paths that can be compressed", files: []*models.File{ { - Name: "dir1/dir3/a", + Path: "dir1/dir3/a", }, { - Name: "dir2/dir4/b", + Path: "dir2/dir4/b", }, }, expected: &Node[models.File]{ - Path: "", + path: "", Children: []*Node[models.File]{ { - Path: "dir1/dir3", + path: ".", Children: []*Node[models.File]{ { - File: &models.File{Name: "dir1/dir3/a"}, - Path: "dir1/dir3/a", + path: "./dir1/dir3", + Children: []*Node[models.File]{ + { + File: &models.File{Path: "dir1/dir3/a"}, + path: "./dir1/dir3/a", + }, + }, + CompressionLevel: 1, }, - }, - CompressionLevel: 1, - }, - { - Path: "dir2/dir4", - Children: []*Node[models.File]{ { - File: &models.File{Name: "dir2/dir4/b"}, - Path: "dir2/dir4/b", + path: "./dir2/dir4", + Children: []*Node[models.File]{ + { + File: &models.File{Path: "dir2/dir4/b"}, + path: "./dir2/dir4/b", + }, + }, + CompressionLevel: 1, }, }, - CompressionLevel: 1, }, }, }, @@ -90,22 +96,27 @@ func TestBuildTreeFromFiles(t *testing.T) { name: "paths that can be sorted", files: []*models.File{ { - Name: "b", + Path: "b", }, { - Name: "a", + Path: "a", }, }, expected: &Node[models.File]{ - Path: "", + path: "", Children: []*Node[models.File]{ { - File: &models.File{Name: "a"}, - Path: "a", - }, - { - File: &models.File{Name: "b"}, - Path: "b", + path: ".", + Children: []*Node[models.File]{ + { + File: &models.File{Path: "a"}, + path: "./a", + }, + { + File: &models.File{Path: "b"}, + path: "./b", + }, + }, }, }, }, @@ -114,32 +125,37 @@ func TestBuildTreeFromFiles(t *testing.T) { name: "paths that can be sorted including a merge conflict file", files: []*models.File{ { - Name: "b", + Path: "b", }, { - Name: "z", + Path: "z", HasMergeConflicts: true, }, { - Name: "a", + Path: "a", }, }, expected: &Node[models.File]{ - Path: "", - // it is a little strange that we're not bubbling up our merge conflict - // here but we are technically still in tree mode and that's the rule + path: "", Children: []*Node[models.File]{ { - File: &models.File{Name: "a"}, - Path: "a", - }, - { - File: &models.File{Name: "b"}, - Path: "b", - }, - { - File: &models.File{Name: "z", HasMergeConflicts: true}, - Path: "z", + path: ".", + // it is a little strange that we're not bubbling up our merge conflict + // here but we are technically still in tree mode and that's the rule + Children: []*Node[models.File]{ + { + File: &models.File{Path: "a"}, + path: "./a", + }, + { + File: &models.File{Path: "b"}, + path: "./b", + }, + { + File: &models.File{Path: "z", HasMergeConflicts: true}, + path: "./z", + }, + }, }, }, }, @@ -164,7 +180,7 @@ func TestBuildFlatTreeFromFiles(t *testing.T) { name: "no files", files: []*models.File{}, expected: &Node[models.File]{ - Path: "", + path: "", Children: []*Node[models.File]{}, }, }, @@ -172,23 +188,23 @@ func TestBuildFlatTreeFromFiles(t *testing.T) { name: "files in same directory", files: []*models.File{ { - Name: "dir1/a", + Path: "dir1/a", }, { - Name: "dir1/b", + Path: "dir1/b", }, }, expected: &Node[models.File]{ - Path: "", + path: "", Children: []*Node[models.File]{ { - File: &models.File{Name: "dir1/a"}, - Path: "dir1/a", + File: &models.File{Path: "dir1/a"}, + path: "./dir1/a", CompressionLevel: 0, }, { - File: &models.File{Name: "dir1/b"}, - Path: "dir1/b", + File: &models.File{Path: "dir1/b"}, + path: "./dir1/b", CompressionLevel: 0, }, }, @@ -198,23 +214,23 @@ func TestBuildFlatTreeFromFiles(t *testing.T) { name: "paths that can be compressed", files: []*models.File{ { - Name: "dir1/a", + Path: "dir1/a", }, { - Name: "dir2/b", + Path: "dir2/b", }, }, expected: &Node[models.File]{ - Path: "", + path: "", Children: []*Node[models.File]{ { - File: &models.File{Name: "dir1/a"}, - Path: "dir1/a", + File: &models.File{Path: "dir1/a"}, + path: "./dir1/a", CompressionLevel: 0, }, { - File: &models.File{Name: "dir2/b"}, - Path: "dir2/b", + File: &models.File{Path: "dir2/b"}, + path: "./dir2/b", CompressionLevel: 0, }, }, @@ -224,22 +240,22 @@ func TestBuildFlatTreeFromFiles(t *testing.T) { name: "paths that can be sorted", files: []*models.File{ { - Name: "b", + Path: "b", }, { - Name: "a", + Path: "a", }, }, expected: &Node[models.File]{ - Path: "", + path: "", Children: []*Node[models.File]{ { - File: &models.File{Name: "a"}, - Path: "a", + File: &models.File{Path: "a"}, + path: "./a", }, { - File: &models.File{Name: "b"}, - Path: "b", + File: &models.File{Path: "b"}, + path: "./b", }, }, }, @@ -248,56 +264,56 @@ func TestBuildFlatTreeFromFiles(t *testing.T) { name: "tracked, untracked, and conflicted files", files: []*models.File{ { - Name: "a2", + Path: "a2", Tracked: false, }, { - Name: "a1", + Path: "a1", Tracked: false, }, { - Name: "c2", + Path: "c2", HasMergeConflicts: true, }, { - Name: "c1", + Path: "c1", HasMergeConflicts: true, }, { - Name: "b2", + Path: "b2", Tracked: true, }, { - Name: "b1", + Path: "b1", Tracked: true, }, }, expected: &Node[models.File]{ - Path: "", + path: "", Children: []*Node[models.File]{ { - File: &models.File{Name: "c1", HasMergeConflicts: true}, - Path: "c1", + File: &models.File{Path: "c1", HasMergeConflicts: true}, + path: "./c1", }, { - File: &models.File{Name: "c2", HasMergeConflicts: true}, - Path: "c2", + File: &models.File{Path: "c2", HasMergeConflicts: true}, + path: "./c2", }, { - File: &models.File{Name: "b1", Tracked: true}, - Path: "b1", + File: &models.File{Path: "b1", Tracked: true}, + path: "./b1", }, { - File: &models.File{Name: "b2", Tracked: true}, - Path: "b2", + File: &models.File{Path: "b2", Tracked: true}, + path: "./b2", }, { - File: &models.File{Name: "a1", Tracked: false}, - Path: "a1", + File: &models.File{Path: "a1", Tracked: false}, + path: "./a1", }, { - File: &models.File{Name: "a2", Tracked: false}, - Path: "a2", + File: &models.File{Path: "a2", Tracked: false}, + path: "./a2", }, }, }, @@ -322,7 +338,7 @@ func TestBuildTreeFromCommitFiles(t *testing.T) { name: "no files", files: []*models.CommitFile{}, expected: &Node[models.CommitFile]{ - Path: "", + path: "", Children: nil, }, }, @@ -330,25 +346,26 @@ func TestBuildTreeFromCommitFiles(t *testing.T) { name: "files in same directory", files: []*models.CommitFile{ { - Name: "dir1/a", + Path: "dir1/a", }, { - Name: "dir1/b", + Path: "dir1/b", }, }, expected: &Node[models.CommitFile]{ - Path: "", + path: "", Children: []*Node[models.CommitFile]{ { - Path: "dir1", + path: "./dir1", + CompressionLevel: 1, Children: []*Node[models.CommitFile]{ { - File: &models.CommitFile{Name: "dir1/a"}, - Path: "dir1/a", + File: &models.CommitFile{Path: "dir1/a"}, + path: "./dir1/a", }, { - File: &models.CommitFile{Name: "dir1/b"}, - Path: "dir1/b", + File: &models.CommitFile{Path: "dir1/b"}, + path: "./dir1/b", }, }, }, @@ -359,34 +376,39 @@ func TestBuildTreeFromCommitFiles(t *testing.T) { name: "paths that can be compressed", files: []*models.CommitFile{ { - Name: "dir1/dir3/a", + Path: "dir1/dir3/a", }, { - Name: "dir2/dir4/b", + Path: "dir2/dir4/b", }, }, expected: &Node[models.CommitFile]{ - Path: "", + path: "", Children: []*Node[models.CommitFile]{ { - Path: "dir1/dir3", + path: ".", Children: []*Node[models.CommitFile]{ { - File: &models.CommitFile{Name: "dir1/dir3/a"}, - Path: "dir1/dir3/a", + path: "./dir1/dir3", + Children: []*Node[models.CommitFile]{ + { + File: &models.CommitFile{Path: "dir1/dir3/a"}, + path: "./dir1/dir3/a", + }, + }, + CompressionLevel: 1, }, - }, - CompressionLevel: 1, - }, - { - Path: "dir2/dir4", - Children: []*Node[models.CommitFile]{ { - File: &models.CommitFile{Name: "dir2/dir4/b"}, - Path: "dir2/dir4/b", + path: "./dir2/dir4", + Children: []*Node[models.CommitFile]{ + { + File: &models.CommitFile{Path: "dir2/dir4/b"}, + path: "./dir2/dir4/b", + }, + }, + CompressionLevel: 1, }, }, - CompressionLevel: 1, }, }, }, @@ -395,22 +417,27 @@ func TestBuildTreeFromCommitFiles(t *testing.T) { name: "paths that can be sorted", files: []*models.CommitFile{ { - Name: "b", + Path: "b", }, { - Name: "a", + Path: "a", }, }, expected: &Node[models.CommitFile]{ - Path: "", + path: "", Children: []*Node[models.CommitFile]{ { - File: &models.CommitFile{Name: "a"}, - Path: "a", - }, - { - File: &models.CommitFile{Name: "b"}, - Path: "b", + path: ".", + Children: []*Node[models.CommitFile]{ + { + File: &models.CommitFile{Path: "a"}, + path: "./a", + }, + { + File: &models.CommitFile{Path: "b"}, + path: "./b", + }, + }, }, }, }, @@ -435,7 +462,7 @@ func TestBuildFlatTreeFromCommitFiles(t *testing.T) { name: "no files", files: []*models.CommitFile{}, expected: &Node[models.CommitFile]{ - Path: "", + path: "", Children: []*Node[models.CommitFile]{}, }, }, @@ -443,23 +470,23 @@ func TestBuildFlatTreeFromCommitFiles(t *testing.T) { name: "files in same directory", files: []*models.CommitFile{ { - Name: "dir1/a", + Path: "dir1/a", }, { - Name: "dir1/b", + Path: "dir1/b", }, }, expected: &Node[models.CommitFile]{ - Path: "", + path: "", Children: []*Node[models.CommitFile]{ { - File: &models.CommitFile{Name: "dir1/a"}, - Path: "dir1/a", + File: &models.CommitFile{Path: "dir1/a"}, + path: "./dir1/a", CompressionLevel: 0, }, { - File: &models.CommitFile{Name: "dir1/b"}, - Path: "dir1/b", + File: &models.CommitFile{Path: "dir1/b"}, + path: "./dir1/b", CompressionLevel: 0, }, }, @@ -469,23 +496,23 @@ func TestBuildFlatTreeFromCommitFiles(t *testing.T) { name: "paths that can be compressed", files: []*models.CommitFile{ { - Name: "dir1/a", + Path: "dir1/a", }, { - Name: "dir2/b", + Path: "dir2/b", }, }, expected: &Node[models.CommitFile]{ - Path: "", + path: "", Children: []*Node[models.CommitFile]{ { - File: &models.CommitFile{Name: "dir1/a"}, - Path: "dir1/a", + File: &models.CommitFile{Path: "dir1/a"}, + path: "./dir1/a", CompressionLevel: 0, }, { - File: &models.CommitFile{Name: "dir2/b"}, - Path: "dir2/b", + File: &models.CommitFile{Path: "dir2/b"}, + path: "./dir2/b", CompressionLevel: 0, }, }, @@ -495,22 +522,22 @@ func TestBuildFlatTreeFromCommitFiles(t *testing.T) { name: "paths that can be sorted", files: []*models.CommitFile{ { - Name: "b", + Path: "b", }, { - Name: "a", + Path: "a", }, }, expected: &Node[models.CommitFile]{ - Path: "", + path: "", Children: []*Node[models.CommitFile]{ { - File: &models.CommitFile{Name: "a"}, - Path: "a", + File: &models.CommitFile{Path: "a"}, + path: "./a", }, { - File: &models.CommitFile{Name: "b"}, - Path: "b", + File: &models.CommitFile{Path: "b"}, + path: "./b", }, }, }, diff --git a/pkg/gui/filetree/commit_file_tree.go b/pkg/gui/filetree/commit_file_tree.go index 9c8e0bf52..48b07e393 100644 --- a/pkg/gui/filetree/commit_file_tree.go +++ b/pkg/gui/filetree/commit_file_tree.go @@ -27,7 +27,7 @@ type CommitFileTree struct { func (self *CommitFileTree) CollapseAll() { dirPaths := lo.FilterMap(self.GetAllItems(), func(file *CommitFileNode, index int) (string, bool) { - return file.Path, !file.IsFile() + return file.path, !file.IsFile() }) for _, path := range dirPaths { @@ -119,7 +119,7 @@ func (self *CommitFileTree) CollapsedPaths() *CollapsedPaths { func (self *CommitFileTree) GetFile(path string) *models.CommitFile { for _, file := range self.getFiles() { - if file.Name == path { + if file.Path == path { return file } } diff --git a/pkg/gui/filetree/commit_file_tree_view_model.go b/pkg/gui/filetree/commit_file_tree_view_model.go index 81f1427b8..e95aed7ca 100644 --- a/pkg/gui/filetree/commit_file_tree_view_model.go +++ b/pkg/gui/filetree/commit_file_tree_view_model.go @@ -148,12 +148,12 @@ func (self *CommitFileTreeViewModel) ToggleShowTree() { if selectedNode == nil { return } - path := selectedNode.Path + path := selectedNode.path if self.InTreeMode() { self.ExpandToPath(path) } else if len(selectedNode.Children) > 0 { - path = selectedNode.GetLeaves()[0].Path + path = selectedNode.GetLeaves()[0].path } index, found := self.GetIndexForPath(path) @@ -170,7 +170,7 @@ func (self *CommitFileTreeViewModel) CollapseAll() { return } - topLevelPath := strings.Split(selectedNode.Path, "/")[0] + topLevelPath := strings.Split(selectedNode.path, "/")[0] index, found := self.GetIndexForPath(topLevelPath) if found { self.SetSelectedLineIdx(index) @@ -186,7 +186,7 @@ func (self *CommitFileTreeViewModel) ExpandAll() { return } - index, found := self.GetIndexForPath(selectedNode.Path) + index, found := self.GetIndexForPath(selectedNode.path) if found { self.SetSelectedLineIdx(index) } diff --git a/pkg/gui/filetree/file_node.go b/pkg/gui/filetree/file_node.go index d55bc56aa..0836eaf02 100644 --- a/pkg/gui/filetree/file_node.go +++ b/pkg/gui/filetree/file_node.go @@ -51,7 +51,7 @@ func (self *FileNode) GetHasInlineMergeConflicts() bool { if !file.HasInlineMergeConflicts { return false } - hasConflicts, _ := mergeconflicts.FileHasConflictMarkers(file.Name) + hasConflicts, _ := mergeconflicts.FileHasConflictMarkers(file.Path) return hasConflicts }) } @@ -69,5 +69,5 @@ func (self *FileNode) GetPreviousPath() string { return "" } - return self.File.PreviousName + return self.File.PreviousPath } diff --git a/pkg/gui/filetree/file_node_test.go b/pkg/gui/filetree/file_node_test.go index c32f0e666..87d62bf86 100644 --- a/pkg/gui/filetree/file_node_test.go +++ b/pkg/gui/filetree/file_node_test.go @@ -21,103 +21,103 @@ func TestCompress(t *testing.T) { { name: "leaf node", root: &Node[models.File]{ - Path: "", + path: "", Children: []*Node[models.File]{ - {File: &models.File{Name: "test", ShortStatus: " M", HasStagedChanges: true}, Path: "test"}, + {File: &models.File{Path: "test", ShortStatus: " M", HasStagedChanges: true}, path: "test"}, }, }, expected: &Node[models.File]{ - Path: "", + path: "", Children: []*Node[models.File]{ - {File: &models.File{Name: "test", ShortStatus: " M", HasStagedChanges: true}, Path: "test"}, + {File: &models.File{Path: "test", ShortStatus: " M", HasStagedChanges: true}, path: "test"}, }, }, }, { name: "big example", root: &Node[models.File]{ - Path: "", + path: "", Children: []*Node[models.File]{ { - Path: "dir1", + path: "dir1", Children: []*Node[models.File]{ { - File: &models.File{Name: "file2", ShortStatus: "M ", HasUnstagedChanges: true}, - Path: "dir1/file2", + File: &models.File{Path: "file2", ShortStatus: "M ", HasUnstagedChanges: true}, + path: "dir1/file2", }, }, }, { - Path: "dir2", + path: "dir2", Children: []*Node[models.File]{ { - File: &models.File{Name: "file3", ShortStatus: " M", HasStagedChanges: true}, - Path: "dir2/file3", + File: &models.File{Path: "file3", ShortStatus: " M", HasStagedChanges: true}, + path: "dir2/file3", }, { - File: &models.File{Name: "file4", ShortStatus: "M ", HasUnstagedChanges: true}, - Path: "dir2/file4", + File: &models.File{Path: "file4", ShortStatus: "M ", HasUnstagedChanges: true}, + path: "dir2/file4", }, }, }, { - Path: "dir3", + path: "dir3", Children: []*Node[models.File]{ { - Path: "dir3/dir3-1", + path: "dir3/dir3-1", Children: []*Node[models.File]{ { - File: &models.File{Name: "file5", ShortStatus: "M ", HasUnstagedChanges: true}, - Path: "dir3/dir3-1/file5", + File: &models.File{Path: "file5", ShortStatus: "M ", HasUnstagedChanges: true}, + path: "dir3/dir3-1/file5", }, }, }, }, }, { - File: &models.File{Name: "file1", ShortStatus: "M ", HasUnstagedChanges: true}, - Path: "file1", + File: &models.File{Path: "file1", ShortStatus: "M ", HasUnstagedChanges: true}, + path: "file1", }, }, }, expected: &Node[models.File]{ - Path: "", + path: "", Children: []*Node[models.File]{ { - Path: "dir1", + path: "dir1", Children: []*Node[models.File]{ { - File: &models.File{Name: "file2", ShortStatus: "M ", HasUnstagedChanges: true}, - Path: "dir1/file2", + File: &models.File{Path: "file2", ShortStatus: "M ", HasUnstagedChanges: true}, + path: "dir1/file2", }, }, }, { - Path: "dir2", + path: "dir2", Children: []*Node[models.File]{ { - File: &models.File{Name: "file3", ShortStatus: " M", HasStagedChanges: true}, - Path: "dir2/file3", + File: &models.File{Path: "file3", ShortStatus: " M", HasStagedChanges: true}, + path: "dir2/file3", }, { - File: &models.File{Name: "file4", ShortStatus: "M ", HasUnstagedChanges: true}, - Path: "dir2/file4", + File: &models.File{Path: "file4", ShortStatus: "M ", HasUnstagedChanges: true}, + path: "dir2/file4", }, }, }, { - Path: "dir3/dir3-1", + path: "dir3/dir3-1", CompressionLevel: 1, Children: []*Node[models.File]{ { - File: &models.File{Name: "file5", ShortStatus: "M ", HasUnstagedChanges: true}, - Path: "dir3/dir3-1/file5", + File: &models.File{Path: "file5", ShortStatus: "M ", HasUnstagedChanges: true}, + path: "dir3/dir3-1/file5", }, }, }, { - File: &models.File{Name: "file1", ShortStatus: "M ", HasUnstagedChanges: true}, - Path: "file1", + File: &models.File{Path: "file1", ShortStatus: "M ", HasUnstagedChanges: true}, + path: "file1", }, }, }, @@ -141,13 +141,13 @@ func TestGetFile(t *testing.T) { }{ { name: "valid case", - viewModel: NewFileTree(func() []*models.File { return []*models.File{{Name: "blah/one"}, {Name: "blah/two"}} }, nil, false), + viewModel: NewFileTree(func() []*models.File { return []*models.File{{Path: "blah/one"}, {Path: "blah/two"}} }, nil, false), path: "blah/two", - expected: &models.File{Name: "blah/two"}, + expected: &models.File{Path: "blah/two"}, }, { name: "not found", - viewModel: NewFileTree(func() []*models.File { return []*models.File{{Name: "blah/one"}, {Name: "blah/two"}} }, nil, false), + viewModel: NewFileTree(func() []*models.File { return []*models.File{{Path: "blah/one"}, {Path: "blah/two"}} }, nil, false), path: "blah/three", expected: nil, }, diff --git a/pkg/gui/filetree/file_tree.go b/pkg/gui/filetree/file_tree.go index fe18db0c0..2dbaa77fb 100644 --- a/pkg/gui/filetree/file_tree.go +++ b/pkg/gui/filetree/file_tree.go @@ -125,7 +125,7 @@ func (self *FileTree) Get(index int) *FileNode { func (self *FileTree) GetFile(path string) *models.File { for _, file := range self.getFiles() { - if file.Name == path { + if file.Path == path { return file } } @@ -185,7 +185,7 @@ func (self *FileTree) ToggleCollapsed(path string) { func (self *FileTree) CollapseAll() { dirPaths := lo.FilterMap(self.GetAllItems(), func(file *FileNode, index int) (string, bool) { - return file.Path, !file.IsFile() + return file.path, !file.IsFile() }) for _, path := range dirPaths { diff --git a/pkg/gui/filetree/file_tree_test.go b/pkg/gui/filetree/file_tree_test.go index a3cdfd966..4a593711c 100644 --- a/pkg/gui/filetree/file_tree_test.go +++ b/pkg/gui/filetree/file_tree_test.go @@ -18,67 +18,67 @@ func TestFilterAction(t *testing.T) { name: "filter files with unstaged changes", filter: DisplayUnstaged, files: []*models.File{ - {Name: "dir2/dir2/file4", ShortStatus: "M ", HasUnstagedChanges: true}, - {Name: "dir2/file5", ShortStatus: "M ", HasStagedChanges: true}, - {Name: "file1", ShortStatus: "M ", HasUnstagedChanges: true}, + {Path: "dir2/dir2/file4", ShortStatus: "M ", HasUnstagedChanges: true}, + {Path: "dir2/file5", ShortStatus: "M ", HasStagedChanges: true}, + {Path: "file1", ShortStatus: "M ", HasUnstagedChanges: true}, }, expected: []*models.File{ - {Name: "dir2/dir2/file4", ShortStatus: "M ", HasUnstagedChanges: true}, - {Name: "file1", ShortStatus: "M ", HasUnstagedChanges: true}, + {Path: "dir2/dir2/file4", ShortStatus: "M ", HasUnstagedChanges: true}, + {Path: "file1", ShortStatus: "M ", HasUnstagedChanges: true}, }, }, { name: "filter files with staged changes", filter: DisplayStaged, files: []*models.File{ - {Name: "dir2/dir2/file4", ShortStatus: "M ", HasStagedChanges: true}, - {Name: "dir2/file5", ShortStatus: "M ", HasStagedChanges: false}, - {Name: "file1", ShortStatus: "M ", HasStagedChanges: true}, + {Path: "dir2/dir2/file4", ShortStatus: "M ", HasStagedChanges: true}, + {Path: "dir2/file5", ShortStatus: "M ", HasStagedChanges: false}, + {Path: "file1", ShortStatus: "M ", HasStagedChanges: true}, }, expected: []*models.File{ - {Name: "dir2/dir2/file4", ShortStatus: "M ", HasStagedChanges: true}, - {Name: "file1", ShortStatus: "M ", HasStagedChanges: true}, + {Path: "dir2/dir2/file4", ShortStatus: "M ", HasStagedChanges: true}, + {Path: "file1", ShortStatus: "M ", HasStagedChanges: true}, }, }, { name: "filter files that are tracked", filter: DisplayTracked, files: []*models.File{ - {Name: "dir2/dir2/file4", ShortStatus: "M ", Tracked: true}, - {Name: "dir2/file5", ShortStatus: "M ", Tracked: false}, - {Name: "file1", ShortStatus: "M ", Tracked: true}, + {Path: "dir2/dir2/file4", ShortStatus: "M ", Tracked: true}, + {Path: "dir2/file5", ShortStatus: "M ", Tracked: false}, + {Path: "file1", ShortStatus: "M ", Tracked: true}, }, expected: []*models.File{ - {Name: "dir2/dir2/file4", ShortStatus: "M ", Tracked: true}, - {Name: "file1", ShortStatus: "M ", Tracked: true}, + {Path: "dir2/dir2/file4", ShortStatus: "M ", Tracked: true}, + {Path: "file1", ShortStatus: "M ", Tracked: true}, }, }, { name: "filter all files", filter: DisplayAll, files: []*models.File{ - {Name: "dir2/dir2/file4", ShortStatus: "M ", HasUnstagedChanges: true}, - {Name: "dir2/file5", ShortStatus: "M ", HasUnstagedChanges: true}, - {Name: "file1", ShortStatus: "M ", HasUnstagedChanges: true}, + {Path: "dir2/dir2/file4", ShortStatus: "M ", HasUnstagedChanges: true}, + {Path: "dir2/file5", ShortStatus: "M ", HasUnstagedChanges: true}, + {Path: "file1", ShortStatus: "M ", HasUnstagedChanges: true}, }, expected: []*models.File{ - {Name: "dir2/dir2/file4", ShortStatus: "M ", HasUnstagedChanges: true}, - {Name: "dir2/file5", ShortStatus: "M ", HasUnstagedChanges: true}, - {Name: "file1", ShortStatus: "M ", HasUnstagedChanges: true}, + {Path: "dir2/dir2/file4", ShortStatus: "M ", HasUnstagedChanges: true}, + {Path: "dir2/file5", ShortStatus: "M ", HasUnstagedChanges: true}, + {Path: "file1", ShortStatus: "M ", HasUnstagedChanges: true}, }, }, { name: "filter conflicted files", filter: DisplayConflicted, files: []*models.File{ - {Name: "dir2/dir2/file4", ShortStatus: "DU", HasMergeConflicts: true}, - {Name: "dir2/file5", ShortStatus: "M ", HasUnstagedChanges: true}, - {Name: "dir2/file6", ShortStatus: " M", HasStagedChanges: true}, - {Name: "file1", ShortStatus: "UU", HasMergeConflicts: true, HasInlineMergeConflicts: true}, + {Path: "dir2/dir2/file4", ShortStatus: "DU", HasMergeConflicts: true}, + {Path: "dir2/file5", ShortStatus: "M ", HasUnstagedChanges: true}, + {Path: "dir2/file6", ShortStatus: " M", HasStagedChanges: true}, + {Path: "file1", ShortStatus: "UU", HasMergeConflicts: true, HasInlineMergeConflicts: true}, }, expected: []*models.File{ - {Name: "dir2/dir2/file4", ShortStatus: "DU", HasMergeConflicts: true}, - {Name: "file1", ShortStatus: "UU", HasMergeConflicts: true, HasInlineMergeConflicts: true}, + {Path: "dir2/dir2/file4", ShortStatus: "DU", HasMergeConflicts: true}, + {Path: "file1", ShortStatus: "UU", HasMergeConflicts: true, HasInlineMergeConflicts: true}, }, }, } diff --git a/pkg/gui/filetree/file_tree_view_model.go b/pkg/gui/filetree/file_tree_view_model.go index 29f563834..4916a7906 100644 --- a/pkg/gui/filetree/file_tree_view_model.go +++ b/pkg/gui/filetree/file_tree_view_model.go @@ -103,8 +103,8 @@ func (self *FileTreeViewModel) SetTree() { // for when you stage the old file of a rename and the new file is in a collapsed dir for _, file := range newFiles { - if selectedNode != nil && selectedNode.Path != "" && file.PreviousName == selectedNode.Path { - self.ExpandToPath(file.Name) + if selectedNode != nil && selectedNode.path != "" && file.PreviousPath == selectedNode.path { + self.ExpandToPath(file.Path) } } @@ -139,7 +139,7 @@ func (self *FileTreeViewModel) findNewSelectedIdx(prevNodes []*FileNode, currNod if node.File != nil && node.File.IsRename() { return node.File.Names() } else { - return []string{node.Path} + return []string{node.path} } } @@ -151,7 +151,7 @@ func (self *FileTreeViewModel) findNewSelectedIdx(prevNodes []*FileNode, currNod // If you started off with a rename selected, and now it's broken in two, we want you to jump to the new file, not the old file. // This is because the new should be in the same position as the rename was meaning less cursor jumping - foundOldFileInRename := prevNode.File != nil && prevNode.File.IsRename() && node.Path == prevNode.File.PreviousName + foundOldFileInRename := prevNode.File != nil && prevNode.File.IsRename() && node.path == prevNode.File.PreviousPath foundNode := utils.StringArraysOverlap(paths, selectedPaths) && !foundOldFileInRename if foundNode { return idx @@ -178,12 +178,12 @@ func (self *FileTreeViewModel) ToggleShowTree() { if selectedNode == nil { return } - path := selectedNode.Path + path := selectedNode.path if self.InTreeMode() { self.ExpandToPath(path) } else if len(selectedNode.Children) > 0 { - path = selectedNode.GetLeaves()[0].Path + path = selectedNode.GetLeaves()[0].path } index, found := self.GetIndexForPath(path) @@ -200,7 +200,7 @@ func (self *FileTreeViewModel) CollapseAll() { return } - topLevelPath := strings.Split(selectedNode.Path, "/")[0] + topLevelPath := strings.Split(selectedNode.path, "/")[0] index, found := self.GetIndexForPath(topLevelPath) if found { self.SetSelectedLineIdx(index) @@ -216,7 +216,7 @@ func (self *FileTreeViewModel) ExpandAll() { return } - index, found := self.GetIndexForPath(selectedNode.Path) + index, found := self.GetIndexForPath(selectedNode.path) if found { self.SetSelectedLineIdx(index) } diff --git a/pkg/gui/filetree/node.go b/pkg/gui/filetree/node.go index dddafde27..d46025a0a 100644 --- a/pkg/gui/filetree/node.go +++ b/pkg/gui/filetree/node.go @@ -20,7 +20,8 @@ type Node[T any] struct { Children []*Node[T] // path of the file/directory - Path string + // private; use either GetPath() or GetInternalPath() to access + path string // rather than render a tree as: // a/ @@ -46,8 +47,20 @@ func (self *Node[T]) GetFile() *T { return self.File } +// This returns the logical path from the user's point of view. It is the +// relative path from the root of the repository. +// Use this for display, or when you want to perform some action on the path +// (e.g. a git command). func (self *Node[T]) GetPath() string { - return self.Path + return strings.TrimPrefix(self.path, "./") +} + +// This returns the internal path from the tree's point of view. It's the same +// as GetPath(), but prefixed with "./" for the root item. +// Use this when interacting with the tree itself, e.g. when calling +// ToggleCollapsed. +func (self *Node[T]) GetInternalPath() string { + return self.path } func (self *Node[T]) Sort() { @@ -89,7 +102,7 @@ func (self *Node[T]) SortChildren() { return 1 } - return strings.Compare(a.GetPath(), b.GetPath()) + return strings.Compare(a.path, b.path) }) // TODO: think about making this in-place @@ -159,7 +172,7 @@ func (self *Node[T]) EveryFile(test func(*T) bool) bool { func (self *Node[T]) Flatten(collapsedPaths *CollapsedPaths) []*Node[T] { result := []*Node[T]{self} - if len(self.Children) > 0 && !collapsedPaths.IsCollapsed(self.GetPath()) { + if len(self.Children) > 0 && !collapsedPaths.IsCollapsed(self.path) { result = append(result, lo.FlatMap(self.Children, func(child *Node[T], _ int) []*Node[T] { return child.Flatten(collapsedPaths) })...) @@ -185,7 +198,7 @@ func (self *Node[T]) getNodeAtIndexAux(index int, collapsedPaths *CollapsedPaths return self, offset } - if !collapsedPaths.IsCollapsed(self.GetPath()) { + if !collapsedPaths.IsCollapsed(self.path) { for _, child := range self.Children { foundNode, offsetChange := child.getNodeAtIndexAux(index-offset, collapsedPaths) offset += offsetChange @@ -201,11 +214,11 @@ func (self *Node[T]) getNodeAtIndexAux(index int, collapsedPaths *CollapsedPaths func (self *Node[T]) GetIndexForPath(path string, collapsedPaths *CollapsedPaths) (int, bool) { offset := 0 - if self.GetPath() == path { + if self.path == path { return offset, true } - if !collapsedPaths.IsCollapsed(self.GetPath()) { + if !collapsedPaths.IsCollapsed(self.path) { for _, child := range self.Children { offsetChange, found := child.GetIndexForPath(path, collapsedPaths) offset += offsetChange + 1 @@ -225,7 +238,7 @@ func (self *Node[T]) Size(collapsedPaths *CollapsedPaths) int { output := 1 - if !collapsedPaths.IsCollapsed(self.GetPath()) { + if !collapsedPaths.IsCollapsed(self.path) { for _, child := range self.Children { output += child.Size(collapsedPaths) } @@ -309,5 +322,5 @@ func (self *Node[T]) Description() string { } func (self *Node[T]) Name() string { - return path.Base(self.Path) + return path.Base(self.path) } diff --git a/pkg/gui/presentation/files.go b/pkg/gui/presentation/files.go index b3123fe32..2b1f3fafa 100644 --- a/pkg/gui/presentation/files.go +++ b/pkg/gui/presentation/files.go @@ -52,11 +52,11 @@ func commitFilePatchStatus(node *filetree.Node[models.CommitFile], tree *filetre // be whatever status it is, but if it's a non-leaf it will determine its status // based on the leaves of that subtree if node.EveryFile(func(file *models.CommitFile) bool { - return patchBuilder.GetFileStatus(file.Name, tree.GetRef().RefName()) == patch.WHOLE + return patchBuilder.GetFileStatus(file.Path, tree.GetRef().RefName()) == patch.WHOLE }) { return patch.WHOLE } else if node.EveryFile(func(file *models.CommitFile) bool { - return patchBuilder.GetFileStatus(file.Name, tree.GetRef().RefName()) == patch.UNSELECTED + return patchBuilder.GetFileStatus(file.Path, tree.GetRef().RefName()) == patch.UNSELECTED }) { return patch.UNSELECTED } else { @@ -91,11 +91,11 @@ func renderAux[T any]( arr := []string{} if !isRoot { - isCollapsed := collapsedPaths.IsCollapsed(node.GetPath()) + isCollapsed := collapsedPaths.IsCollapsed(node.GetInternalPath()) arr = append(arr, renderLine(node, treeDepth, visualDepth, isCollapsed)) } - if collapsedPaths.IsCollapsed(node.GetPath()) { + if collapsedPaths.IsCollapsed(node.GetInternalPath()) { return arr } @@ -293,13 +293,19 @@ func getColorForChangeStatus(changeStatus string) style.TextStyle { } func fileNameAtDepth(node *filetree.Node[models.File], depth int) string { - splitName := split(node.Path) + splitName := split(node.GetInternalPath()) + if depth == 0 && splitName[0] == "." { + if len(splitName) == 1 { + return "/" + } + depth = 1 + } name := join(splitName[depth:]) if node.File != nil && node.File.IsRename() { - splitPrevName := split(node.File.PreviousName) + splitPrevName := split(node.File.PreviousPath) - prevName := node.File.PreviousName + prevName := node.File.PreviousPath // 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 := len(splitName) == len(splitPrevName) && join(splitName[0:depth]) == join(splitPrevName[0:depth]) @@ -314,7 +320,13 @@ func fileNameAtDepth(node *filetree.Node[models.File], depth int) string { } func commitFileNameAtDepth(node *filetree.Node[models.CommitFile], depth int) string { - splitName := split(node.Path) + splitName := split(node.GetInternalPath()) + if depth == 0 && splitName[0] == "." { + if len(splitName) == 1 { + return "/" + } + depth = 1 + } name := join(splitName[depth:]) return name diff --git a/pkg/gui/presentation/files_test.go b/pkg/gui/presentation/files_test.go index a6cdbf99d..858b836d8 100644 --- a/pkg/gui/presentation/files_test.go +++ b/pkg/gui/presentation/files_test.go @@ -34,48 +34,50 @@ func TestRenderFileTree(t *testing.T) { { name: "leaf node", files: []*models.File{ - {Name: "test", ShortStatus: " M", HasStagedChanges: true}, + {Path: "test", ShortStatus: " M", HasStagedChanges: true}, }, expected: []string{" M test"}, }, { name: "numstat", files: []*models.File{ - {Name: "test", ShortStatus: " M", HasStagedChanges: true, LinesAdded: 1, LinesDeleted: 1}, - {Name: "test2", ShortStatus: " M", HasStagedChanges: true, LinesAdded: 1}, - {Name: "test3", ShortStatus: " M", HasStagedChanges: true, LinesDeleted: 1}, - {Name: "test4", ShortStatus: " M", HasStagedChanges: true, LinesAdded: 0, LinesDeleted: 0}, + {Path: "test", ShortStatus: " M", HasStagedChanges: true, LinesAdded: 1, LinesDeleted: 1}, + {Path: "test2", ShortStatus: " M", HasStagedChanges: true, LinesAdded: 1}, + {Path: "test3", ShortStatus: " M", HasStagedChanges: true, LinesDeleted: 1}, + {Path: "test4", ShortStatus: " M", HasStagedChanges: true, LinesAdded: 0, LinesDeleted: 0}, }, showLineChanges: true, expected: []string{ - " M test +1 -1", - " M test2 +1", - " M test3 -1", - " M test4", + "▼ /", + " M test +1 -1", + " M test2 +1", + " M test3 -1", + " M test4", }, }, { name: "big example", files: []*models.File{ - {Name: "dir1/file2", ShortStatus: "M ", HasUnstagedChanges: true}, - {Name: "dir1/file3", ShortStatus: "M ", HasUnstagedChanges: true}, - {Name: "dir2/dir2/file3", ShortStatus: " M", HasStagedChanges: true}, - {Name: "dir2/dir2/file4", ShortStatus: "M ", HasUnstagedChanges: true}, - {Name: "dir2/file5", ShortStatus: "M ", HasUnstagedChanges: true}, - {Name: "file1", ShortStatus: "M ", HasUnstagedChanges: true}, + {Path: "dir1/file2", ShortStatus: "M ", HasUnstagedChanges: true}, + {Path: "dir1/file3", ShortStatus: "M ", HasUnstagedChanges: true}, + {Path: "dir2/dir2/file3", ShortStatus: " M", HasStagedChanges: true}, + {Path: "dir2/dir2/file4", ShortStatus: "M ", HasUnstagedChanges: true}, + {Path: "dir2/file5", ShortStatus: "M ", HasUnstagedChanges: true}, + {Path: "file1", ShortStatus: "M ", HasUnstagedChanges: true}, }, expected: toStringSlice( ` -▶ dir1 -▼ dir2 +▼ / + ▶ dir1 ▼ dir2 - M file3 - M file4 - M file5 -M file1 + ▼ dir2 + M file3 + M file4 + M file5 + M file1 `, ), - collapsedPaths: []string{"dir1"}, + collapsedPaths: []string{"./dir1"}, }, } @@ -111,32 +113,33 @@ func TestRenderCommitFileTree(t *testing.T) { { name: "leaf node", files: []*models.CommitFile{ - {Name: "test", ChangeStatus: "A"}, + {Path: "test", ChangeStatus: "A"}, }, expected: []string{"A test"}, }, { name: "big example", files: []*models.CommitFile{ - {Name: "dir1/file2", ChangeStatus: "M"}, - {Name: "dir1/file3", ChangeStatus: "A"}, - {Name: "dir2/dir2/file3", ChangeStatus: "D"}, - {Name: "dir2/dir2/file4", ChangeStatus: "M"}, - {Name: "dir2/file5", ChangeStatus: "M"}, - {Name: "file1", ChangeStatus: "M"}, + {Path: "dir1/file2", ChangeStatus: "M"}, + {Path: "dir1/file3", ChangeStatus: "A"}, + {Path: "dir2/dir2/file3", ChangeStatus: "D"}, + {Path: "dir2/dir2/file4", ChangeStatus: "M"}, + {Path: "dir2/file5", ChangeStatus: "M"}, + {Path: "file1", ChangeStatus: "M"}, }, expected: toStringSlice( ` -▶ dir1 -▼ dir2 +▼ / + ▶ dir1 ▼ dir2 - D file3 - M file4 - M file5 -M file1 + ▼ dir2 + D file3 + M file4 + M file5 + M file1 `, ), - collapsedPaths: []string{"dir1"}, + collapsedPaths: []string{"./dir1"}, }, } diff --git a/pkg/gui/services/custom_commands/session_state_loader.go b/pkg/gui/services/custom_commands/session_state_loader.go index 8d6ef5b48..933a99711 100644 --- a/pkg/gui/services/custom_commands/session_state_loader.go +++ b/pkg/gui/services/custom_commands/session_state_loader.go @@ -47,8 +47,8 @@ func fileShimFromModelFile(file *models.File) *File { } return &File{ - Name: file.Name, - PreviousName: file.PreviousName, + Name: file.Path, + PreviousName: file.PreviousPath, HasStagedChanges: file.HasStagedChanges, HasUnstagedChanges: file.HasUnstagedChanges, Tracked: file.Tracked, @@ -141,7 +141,7 @@ func commitFileShimFromModelRemote(commitFile *models.CommitFile) *CommitFile { } return &CommitFile{ - Name: commitFile.Name, + Name: commitFile.Path, ChangeStatus: commitFile.ChangeStatus, } } diff --git a/pkg/integration/tests/branch/reset_to_upstream.go b/pkg/integration/tests/branch/reset_to_upstream.go index c2ca41f4a..18f04257e 100644 --- a/pkg/integration/tests/branch/reset_to_upstream.go +++ b/pkg/integration/tests/branch/reset_to_upstream.go @@ -72,8 +72,9 @@ var ResetToUpstream = NewIntegrationTest(NewIntegrationTestArgs{ Contains("hard commit"), ) t.Views().Files().Lines( - Contains("file-1").Contains("A"), - Contains("file-2").Contains("A"), + Equals("▼ /"), + Equals(" A file-1"), + Equals(" A file-2"), ) // hard reset diff --git a/pkg/integration/tests/commit/commit.go b/pkg/integration/tests/commit/commit.go index 3737f2e1c..c9599f4e0 100644 --- a/pkg/integration/tests/commit/commit.go +++ b/pkg/integration/tests/commit/commit.go @@ -21,19 +21,23 @@ var Commit = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). IsFocused(). Lines( - Contains("?? myfile").IsSelected(), - Contains("?? myfile2"), + Equals("▼ /").IsSelected(), + Equals(" ?? myfile"), + Equals(" ?? myfile2"), ). + SelectNextItem(). PressPrimaryAction(). // stage file Lines( - Contains("A myfile").IsSelected(), - Contains("?? myfile2"), + Equals("▼ /"), + Equals(" A myfile").IsSelected(), + Equals(" ?? myfile2"), ). SelectNextItem(). PressPrimaryAction(). // stage other file Lines( - Contains("A myfile"), - Contains("A myfile2").IsSelected(), + Equals("▼ /"), + Equals(" A myfile"), + Equals(" A myfile2").IsSelected(), ). Press(keys.Files.CommitChanges) @@ -54,8 +58,9 @@ var Commit = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().CommitFiles(). IsFocused(). Lines( - Contains("A myfile"), - Contains("A myfile2"), + Equals("▼ /"), + Equals(" A myfile"), + Equals(" A myfile2"), ) }, }) diff --git a/pkg/integration/tests/commit/commit_switch_to_editor.go b/pkg/integration/tests/commit/commit_switch_to_editor.go index 069384ab1..b3c82aadc 100644 --- a/pkg/integration/tests/commit/commit_switch_to_editor.go +++ b/pkg/integration/tests/commit/commit_switch_to_editor.go @@ -25,6 +25,12 @@ var CommitSwitchToEditor = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). IsFocused(). + Lines( + Equals("▼ /").IsSelected(), + Equals(" ?? file1"), + Equals(" ?? file2"), + ). + SelectNextItem(). PressPrimaryAction(). // stage one of the files Press(keys.Files.CommitChanges) @@ -45,6 +51,9 @@ var CommitSwitchToEditor = NewIntegrationTest(NewIntegrationTestArgs{ // Now check that the preserved commit message was cleared: t.Views().Files(). Focus(). + Lines( + Equals("?? file2"), + ). PressPrimaryAction(). // stage the other file Press(keys.Files.CommitChanges) diff --git a/pkg/integration/tests/commit/discard_old_file_changes.go b/pkg/integration/tests/commit/discard_old_file_changes.go index 1ab189264..3e4057af5 100644 --- a/pkg/integration/tests/commit/discard_old_file_changes.go +++ b/pkg/integration/tests/commit/discard_old_file_changes.go @@ -43,13 +43,14 @@ var DiscardOldFileChanges = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().CommitFiles(). IsFocused(). Lines( - Contains("dir1").IsSelected(), - Contains("subd1"), - Contains("subfile0"), - Contains("d1_file0"), - Contains("dir2"), - Contains("d2_file1"), - Contains("d2_file2"), + Equals("▼ /").IsSelected(), + Equals(" ▼ dir1"), + Equals(" ▼ subd1"), + Equals(" A subfile0"), + Equals(" A d1_file0"), + Equals(" ▼ dir2"), + Equals(" A d2_file1"), + Equals(" A d2_file2"), ). NavigateToLine(Contains("d1_file0")). Press(keys.Universal.Remove) @@ -62,11 +63,12 @@ var DiscardOldFileChanges = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().CommitFiles(). IsFocused(). Lines( - Contains("dir1/subd1"), - Contains("subfile0"), - Contains("dir2"), - Contains("d2_file1").IsSelected(), - Contains("d2_file2"), + Equals("▼ /"), + Equals(" ▼ dir1/subd1"), + Equals(" A subfile0"), + Equals(" ▼ dir2"), + Equals(" A d2_file1").IsSelected(), + Equals(" A d2_file2"), ). PressEscape() @@ -84,11 +86,11 @@ var DiscardOldFileChanges = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().CommitFiles(). IsFocused(). Lines( - Contains("dir2").IsSelected(), - Contains("d2_file1"), - Contains("d2_file2"), - Contains("d2_file3"), - Contains("d2_file4"), + Equals("▼ dir2").IsSelected(), + Equals(" M d2_file1"), + Equals(" D d2_file2"), + Equals(" A d2_file3"), + Equals(" A d2_file4"), ). NavigateToLine(Contains("d2_file1")). Press(keys.Universal.ToggleRangeSelect). @@ -122,11 +124,11 @@ var DiscardOldFileChanges = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().CommitFiles(). IsFocused(). Lines( - Contains("dir1").IsSelected(), - Contains("subd1"), - Contains("file2ToRemove"), - Contains("fileToRemove"), - Contains("multiLineFile"), + Equals("▼ dir1").IsSelected(), + Equals(" ▼ subd1"), + Equals(" A file2ToRemove"), + Equals(" A fileToRemove"), + Equals(" A multiLineFile"), ). NavigateToLine(Contains("multiLineFile")). PressEnter() @@ -142,11 +144,11 @@ var DiscardOldFileChanges = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().CommitFiles(). IsFocused(). Lines( - Contains("dir1"), - Contains("subd1"), - Contains("file2ToRemove"), - Contains("fileToRemove"), - Contains("multiLineFile").IsSelected(), + Equals("▼ dir1"), + Equals(" ▼ subd1"), + Equals(" A file2ToRemove"), + Equals(" A fileToRemove"), + Equals(" ◐ multiLineFile").IsSelected(), ). NavigateToLine(Contains("dir1")). Press(keys.Universal.ToggleRangeSelect). diff --git a/pkg/integration/tests/commit/reword.go b/pkg/integration/tests/commit/reword.go index 21727c494..c349a0e28 100644 --- a/pkg/integration/tests/commit/reword.go +++ b/pkg/integration/tests/commit/reword.go @@ -20,6 +20,12 @@ var Reword = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). IsFocused(). + Lines( + Equals("▼ /").IsSelected(), + Contains("myfile"), + Contains("myfile2"), + ). + SelectNextItem(). PressPrimaryAction(). Press(keys.Files.CommitChanges) diff --git a/pkg/integration/tests/commit/staged.go b/pkg/integration/tests/commit/staged.go index 36d9cec58..aac40313b 100644 --- a/pkg/integration/tests/commit/staged.go +++ b/pkg/integration/tests/commit/staged.go @@ -21,7 +21,12 @@ var Staged = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). IsFocused(). - SelectedLine(Contains("myfile")). + Lines( + Equals("▼ /").IsSelected(), + Contains("myfile"), + Contains("myfile2"), + ). + SelectNextItem(). PressPrimaryAction(). // stage the file PressEnter() diff --git a/pkg/integration/tests/commit/staged_without_hooks.go b/pkg/integration/tests/commit/staged_without_hooks.go index fcf53dd22..0a020e58f 100644 --- a/pkg/integration/tests/commit/staged_without_hooks.go +++ b/pkg/integration/tests/commit/staged_without_hooks.go @@ -22,7 +22,12 @@ var StagedWithoutHooks = NewIntegrationTest(NewIntegrationTestArgs{ // stage the file t.Views().Files(). IsFocused(). - SelectedLine(Contains("myfile")). + Lines( + Equals("▼ /").IsSelected(), + Contains("myfile"), + Contains("myfile2"), + ). + SelectNextItem(). PressPrimaryAction(). PressEnter() diff --git a/pkg/integration/tests/commit/unstaged.go b/pkg/integration/tests/commit/unstaged.go index 2cbd5e33c..043e6ea9c 100644 --- a/pkg/integration/tests/commit/unstaged.go +++ b/pkg/integration/tests/commit/unstaged.go @@ -21,7 +21,12 @@ var Unstaged = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). IsFocused(). - SelectedLine(Contains("myfile")). + Lines( + Equals("▼ /").IsSelected(), + Contains("myfile"), + Contains("myfile2"), + ). + SelectNextItem(). PressEnter() t.Views().Staging(). diff --git a/pkg/integration/tests/conflicts/filter.go b/pkg/integration/tests/conflicts/filter.go index c997d8daa..7b26df6b8 100644 --- a/pkg/integration/tests/conflicts/filter.go +++ b/pkg/integration/tests/conflicts/filter.go @@ -18,8 +18,9 @@ var Filter = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). IsFocused(). Lines( - Contains("UU").Contains("file1").IsSelected(), - Contains("UU").Contains("file2"), + Equals("▼ /").IsSelected(), + Equals(" UU file1"), + Equals(" UU file2"), ). Press(keys.Files.OpenStatusFilter). Tap(func() { @@ -29,10 +30,11 @@ var Filter = NewIntegrationTest(NewIntegrationTestArgs{ Confirm() }). Lines( - Contains("UU").Contains("file1").IsSelected(), - Contains("UU").Contains("file2"), + Equals("▼ /").IsSelected(), + Equals(" UU file1"), + Equals(" UU file2"), // now we see the non-merge conflict file - Contains("A ").Contains("file3"), + Equals(" A file3"), ) }, }) diff --git a/pkg/integration/tests/conflicts/resolve_multiple_files.go b/pkg/integration/tests/conflicts/resolve_multiple_files.go index f5f8db0bc..542a74d54 100644 --- a/pkg/integration/tests/conflicts/resolve_multiple_files.go +++ b/pkg/integration/tests/conflicts/resolve_multiple_files.go @@ -18,9 +18,11 @@ var ResolveMultipleFiles = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). IsFocused(). Lines( - Contains("UU").Contains("file1").IsSelected(), - Contains("UU").Contains("file2"), + Equals("▼ /").IsSelected(), + Equals(" UU file1"), + Equals(" UU file2"), ). + SelectNextItem(). PressEnter() t.Views().MergeConflicts(). @@ -35,7 +37,7 @@ var ResolveMultipleFiles = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). IsFocused(). Lines( - Contains("UU").Contains("file2").IsSelected(), + Equals("UU file2").IsSelected(), ). PressEnter() diff --git a/pkg/integration/tests/conflicts/resolve_no_auto_stage.go b/pkg/integration/tests/conflicts/resolve_no_auto_stage.go index 35a509126..129ae3fe4 100644 --- a/pkg/integration/tests/conflicts/resolve_no_auto_stage.go +++ b/pkg/integration/tests/conflicts/resolve_no_auto_stage.go @@ -20,9 +20,11 @@ var ResolveNoAutoStage = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). IsFocused(). Lines( - Contains("UU").Contains("file1").IsSelected(), - Contains("UU").Contains("file2"), + Equals("▼ /").IsSelected(), + Equals(" UU file1"), + Equals(" UU file2"), ). + SelectNextItem(). PressEnter() t.Views().MergeConflicts(). @@ -38,13 +40,14 @@ var ResolveNoAutoStage = NewIntegrationTest(NewIntegrationTestArgs{ IsFocused(). // Resolving the conflict didn't auto-stage it Lines( - Contains("UU").Contains("file1").IsSelected(), - Contains("UU").Contains("file2"), + Equals("▼ /"), + Equals(" UU file1").IsSelected(), + Equals(" UU file2"), ). // So do that manually PressPrimaryAction(). Lines( - Contains("UU").Contains("file2").IsSelected(), + Equals("UU file2").IsSelected(), ). // Trying to stage a file that still has conflicts is not allowed: PressPrimaryAction(). @@ -70,12 +73,12 @@ var ResolveNoAutoStage = NewIntegrationTest(NewIntegrationTestArgs{ IsFocused(). // Again, resolving the conflict didn't auto-stage it Lines( - Contains("UU").Contains("file2").IsSelected(), + Equals("UU file2").IsSelected(), ). // Doing that manually now works: PressPrimaryAction(). Lines( - Contains("A").Contains("file3").IsSelected(), + Equals("A file3").IsSelected(), ) }, }) diff --git a/pkg/integration/tests/custom_commands/custom_commands_submenu.go b/pkg/integration/tests/custom_commands/custom_commands_submenu.go index 45e1fb169..a8d13cf73 100644 --- a/pkg/integration/tests/custom_commands/custom_commands_submenu.go +++ b/pkg/integration/tests/custom_commands/custom_commands_submenu.go @@ -68,6 +68,7 @@ var CustomCommandsSubmenu = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). Lines( + Equals("▼ /"), Contains("myfile-commits"), Contains("myfile-files"), ) diff --git a/pkg/integration/tests/file/collapse_expand.go b/pkg/integration/tests/file/collapse_expand.go index 68efe323e..7ec25b02a 100644 --- a/pkg/integration/tests/file/collapse_expand.go +++ b/pkg/integration/tests/file/collapse_expand.go @@ -21,26 +21,27 @@ var CollapseExpand = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). IsFocused(). Lines( - Contains("dir").IsSelected(), - Contains("??").Contains("file-one"), - Contains("dir2"), - Contains("??").Contains("file-two"), + Equals("▼ /").IsSelected(), + Equals(" ▼ dir"), + Equals(" ?? file-one"), + Equals(" ▼ dir2"), + Equals(" ?? file-two"), ) t.Views().Files(). Press(keys.Files.CollapseAll). Lines( - Contains("dir"), - Contains("dir2"), + Equals("▶ /"), ) t.Views().Files(). Press(keys.Files.ExpandAll). Lines( - Contains("dir").IsSelected(), - Contains("??").Contains("file-one"), - Contains("dir2"), - Contains("??").Contains("file-two"), + Equals("▼ /").IsSelected(), + Equals(" ▼ dir"), + Equals(" ?? file-one"), + Equals(" ▼ dir2"), + Equals(" ?? file-two"), ) }, }) diff --git a/pkg/integration/tests/file/discard_range_select.go b/pkg/integration/tests/file/discard_range_select.go index 2de82dd98..27492cf69 100644 --- a/pkg/integration/tests/file/discard_range_select.go +++ b/pkg/integration/tests/file/discard_range_select.go @@ -29,33 +29,35 @@ var DiscardRangeSelect = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). IsFocused(). Lines( - Contains("▼ dir1").IsSelected(), - Contains(" ??").Contains("file-1a"), - Contains(" ??").Contains("file-1b"), - Contains("▼ dir2"), - Contains(" ??").Contains("file-2a"), - Contains(" M").Contains("file-2b"), - Contains("▼ dir3"), - Contains(" ??").Contains("file-3a"), - Contains(" M").Contains("file-3b"), - Contains("??").Contains("file-a"), - Contains("??").Contains("file-b"), + Equals("▼ /").IsSelected(), + Equals(" ▼ dir1"), + Equals(" ?? file-1a"), + Equals(" ?? file-1b"), + Equals(" ▼ dir2"), + Equals(" ?? file-2a"), + Equals(" M file-2b"), + Equals(" ▼ dir3"), + Equals(" ?? file-3a"), + Equals(" M file-3b"), + Equals(" ?? file-a"), + Equals(" ?? file-b"), ). NavigateToLine(Contains("file-1b")). Press(keys.Universal.ToggleRangeSelect). NavigateToLine(Contains("file-2a")). Lines( - Contains("▼ dir1"), - Contains(" ??").Contains("file-1a"), - Contains(" ??").Contains("file-1b").IsSelected(), - Contains("▼ dir2").IsSelected(), - Contains(" ??").Contains("file-2a").IsSelected(), - Contains(" M").Contains("file-2b"), - Contains("▼ dir3"), - Contains(" ??").Contains("file-3a"), - Contains(" M").Contains("file-3b"), - Contains("??").Contains("file-a"), - Contains("??").Contains("file-b"), + Equals("▼ /"), + Equals(" ▼ dir1"), + Equals(" ?? file-1a"), + Equals(" ?? file-1b").IsSelected(), + Equals(" ▼ dir2").IsSelected(), + Equals(" ?? file-2a").IsSelected(), + Equals(" M file-2b"), + Equals(" ▼ dir3"), + Equals(" ?? file-3a"), + Equals(" M file-3b"), + Equals(" ?? file-a"), + Equals(" ?? file-b"), ). // Discard Press(keys.Universal.Remove). @@ -66,24 +68,26 @@ var DiscardRangeSelect = NewIntegrationTest(NewIntegrationTestArgs{ Confirm() }). Lines( - Contains("▼ dir1"), - Contains(" ??").Contains("file-1a"), - Contains("▼ dir3").IsSelected(), - Contains(" ??").Contains("file-3a"), - Contains(" M").Contains("file-3b"), - Contains("??").Contains("file-a"), - Contains("??").Contains("file-b"), + Equals("▼ /"), + Equals(" ▼ dir1"), + Equals(" ?? file-1a"), + Equals(" ▼ dir3").IsSelected(), + Equals(" ?? file-3a"), + Equals(" M file-3b"), + Equals(" ?? file-a"), + Equals(" ?? file-b"), ). // Verify you can discard collapsed directories in range select PressEnter(). Press(keys.Universal.ToggleRangeSelect). NavigateToLine(Contains("file-a")). Lines( - Contains("▼ dir1"), - Contains(" ??").Contains("file-1a"), - Contains("▶ dir3").IsSelected(), - Contains("??").Contains("file-a").IsSelected(), - Contains("??").Contains("file-b"), + Equals("▼ /"), + Equals(" ▼ dir1"), + Equals(" ?? file-1a"), + Equals(" ▶ dir3").IsSelected(), + Equals(" ?? file-a").IsSelected(), + Equals(" ?? file-b"), ). Press(keys.Universal.Remove). Tap(func() { @@ -93,9 +97,10 @@ var DiscardRangeSelect = NewIntegrationTest(NewIntegrationTestArgs{ Confirm() }). Lines( - Contains("▼ dir1"), - Contains(" ??").Contains("file-1a"), - Contains("??").Contains("file-b").IsSelected(), + Equals("▼ /"), + Equals(" ▼ dir1"), + Equals(" ?? file-1a"), + Equals(" ?? file-b").IsSelected(), ) }, }) diff --git a/pkg/integration/tests/file/discard_staged_changes.go b/pkg/integration/tests/file/discard_staged_changes.go index 022796bdf..06322567f 100644 --- a/pkg/integration/tests/file/discard_staged_changes.go +++ b/pkg/integration/tests/file/discard_staged_changes.go @@ -24,16 +24,18 @@ var DiscardStagedChanges = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). IsFocused(). Lines( - Contains(` M file2`).IsSelected(), - Contains(`?? file3`), - Contains(` M fileToRemove`), + Equals("▼ /").IsSelected(), + Equals(" M file2"), + Equals(" ?? file3"), + Equals(" M fileToRemove"), ). NavigateToLine(Contains(`fileToRemove`)). PressPrimaryAction(). Lines( - Contains(` M file2`), - Contains(`?? file3`), - Contains(`M fileToRemove`).IsSelected(), + Equals("▼ /"), + Equals(" M file2"), + Equals(" ?? file3"), + Equals(" M fileToRemove").IsSelected(), ). Press(keys.Files.ViewResetOptions) @@ -42,8 +44,9 @@ var DiscardStagedChanges = NewIntegrationTest(NewIntegrationTestArgs{ // staged file has been removed t.Views().Files(). Lines( - Contains(` M file2`), - Contains(`?? file3`).IsSelected(), + Equals("▼ /"), + Equals(" M file2"), + Equals(" ?? file3").IsSelected(), ) // the file should have the same content that it originally had, given that that was committed already diff --git a/pkg/integration/tests/file/discard_unstaged_dir_changes.go b/pkg/integration/tests/file/discard_unstaged_dir_changes.go index 66e2ed67c..572194572 100644 --- a/pkg/integration/tests/file/discard_unstaged_dir_changes.go +++ b/pkg/integration/tests/file/discard_unstaged_dir_changes.go @@ -30,13 +30,15 @@ var DiscardUnstagedDirChanges = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). IsFocused(). Lines( - Contains("dir").IsSelected(), - Contains("subdir"), - Contains("??").Contains("unstaged-file-one"), - Contains("MM").Contains("file-one"), - Contains("??").Contains("unstaged-file-two"), - Contains("??").Contains("unstaged-file-three"), + Equals("▼ /").IsSelected(), + Equals(" ▼ dir"), + Equals(" ▼ subdir"), + Equals(" ?? unstaged-file-one"), + Equals(" MM file-one"), + Equals(" ?? unstaged-file-two"), + Equals(" ?? unstaged-file-three"), ). + SelectNextItem(). Press(keys.Universal.Remove). Tap(func() { t.ExpectPopup().Menu(). @@ -45,10 +47,11 @@ var DiscardUnstagedDirChanges = NewIntegrationTest(NewIntegrationTestArgs{ Confirm() }). Lines( - Contains("dir").IsSelected(), - Contains("M ").Contains("file-one"), + Equals("▼ /"), + Equals(" ▼ dir").IsSelected(), + Equals(" M file-one"), // this guy remains untouched because it wasn't inside the 'dir' directory - Contains("??").Contains("unstaged-file-three"), + Equals(" ?? unstaged-file-three"), ) t.FileSystem().FileContent("dir/file-one", Equals("original content\nnew content\n")) diff --git a/pkg/integration/tests/file/discard_unstaged_file_changes.go b/pkg/integration/tests/file/discard_unstaged_file_changes.go index 2d2b5f192..f9dcaf6bb 100644 --- a/pkg/integration/tests/file/discard_unstaged_file_changes.go +++ b/pkg/integration/tests/file/discard_unstaged_file_changes.go @@ -26,9 +26,11 @@ var DiscardUnstagedFileChanges = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). IsFocused(). Lines( - Contains("MM").Contains("file-one").IsSelected(), - Contains("AM").Contains("file-two"), + Equals("▼ /").IsSelected(), + Equals(" MM file-one"), + Equals(" AM file-two"), ). + SelectNextItem(). Press(keys.Universal.Remove). Tap(func() { t.ExpectPopup().Menu(). @@ -37,13 +39,15 @@ var DiscardUnstagedFileChanges = NewIntegrationTest(NewIntegrationTestArgs{ Confirm() }). Lines( - Contains("M ").Contains("file-one").IsSelected(), - Contains("AM").Contains("file-two"), + Equals("▼ /"), + Equals(" M file-one").IsSelected(), + Equals(" AM file-two"), ). SelectNextItem(). Lines( - Contains("M ").Contains("file-one"), - Contains("AM").Contains("file-two").IsSelected(), + Equals("▼ /"), + Equals(" M file-one"), + Equals(" AM file-two").IsSelected(), ). Press(keys.Universal.Remove). Tap(func() { @@ -53,8 +57,9 @@ var DiscardUnstagedFileChanges = NewIntegrationTest(NewIntegrationTestArgs{ Confirm() }). Lines( - Contains("M ").Contains("file-one"), - Contains("A ").Contains("file-two").IsSelected(), + Equals("▼ /"), + Equals(" M file-one"), + Equals(" A file-two").IsSelected(), ) t.FileSystem().FileContent("file-one", Equals("original content\nnew content\n")) diff --git a/pkg/integration/tests/file/discard_unstaged_range_select.go b/pkg/integration/tests/file/discard_unstaged_range_select.go index efcf83c10..fc99c7502 100644 --- a/pkg/integration/tests/file/discard_unstaged_range_select.go +++ b/pkg/integration/tests/file/discard_unstaged_range_select.go @@ -26,27 +26,29 @@ var DiscardUnstagedRangeSelect = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). IsFocused(). Lines( - Contains("▼ dir1").IsSelected(), - Contains(" ??").Contains("file-a"), - Contains(" ??").Contains("file-b"), - Contains("▼ dir2"), - Contains(" A ").Contains("file-c"), - Contains(" M").Contains("file-d"), - Contains("??").Contains("file-e"), - Contains("??").Contains("file-f"), + Equals("▼ /").IsSelected(), + Equals(" ▼ dir1"), + Equals(" ?? file-a"), + Equals(" ?? file-b"), + Equals(" ▼ dir2"), + Equals(" A file-c"), + Equals(" M file-d"), + Equals(" ?? file-e"), + Equals(" ?? file-f"), ). NavigateToLine(Contains("file-b")). Press(keys.Universal.ToggleRangeSelect). NavigateToLine(Contains("file-c")). Lines( - Contains("▼ dir1"), - Contains(" ??").Contains("file-a"), - Contains(" ??").Contains("file-b").IsSelected(), - Contains("▼ dir2").IsSelected(), - Contains(" A ").Contains("file-c").IsSelected(), - Contains(" M").Contains("file-d"), - Contains("??").Contains("file-e"), - Contains("??").Contains("file-f"), + Equals("▼ /"), + Equals(" ▼ dir1"), + Equals(" ?? file-a"), + Equals(" ?? file-b").IsSelected(), + Equals(" ▼ dir2").IsSelected(), + Equals(" A file-c").IsSelected(), + Equals(" M file-d"), + Equals(" ?? file-e"), + Equals(" ?? file-f"), ). // Discard Press(keys.Universal.Remove). @@ -60,14 +62,15 @@ var DiscardUnstagedRangeSelect = NewIntegrationTest(NewIntegrationTestArgs{ // file-c is still there because it contained no unstaged changes // file-d is gone because it was selected via dir2 and contained only unstaged changes Lines( - Contains("▼ dir1"), - Contains(" ??").Contains("file-a"), - Contains("▼ dir2"), + Equals("▼ /"), + Equals(" ▼ dir1"), + Equals(" ?? file-a"), + Equals(" ▼ dir2"), // Re-selecting file-c because it's where the selected line index // was before performing the action. - Contains(" A ").Contains("file-c").IsSelected(), - Contains("??").Contains("file-e"), - Contains("??").Contains("file-f"), + Equals(" A file-c").IsSelected(), + Equals(" ?? file-e"), + Equals(" ?? file-f"), ) }, }) diff --git a/pkg/integration/tests/file/discard_various_changes.go b/pkg/integration/tests/file/discard_various_changes.go index db96f8db0..0cc188f65 100644 --- a/pkg/integration/tests/file/discard_various_changes.go +++ b/pkg/integration/tests/file/discard_various_changes.go @@ -21,11 +21,17 @@ var DiscardVariousChanges = NewIntegrationTest(NewIntegrationTestArgs{ label string } + t.Views().Files(). + IsFocused(). + TopLines( + Equals("▼ /").IsSelected(), + ) + discardOneByOne := func(files []statusFile) { for _, file := range files { t.Views().Files(). IsFocused(). - SelectedLine(Contains(file.status + " " + file.label)). + NavigateToLine(Contains(file.status + " " + file.label)). Press(keys.Universal.Remove) t.ExpectPopup().Menu(). diff --git a/pkg/integration/tests/file/discard_various_changes_range_select.go b/pkg/integration/tests/file/discard_various_changes_range_select.go index eb78ce93a..403ece7f7 100644 --- a/pkg/integration/tests/file/discard_various_changes_range_select.go +++ b/pkg/integration/tests/file/discard_various_changes_range_select.go @@ -19,14 +19,16 @@ var DiscardVariousChangesRangeSelect = NewIntegrationTest(NewIntegrationTestArgs t.Views().Files(). IsFocused(). Lines( - Contains("UA").Contains("added-them-changed-us.txt").IsSelected(), - Contains("AA").Contains("both-added.txt"), - Contains("DD").Contains("both-deleted.txt"), - Contains("UU").Contains("both-modded.txt"), - Contains("AU").Contains("changed-them-added-us.txt"), - Contains("UD").Contains("deleted-them.txt"), - Contains("DU").Contains("deleted-us.txt"), + Equals("▼ /").IsSelected(), + Equals(" UA added-them-changed-us.txt"), + Equals(" AA both-added.txt"), + Equals(" DD both-deleted.txt"), + Equals(" UU both-modded.txt"), + Equals(" AU changed-them-added-us.txt"), + Equals(" UD deleted-them.txt"), + Equals(" DU deleted-us.txt"), ). + SelectNextItem(). Press(keys.Universal.ToggleRangeSelect). NavigateToLine(Contains("deleted-us.txt")). Press(keys.Universal.Remove). @@ -42,17 +44,18 @@ var DiscardVariousChangesRangeSelect = NewIntegrationTest(NewIntegrationTestArgs Cancel() }). Lines( - Contains("AM").Contains("added-changed.txt").IsSelected(), - Contains("MD").Contains("change-delete.txt"), - Contains("D ").Contains("delete-change.txt"), - Contains("D ").Contains("deleted-staged.txt"), - Contains(" D").Contains("deleted.txt"), - Contains("MM").Contains("double-modded.txt"), - Contains("M ").Contains("modded-staged.txt"), - Contains(" M").Contains("modded.txt"), - Contains("A ").Contains("new-staged.txt"), - Contains("??").Contains("new.txt"), - Contains("R ").Contains("renamed.txt → renamed2.txt"), + Equals("▼ /").IsSelected(), + Equals(" AM added-changed.txt"), + Equals(" MD change-delete.txt"), + Equals(" D delete-change.txt"), + Equals(" D deleted-staged.txt"), + Equals(" D deleted.txt"), + Equals(" MM double-modded.txt"), + Equals(" M modded-staged.txt"), + Equals(" M modded.txt"), + Equals(" A new-staged.txt"), + Equals(" ?? new.txt"), + Equals(" R renamed.txt → renamed2.txt"), ). Press(keys.Universal.ToggleRangeSelect). NavigateToLine(Contains("renamed.txt")). diff --git a/pkg/integration/tests/file/gitignore.go b/pkg/integration/tests/file/gitignore.go index e206f19e1..0d7c1a019 100644 --- a/pkg/integration/tests/file/gitignore.go +++ b/pkg/integration/tests/file/gitignore.go @@ -20,10 +20,12 @@ var Gitignore = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). IsFocused(). Lines( - Contains(`?? .gitignore`).IsSelected(), - Contains(`?? toExclude`), - Contains(`?? toIgnore`), + Equals("▼ /").IsSelected(), + Equals(" ?? .gitignore"), + Equals(" ?? toExclude"), + Equals(" ?? toIgnore"), ). + SelectNextItem(). Press(keys.Files.IgnoreFile). // ensure we can't exclude the .gitignore file Tap(func() { diff --git a/pkg/integration/tests/file/remember_commit_message_after_fail.go b/pkg/integration/tests/file/remember_commit_message_after_fail.go index 828b30330..b6938ba55 100644 --- a/pkg/integration/tests/file/remember_commit_message_after_fail.go +++ b/pkg/integration/tests/file/remember_commit_message_after_fail.go @@ -31,6 +31,7 @@ var RememberCommitMessageAfterFail = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). IsFocused(). Lines( + Equals("▼ /"), Contains("bad"), Contains("one"), ). @@ -40,6 +41,7 @@ var RememberCommitMessageAfterFail = NewIntegrationTest(NewIntegrationTestArgs{ t.ExpectPopup().Alert().Title(Equals("Error")).Content(Contains("Git command failed")).Confirm() }). + NavigateToLine(Contains("bad")). Press(keys.Universal.Remove). // remove file that triggers pre-commit hook to fail Tap(func() { t.ExpectPopup().Menu(). diff --git a/pkg/integration/tests/file/rename_similarity_threshold_change.go b/pkg/integration/tests/file/rename_similarity_threshold_change.go index ec3aad241..b2a6fc376 100644 --- a/pkg/integration/tests/file/rename_similarity_threshold_change.go +++ b/pkg/integration/tests/file/rename_similarity_threshold_change.go @@ -21,15 +21,16 @@ var RenameSimilarityThresholdChange = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). IsFocused(). Lines( - Contains("D ").Contains("original"), - Contains("A ").Contains("renamed"), + Equals("▼ /"), + Equals(" D original"), + Equals(" A renamed"), ). Press(keys.Universal.DecreaseRenameSimilarityThreshold). Tap(func() { t.ExpectToast(Equals("Changed rename similarity threshold to 45%")) }). Lines( - Contains("R ").Contains("original → renamed"), + Equals("R original → renamed"), ) }, }) diff --git a/pkg/integration/tests/file/stage_children_range_select.go b/pkg/integration/tests/file/stage_children_range_select.go index 30a0a5e6b..5bcf30336 100644 --- a/pkg/integration/tests/file/stage_children_range_select.go +++ b/pkg/integration/tests/file/stage_children_range_select.go @@ -21,12 +21,13 @@ var StageChildrenRangeSelect = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). IsFocused(). Lines( - Contains("▼ baz").IsSelected(), - Contains(" ??").Contains("file"), - Contains("▼ bazbam"), - Contains(" ??").Contains("file"), - Contains("??").Contains("foo"), - Contains("??").Contains("foobar"), + Equals("▼ /").IsSelected(), + Equals(" ▼ baz"), + Equals(" ?? file"), + Equals(" ▼ bazbam"), + Equals(" ?? file"), + Equals(" ?? foo"), + Equals(" ?? foobar"), ). // Select everything Press(keys.Universal.ToggleRangeSelect). @@ -34,12 +35,13 @@ var StageChildrenRangeSelect = NewIntegrationTest(NewIntegrationTestArgs{ // Stage PressPrimaryAction(). Lines( - Contains("▼ baz").IsSelected(), - Contains(" A ").Contains("file").IsSelected(), - Contains("▼ bazbam").IsSelected(), - Contains(" A ").Contains("file").IsSelected(), - Contains("A ").Contains("foo").IsSelected(), - Contains("A ").Contains("foobar").IsSelected(), + Equals("▼ /").IsSelected(), + Equals(" ▼ baz").IsSelected(), + Equals(" A file").IsSelected(), + Equals(" ▼ bazbam").IsSelected(), + Equals(" A file").IsSelected(), + Equals(" A foo").IsSelected(), + Equals(" A foobar").IsSelected(), ) }, }) diff --git a/pkg/integration/tests/file/stage_deleted_range_select.go b/pkg/integration/tests/file/stage_deleted_range_select.go index d10188756..702f1bf6c 100644 --- a/pkg/integration/tests/file/stage_deleted_range_select.go +++ b/pkg/integration/tests/file/stage_deleted_range_select.go @@ -23,28 +23,33 @@ var StageDeletedRangeSelect = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). IsFocused(). Lines( - Contains(" D").Contains("file-a").IsSelected(), - Contains(" D").Contains("file-b"), + Equals("▼ /").IsSelected(), + Equals(" D file-a"), + Equals(" D file-b"), ). + SelectNextItem(). // Stage a single deleted file PressPrimaryAction(). Lines( - Contains("D ").Contains("file-a").IsSelected(), - Contains(" D").Contains("file-b"), + Equals("▼ /"), + Equals(" D file-a").IsSelected(), + Equals(" D file-b"), ). Press(keys.Universal.ToggleRangeSelect). NavigateToLine(Contains("file-b")). // Stage both files while a deleted file is already staged PressPrimaryAction(). Lines( - Contains("D ").Contains("file-a").IsSelected(), - Contains("D ").Contains("file-b").IsSelected(), + Equals("▼ /"), + Equals(" D file-a").IsSelected(), + Equals(" D file-b").IsSelected(), ). // Unstage; back to everything being unstaged PressPrimaryAction(). Lines( - Contains(" D").Contains("file-a").IsSelected(), - Contains(" D").Contains("file-b").IsSelected(), + Equals("▼ /"), + Equals(" D file-a").IsSelected(), + Equals(" D file-b").IsSelected(), ) }, }) diff --git a/pkg/integration/tests/file/stage_range_select.go b/pkg/integration/tests/file/stage_range_select.go index d0c26e39b..ea80e3ff6 100644 --- a/pkg/integration/tests/file/stage_range_select.go +++ b/pkg/integration/tests/file/stage_range_select.go @@ -26,14 +26,15 @@ var StageRangeSelect = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). IsFocused(). Lines( - Contains("▼ dir1").IsSelected(), - Contains(" ??").Contains("file-a"), - Contains(" ??").Contains("file-b"), - Contains("▼ dir2"), - Contains(" ??").Contains("file-c"), - Contains(" M").Contains("file-d"), - Contains("??").Contains("file-e"), - Contains("??").Contains("file-f"), + Equals("▼ /").IsSelected(), + Equals(" ▼ dir1"), + Equals(" ?? file-a"), + Equals(" ?? file-b"), + Equals(" ▼ dir2"), + Equals(" ?? file-c"), + Equals(" M file-d"), + Equals(" ?? file-e"), + Equals(" ?? file-f"), ). NavigateToLine(Contains("file-b")). Press(keys.Universal.ToggleRangeSelect). @@ -41,27 +42,29 @@ var StageRangeSelect = NewIntegrationTest(NewIntegrationTestArgs{ // Stage PressPrimaryAction(). Lines( - Contains("▼ dir1"), - Contains(" ??").Contains("file-a"), - Contains(" A ").Contains("file-b").IsSelected(), - Contains("▼ dir2").IsSelected(), - Contains(" A ").Contains("file-c").IsSelected(), + Equals("▼ /"), + Equals(" ▼ dir1"), + Equals(" ?? file-a"), + Equals(" A file-b").IsSelected(), + Equals(" ▼ dir2").IsSelected(), + Equals(" A file-c").IsSelected(), // Staged because dir2 was part of the selection when he hit space - Contains(" M ").Contains("file-d"), - Contains("??").Contains("file-e"), - Contains("??").Contains("file-f"), + Equals(" M file-d"), + Equals(" ?? file-e"), + Equals(" ?? file-f"), ). // Unstage; back to everything being unstaged PressPrimaryAction(). Lines( - Contains("▼ dir1"), - Contains(" ??").Contains("file-a"), - Contains(" ??").Contains("file-b").IsSelected(), - Contains("▼ dir2").IsSelected(), - Contains(" ??").Contains("file-c").IsSelected(), - Contains(" M").Contains("file-d"), - Contains("??").Contains("file-e"), - Contains("??").Contains("file-f"), + Equals("▼ /"), + Equals(" ▼ dir1"), + Equals(" ?? file-a"), + Equals(" ?? file-b").IsSelected(), + Equals(" ▼ dir2").IsSelected(), + Equals(" ?? file-c").IsSelected(), + Equals(" M file-d"), + Equals(" ?? file-e"), + Equals(" ?? file-f"), ). Press(keys.Universal.ToggleRangeSelect). NavigateToLine(Contains("dir2")). @@ -69,38 +72,41 @@ var StageRangeSelect = NewIntegrationTest(NewIntegrationTestArgs{ // Collapse the directory PressEnter(). Lines( - Contains("▼ dir1"), - Contains(" ??").Contains("file-a"), - Contains(" ??").Contains("file-b"), - Contains("▶ dir2").IsSelected(), - Contains("??").Contains("file-e"), - Contains("??").Contains("file-f"), + Equals("▼ /"), + Equals(" ▼ dir1"), + Equals(" ?? file-a"), + Equals(" ?? file-b"), + Equals(" ▶ dir2").IsSelected(), + Equals(" ?? file-e"), + Equals(" ?? file-f"), ). Press(keys.Universal.ToggleRangeSelect). NavigateToLine(Contains("file-e")). // Stage PressPrimaryAction(). Lines( - Contains("▼ dir1"), - Contains(" ??").Contains("file-a"), - Contains(" ??").Contains("file-b"), - Contains("▶ dir2").IsSelected(), - Contains("A ").Contains("file-e").IsSelected(), - Contains("??").Contains("file-f"), + Equals("▼ /"), + Equals(" ▼ dir1"), + Equals(" ?? file-a"), + Equals(" ?? file-b"), + Equals(" ▶ dir2").IsSelected(), + Equals(" A file-e").IsSelected(), + Equals(" ?? file-f"), ). Press(keys.Universal.ToggleRangeSelect). NavigateToLine(Contains("dir2")). // Expand the directory again to verify it's been staged PressEnter(). Lines( - Contains("▼ dir1"), - Contains(" ??").Contains("file-a"), - Contains(" ??").Contains("file-b"), - Contains("▼ dir2").IsSelected(), - Contains(" A ").Contains("file-c"), - Contains(" M ").Contains("file-d"), - Contains("A ").Contains("file-e"), - Contains("??").Contains("file-f"), + Equals("▼ /"), + Equals(" ▼ dir1"), + Equals(" ?? file-a"), + Equals(" ?? file-b"), + Equals(" ▼ dir2").IsSelected(), + Equals(" A file-c"), + Equals(" M file-d"), + Equals(" A file-e"), + Equals(" ?? file-f"), ) }, }) diff --git a/pkg/integration/tests/filter_and_search/filter_by_file_status.go b/pkg/integration/tests/filter_and_search/filter_by_file_status.go index 0c5f95e1d..2e706936f 100644 --- a/pkg/integration/tests/filter_and_search/filter_by_file_status.go +++ b/pkg/integration/tests/filter_and_search/filter_by_file_status.go @@ -29,8 +29,9 @@ var FilterByFileStatus = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). Focus(). Lines( - Equals("A file-staged-but-untracked").IsSelected(), - Equals(" M file-tracked"), + Equals("▼ /").IsSelected(), + Equals(" A file-staged-but-untracked"), + Equals(" M file-tracked"), ). Press(keys.Files.OpenStatusFilter). Tap(func() { @@ -50,8 +51,9 @@ var FilterByFileStatus = NewIntegrationTest(NewIntegrationTestArgs{ Confirm() }). Lines( - Equals("A file-staged-but-untracked").IsSelected(), - Equals(" M file-tracked"), + Equals("▼ /").IsSelected(), + Equals(" A file-staged-but-untracked"), + Equals(" M file-tracked"), ). Press(keys.Files.OpenStatusFilter). Tap(func() { @@ -61,8 +63,9 @@ var FilterByFileStatus = NewIntegrationTest(NewIntegrationTestArgs{ Confirm() }). Lines( - Equals("A file-staged-but-untracked").IsSelected(), - Equals(" M file-tracked"), + Equals("▼ /").IsSelected(), + Equals(" A file-staged-but-untracked"), + Equals(" M file-tracked"), ) }, }) diff --git a/pkg/integration/tests/filter_and_search/nested_filter.go b/pkg/integration/tests/filter_and_search/nested_filter.go index 6444ad523..db20dd5b5 100644 --- a/pkg/integration/tests/filter_and_search/nested_filter.go +++ b/pkg/integration/tests/filter_and_search/nested_filter.go @@ -61,15 +61,17 @@ var NestedFilter = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().CommitFiles(). IsFocused(). Lines( - Contains(`apple`).IsSelected(), - Contains(`grape`), - Contains(`orange`), + Equals("▼ /").IsSelected(), + Equals(" A apple"), + Equals(" A grape"), + Equals(" A orange"), ). FilterOrSearch("grape"). Lines( - Contains(`apple`), - Contains(`grape`).IsSelected(), - Contains(`orange`), + Equals("▼ /"), + Equals(" A apple"), + Equals(" A grape").IsSelected(), + Equals(" A orange"), ). PressEnter() @@ -87,9 +89,10 @@ var NestedFilter = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().CommitFiles(). IsFocused(). Lines( - Contains(`apple`), - Contains(`grape`).IsSelected(), - Contains(`orange`), + Equals("▼ /"), + Equals(" A apple"), + Equals(" A grape").IsSelected(), + Equals(" A orange"), ). Tap(func() { t.Views().Search().IsVisible().Content(Contains("matches for 'grape'")) @@ -100,9 +103,10 @@ var NestedFilter = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Search().IsInvisible() }). Lines( - Contains(`apple`), - Contains(`grape`).IsSelected(), - Contains(`orange`), + Equals("▼ /"), + Equals(" A apple"), + Equals(" A grape").IsSelected(), + Equals(" A orange"), ). // escape to sub-commits view PressEscape() diff --git a/pkg/integration/tests/filter_and_search/nested_filter_transient.go b/pkg/integration/tests/filter_and_search/nested_filter_transient.go index 3bc8e78bb..8548d68c0 100644 --- a/pkg/integration/tests/filter_and_search/nested_filter_transient.go +++ b/pkg/integration/tests/filter_and_search/nested_filter_transient.go @@ -69,13 +69,15 @@ var NestedFilterTransient = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().CommitFiles(). IsFocused(). Lines( - Contains(`file-one`).IsSelected(), - Contains(`file-two`), + Equals("▼ /").IsSelected(), + Equals(" A file-one"), + Equals(" A file-two"), ). FilterOrSearch("two"). Lines( - Contains(`file-one`), - Contains(`file-two`).IsSelected(), + Equals("▼ /"), + Equals(" A file-one"), + Equals(" A file-two").IsSelected(), ) t.Views().Branches(). @@ -96,8 +98,9 @@ var NestedFilterTransient = NewIntegrationTest(NewIntegrationTestArgs{ IsFocused(). // the search on the commit-files context has been cancelled Lines( - Contains(`file-one`).IsSelected(), - Contains(`file-two`), + Equals("▼ /").IsSelected(), + Equals(" A file-one"), + Equals(" A file-two"), ). Tap(func() { t.Views().Search().IsInvisible() diff --git a/pkg/integration/tests/filter_by_path/shared.go b/pkg/integration/tests/filter_by_path/shared.go index 3d514b96b..6fec20a3e 100644 --- a/pkg/integration/tests/filter_by_path/shared.go +++ b/pkg/integration/tests/filter_by_path/shared.go @@ -27,17 +27,20 @@ func postFilterTest(t *TestDriver) { Contains(`only filterFile`).IsSelected(), Contains(`both files`), ). - SelectNextItem(). - PressEnter() + SelectNextItem() // we only show the filtered file's changes in the main view t.Views().Main(). Content(Contains("filterFile").DoesNotContain("otherFile")) + t.Views().Commits(). + PressEnter() + // when you click into the commit itself, you see all files from that commit t.Views().CommitFiles(). IsFocused(). Lines( + Equals("▼ /"), Contains(`filterFile`), Contains(`otherFile`), ) diff --git a/pkg/integration/tests/patch_building/apply_in_reverse.go b/pkg/integration/tests/patch_building/apply_in_reverse.go index c587d8fc1..f15d4c35c 100644 --- a/pkg/integration/tests/patch_building/apply_in_reverse.go +++ b/pkg/integration/tests/patch_building/apply_in_reverse.go @@ -26,9 +26,11 @@ var ApplyInReverse = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().CommitFiles(). IsFocused(). Lines( - Contains("file1").IsSelected(), - Contains("file2"), + Equals("▼ /").IsSelected(), + Equals(" A file1"), + Equals(" A file2"), ). + SelectNextItem(). PressPrimaryAction() t.Views().Information().Content(Contains("Building patch")) diff --git a/pkg/integration/tests/patch_building/apply_in_reverse_with_conflict.go b/pkg/integration/tests/patch_building/apply_in_reverse_with_conflict.go index f450f8229..78367cc84 100644 --- a/pkg/integration/tests/patch_building/apply_in_reverse_with_conflict.go +++ b/pkg/integration/tests/patch_building/apply_in_reverse_with_conflict.go @@ -34,9 +34,11 @@ var ApplyInReverseWithConflict = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().CommitFiles(). IsFocused(). Lines( - Contains("M").Contains("file1").IsSelected(), - Contains("M").Contains("file2"), + Equals("▼ /").IsSelected(), + Equals(" M file1"), + Equals(" M file2"), ). + SelectNextItem(). // Add both files to the patch; the first will conflict, the second won't PressPrimaryAction(). Tap(func() { @@ -61,7 +63,7 @@ var ApplyInReverseWithConflict = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). Focus(). Lines( - Contains("UU").Contains("file1").IsSelected(), + Equals("UU file1").IsSelected(), ). PressEnter() @@ -81,9 +83,11 @@ var ApplyInReverseWithConflict = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). Focus(). Lines( - Contains("M").Contains("file1").IsSelected(), - Contains("M").Contains("file2"), - ) + Equals("▼ /").IsSelected(), + Equals(" M file1"), + Equals(" M file2"), + ). + SelectNextItem() t.Views().Main(). ContainsLines( diff --git a/pkg/integration/tests/patch_building/move_range_to_index.go b/pkg/integration/tests/patch_building/move_range_to_index.go index 2e7c95e9a..fbacb50a5 100644 --- a/pkg/integration/tests/patch_building/move_range_to_index.go +++ b/pkg/integration/tests/patch_building/move_range_to_index.go @@ -31,10 +31,12 @@ var MoveRangeToIndex = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().CommitFiles(). IsFocused(). Lines( - Contains("M file1").IsSelected(), - Contains("A file2"), - Contains("A file3"), + Equals("▼ /").IsSelected(), + Equals(" M file1"), + Equals(" A file2"), + Equals(" A file3"), ). + SelectNextItem(). Press(keys.Universal.ToggleRangeSelect). NavigateToLine(Contains("file2")). PressPrimaryAction() @@ -55,8 +57,9 @@ var MoveRangeToIndex = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). Focus(). Lines( - Contains("file1").IsSelected(), - Contains("file2"), + Equals("▼ /").IsSelected(), + Equals(" M file1"), + Equals(" A file2"), ) t.Views().Main(). diff --git a/pkg/integration/tests/patch_building/move_to_earlier_commit.go b/pkg/integration/tests/patch_building/move_to_earlier_commit.go index 4336f8bc5..c7916c0a6 100644 --- a/pkg/integration/tests/patch_building/move_to_earlier_commit.go +++ b/pkg/integration/tests/patch_building/move_to_earlier_commit.go @@ -66,11 +66,12 @@ var MoveToEarlierCommit = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().CommitFiles(). IsFocused(). Lines( - Contains("dir").IsSelected(), - Contains(" M file1"), - Contains(" D file2"), - Contains(" A file3"), - Contains("A unrelated-file"), + Equals("▼ /").IsSelected(), + Equals(" ▼ dir"), + Equals(" M file1"), + Equals(" D file2"), + Equals(" A file3"), + Equals(" A unrelated-file"), ). PressEscape() diff --git a/pkg/integration/tests/patch_building/move_to_earlier_commit_no_keep_empty.go b/pkg/integration/tests/patch_building/move_to_earlier_commit_no_keep_empty.go index bbe1373e0..e3a9003c0 100644 --- a/pkg/integration/tests/patch_building/move_to_earlier_commit_no_keep_empty.go +++ b/pkg/integration/tests/patch_building/move_to_earlier_commit_no_keep_empty.go @@ -66,11 +66,12 @@ var MoveToEarlierCommitNoKeepEmpty = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().CommitFiles(). IsFocused(). Lines( - Contains("dir").IsSelected(), - Contains(" M file1"), - Contains(" D file2"), - Contains(" A file3"), - Contains("A unrelated-file"), + Equals("▼ /").IsSelected(), + Equals(" ▼ dir"), + Equals(" M file1"), + Equals(" D file2"), + Equals(" A file3"), + Equals(" A unrelated-file"), ). PressEscape() }, diff --git a/pkg/integration/tests/patch_building/move_to_index.go b/pkg/integration/tests/patch_building/move_to_index.go index 5ae6a4d33..af2e867c7 100644 --- a/pkg/integration/tests/patch_building/move_to_index.go +++ b/pkg/integration/tests/patch_building/move_to_index.go @@ -26,9 +26,11 @@ var MoveToIndex = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().CommitFiles(). IsFocused(). Lines( - Contains("file1").IsSelected(), + Equals("▼ /").IsSelected(), + Contains("file1"), Contains("file2"), ). + SelectNextItem(). PressPrimaryAction() t.Views().Information().Content(Contains("Building patch")) diff --git a/pkg/integration/tests/patch_building/move_to_later_commit.go b/pkg/integration/tests/patch_building/move_to_later_commit.go index 0e2a2ad86..aa97a9504 100644 --- a/pkg/integration/tests/patch_building/move_to_later_commit.go +++ b/pkg/integration/tests/patch_building/move_to_later_commit.go @@ -66,11 +66,12 @@ var MoveToLaterCommit = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().CommitFiles(). IsFocused(). Lines( - Contains("dir").IsSelected(), - Contains(" M file1"), - Contains(" D file2"), - Contains(" A file3"), - Contains("A unrelated-file"), + Equals("▼ /").IsSelected(), + Equals(" ▼ dir"), + Equals(" M file1"), + Equals(" D file2"), + Equals(" A file3"), + Equals(" A unrelated-file"), ). PressEscape() diff --git a/pkg/integration/tests/patch_building/move_to_later_commit_partial_hunk.go b/pkg/integration/tests/patch_building/move_to_later_commit_partial_hunk.go index 9ec9efac7..974dd4ec6 100644 --- a/pkg/integration/tests/patch_building/move_to_later_commit_partial_hunk.go +++ b/pkg/integration/tests/patch_building/move_to_later_commit_partial_hunk.go @@ -67,9 +67,11 @@ var MoveToLaterCommitPartialHunk = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().CommitFiles(). IsFocused(). Lines( - Contains("file1").IsSelected(), + Equals("▼ /").IsSelected(), + Contains("file1"), Contains("unrelated-file"), ). + SelectNextItem(). Tap(func() { t.Views().Main(). Content(Contains("+1st line\n 2nd line")) diff --git a/pkg/integration/tests/patch_building/remove_from_commit.go b/pkg/integration/tests/patch_building/remove_from_commit.go index fddbdc839..bfa0925d6 100644 --- a/pkg/integration/tests/patch_building/remove_from_commit.go +++ b/pkg/integration/tests/patch_building/remove_from_commit.go @@ -26,9 +26,11 @@ var RemoveFromCommit = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().CommitFiles(). IsFocused(). Lines( - Contains("file1").IsSelected(), + Equals("▼ /").IsSelected(), + Contains("file1"), Contains("file2"), ). + SelectNextItem(). PressPrimaryAction() t.Views().Information().Content(Contains("Building patch")) diff --git a/pkg/integration/tests/patch_building/select_all_files.go b/pkg/integration/tests/patch_building/select_all_files.go index 5665cef50..b4a2f6335 100644 --- a/pkg/integration/tests/patch_building/select_all_files.go +++ b/pkg/integration/tests/patch_building/select_all_files.go @@ -27,9 +27,10 @@ var SelectAllFiles = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().CommitFiles(). IsFocused(). Lines( - Contains("file1").IsSelected(), - Contains("file2"), - Contains("file3"), + Equals("▼ /").IsSelected(), + Equals(" A file1"), + Equals(" A file2"), + Equals(" A file3"), ). Press(keys.Files.ToggleStagedAll) diff --git a/pkg/integration/tests/patch_building/specific_selection.go b/pkg/integration/tests/patch_building/specific_selection.go index b59b62ccb..9027a34e6 100644 --- a/pkg/integration/tests/patch_building/specific_selection.go +++ b/pkg/integration/tests/patch_building/specific_selection.go @@ -33,10 +33,12 @@ var SpecificSelection = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().CommitFiles(). IsFocused(). Lines( - Contains("direct-file").IsSelected(), + Equals("▼ /").IsSelected(), + Contains("direct-file"), Contains("hunk-file"), Contains("line-file"), ). + SelectNextItem(). PressPrimaryAction(). Tap(func() { t.Views().Information().Content(Contains("Building patch")) diff --git a/pkg/integration/tests/patch_building/toggle_range.go b/pkg/integration/tests/patch_building/toggle_range.go index 6fd49adcf..c6fbd1f49 100644 --- a/pkg/integration/tests/patch_building/toggle_range.go +++ b/pkg/integration/tests/patch_building/toggle_range.go @@ -34,28 +34,30 @@ var ToggleRange = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().CommitFiles(). IsFocused(). Lines( - Contains("▼ dir1").IsSelected(), - Contains(" A").Contains("file1-a"), - Contains(" A").Contains("file2-a"), - Contains(" A").Contains("file3-a"), - Contains("▼ dir2"), - Contains(" A").Contains("file1-b"), - Contains(" A").Contains("file2-b"), - Contains(" A").Contains("file3-b"), + Equals("▼ /").IsSelected(), + Equals(" ▼ dir1"), + Equals(" A file1-a"), + Equals(" A file2-a"), + Equals(" A file3-a"), + Equals(" ▼ dir2"), + Equals(" A file1-b"), + Equals(" A file2-b"), + Equals(" A file3-b"), ). NavigateToLine(Contains("file1-a")). Press(keys.Universal.ToggleRangeSelect). NavigateToLine(Contains("file3-a")). PressPrimaryAction(). Lines( - Contains("▼ dir1"), - Contains(" ●").Contains("file1-a").IsSelected(), - Contains(" ●").Contains("file2-a").IsSelected(), - Contains(" ●").Contains("file3-a").IsSelected(), - Contains("▼ dir2"), - Contains(" A").Contains("file1-b"), - Contains(" A").Contains("file2-b"), - Contains(" A").Contains("file3-b"), + Equals("▼ /"), + Equals(" ▼ dir1"), + Equals(" ● file1-a").IsSelected(), + Equals(" ● file2-a").IsSelected(), + Equals(" ● file3-a").IsSelected(), + Equals(" ▼ dir2"), + Equals(" A file1-b"), + Equals(" A file2-b"), + Equals(" A file3-b"), ). PressEscape(). NavigateToLine(Contains("file3-b")). @@ -69,39 +71,42 @@ var ToggleRange = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().CommitFiles(). IsFocused(). Lines( - Contains("▼ dir1"), - Contains(" ●").Contains("file1-a"), - Contains(" ●").Contains("file2-a"), - Contains(" ●").Contains("file3-a"), - Contains("▼ dir2"), - Contains(" A").Contains("file1-b"), - Contains(" A").Contains("file2-b"), - Contains(" ◐").Contains("file3-b").IsSelected(), + Equals("▼ /"), + Equals(" ▼ dir1"), + Equals(" ● file1-a"), + Equals(" ● file2-a"), + Equals(" ● file3-a"), + Equals(" ▼ dir2"), + Equals(" A file1-b"), + Equals(" A file2-b"), + Equals(" ◐ file3-b").IsSelected(), ). NavigateToLine(Contains("dir1")). Press(keys.Universal.ToggleRangeSelect). NavigateToLine(Contains("dir2")). PressPrimaryAction(). Lines( - Contains("▼ dir1").IsSelected(), - Contains(" ●").Contains("file1-a").IsSelected(), - Contains(" ●").Contains("file2-a").IsSelected(), - Contains(" ●").Contains("file3-a").IsSelected(), - Contains("▼ dir2").IsSelected(), - Contains(" ●").Contains("file1-b"), - Contains(" ●").Contains("file2-b"), - Contains(" ●").Contains("file3-b"), + Equals("▼ /"), + Equals(" ▼ dir1").IsSelected(), + Equals(" ● file1-a").IsSelected(), + Equals(" ● file2-a").IsSelected(), + Equals(" ● file3-a").IsSelected(), + Equals(" ▼ dir2").IsSelected(), + Equals(" ● file1-b"), + Equals(" ● file2-b"), + Equals(" ● file3-b"), ). PressPrimaryAction(). Lines( - Contains("▼ dir1").IsSelected(), - Contains(" A").Contains("file1-a").IsSelected(), - Contains(" A").Contains("file2-a").IsSelected(), - Contains(" A").Contains("file3-a").IsSelected(), - Contains("▼ dir2").IsSelected(), - Contains(" A").Contains("file1-b"), - Contains(" A").Contains("file2-b"), - Contains(" A").Contains("file3-b"), + Equals("▼ /"), + Equals(" ▼ dir1").IsSelected(), + Equals(" A file1-a").IsSelected(), + Equals(" A file2-a").IsSelected(), + Equals(" A file3-a").IsSelected(), + Equals(" ▼ dir2").IsSelected(), + Equals(" A file1-b"), + Equals(" A file2-b"), + Equals(" A file3-b"), ) }, }) diff --git a/pkg/integration/tests/reflog/patch.go b/pkg/integration/tests/reflog/patch.go index 415fb18ee..3db994ba4 100644 --- a/pkg/integration/tests/reflog/patch.go +++ b/pkg/integration/tests/reflog/patch.go @@ -48,9 +48,11 @@ var Patch = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().CommitFiles(). IsFocused(). Lines( - Contains("file1").IsSelected(), + Equals("▼ /").IsSelected(), + Contains("file1"), Contains("file2"), ). + SelectNextItem(). PressPrimaryAction() t.Views().Information().Content(Contains("Building patch")) diff --git a/pkg/integration/tests/staging/discard_all_changes.go b/pkg/integration/tests/staging/discard_all_changes.go index b869b2318..e73f69a5e 100644 --- a/pkg/integration/tests/staging/discard_all_changes.go +++ b/pkg/integration/tests/staging/discard_all_changes.go @@ -22,9 +22,11 @@ var DiscardAllChanges = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). IsFocused(). Lines( - Contains("file1").IsSelected(), - Contains("file2"), + Equals("▼ /").IsSelected(), + Equals(" M file1"), + Equals(" M file2"), ). + SelectNextItem(). PressEnter() t.Views().Staging(). @@ -44,7 +46,7 @@ var DiscardAllChanges = NewIntegrationTest(NewIntegrationTestArgs{ // because there are no more changes in file1 we switch to file2 t.Views().Files(). Lines( - Contains("file2").IsSelected(), + Equals(" M file2"), ) }). // assert we are still in the staging panel, but now looking at the changes of the other file diff --git a/pkg/integration/tests/stash/apply_patch.go b/pkg/integration/tests/stash/apply_patch.go index ba454178b..7f47beca2 100644 --- a/pkg/integration/tests/stash/apply_patch.go +++ b/pkg/integration/tests/stash/apply_patch.go @@ -30,9 +30,11 @@ var ApplyPatch = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().CommitFiles(). IsFocused(). Lines( - Contains("myfile").IsSelected(), + Equals("▼ /").IsSelected(), + Contains("myfile"), Contains("myfile2"), ). + SelectNextItem(). PressPrimaryAction() t.Views().Information().Content(Contains("Building patch")) diff --git a/pkg/integration/tests/stash/stash_and_keep_index.go b/pkg/integration/tests/stash/stash_and_keep_index.go index db37e7328..9ba036164 100644 --- a/pkg/integration/tests/stash/stash_and_keep_index.go +++ b/pkg/integration/tests/stash/stash_and_keep_index.go @@ -23,8 +23,9 @@ var StashAndKeepIndex = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). Lines( - Contains("file-staged"), - Contains("file-unstaged"), + Equals("▼ /"), + Equals(" M file-staged"), + Equals(" M file-unstaged"), ). Press(keys.Files.ViewStashOptions) @@ -39,7 +40,7 @@ var StashAndKeepIndex = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). Lines( - Contains("file-staged"), + Equals("M file-staged"), ) t.Views().Stash(). @@ -49,8 +50,9 @@ var StashAndKeepIndex = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().CommitFiles(). IsFocused(). Lines( - Contains("file-staged"), - Contains("file-unstaged"), + Equals("▼ /"), + Equals(" M file-staged"), + Equals(" M file-unstaged"), ) }, }) diff --git a/pkg/integration/tests/stash/stash_including_untracked_files.go b/pkg/integration/tests/stash/stash_including_untracked_files.go index 1db09394f..91400d8a2 100644 --- a/pkg/integration/tests/stash/stash_including_untracked_files.go +++ b/pkg/integration/tests/stash/stash_including_untracked_files.go @@ -22,8 +22,9 @@ var StashIncludingUntrackedFiles = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). Lines( - Contains("file_1"), - Contains("file_2"), + Equals("▼ /"), + Equals(" A file_1"), + Equals(" ?? file_2"), ). Press(keys.Files.ViewStashOptions) diff --git a/pkg/integration/tests/stash/stash_staged.go b/pkg/integration/tests/stash/stash_staged.go index 11347d98d..38d96a354 100644 --- a/pkg/integration/tests/stash/stash_staged.go +++ b/pkg/integration/tests/stash/stash_staged.go @@ -23,8 +23,9 @@ var StashStaged = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). Lines( - Contains("file-staged"), - Contains("file-unstaged"), + Equals("▼ /"), + Equals(" M file-staged"), + Equals(" M file-unstaged"), ). Press(keys.Files.ViewStashOptions) @@ -39,7 +40,7 @@ var StashStaged = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). Lines( - Contains("file-unstaged"), + Equals(" M file-unstaged"), ) t.Views().Stash(). diff --git a/pkg/integration/tests/stash/stash_unstaged.go b/pkg/integration/tests/stash/stash_unstaged.go index 8027ec387..0604b1cce 100644 --- a/pkg/integration/tests/stash/stash_unstaged.go +++ b/pkg/integration/tests/stash/stash_unstaged.go @@ -23,8 +23,9 @@ var StashUnstaged = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). Lines( - Contains("file-staged"), - Contains("file-unstaged"), + Equals("▼ /"), + Equals(" M file-staged"), + Equals(" M file-unstaged"), ). Press(keys.Files.ViewStashOptions) diff --git a/pkg/integration/tests/submodule/add.go b/pkg/integration/tests/submodule/add.go index 9437a205a..a82a71227 100644 --- a/pkg/integration/tests/submodule/add.go +++ b/pkg/integration/tests/submodule/add.go @@ -44,9 +44,11 @@ var Add = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files().Focus(). Lines( - Contains(".gitmodules").IsSelected(), - Contains("my_submodule_path (submodule)"), + Equals("▼ /").IsSelected(), + Equals(" A .gitmodules"), + Equals(" A my_submodule_path (submodule)"), ). + SelectNextItem(). Tap(func() { t.Views().Main().Content( Contains("[submodule \"my_submodule\"]"). diff --git a/pkg/integration/tests/submodule/remove.go b/pkg/integration/tests/submodule/remove.go index 22fb83f30..9290726ff 100644 --- a/pkg/integration/tests/submodule/remove.go +++ b/pkg/integration/tests/submodule/remove.go @@ -35,9 +35,11 @@ var Remove = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files().Focus(). Lines( - MatchesRegexp(`M.*\.gitmodules`).IsSelected(), - MatchesRegexp(`D.*my_submodule_path`), - ) + Equals("▼ /").IsSelected(), + Equals(" M .gitmodules"), + Equals(" D my_submodule_path"), + ). + SelectNextItem() t.Views().Main().Content( Contains("-[submodule \"my_submodule_name\"]"). diff --git a/pkg/integration/tests/submodule/remove_nested.go b/pkg/integration/tests/submodule/remove_nested.go index ae32c0907..fe05c0fb0 100644 --- a/pkg/integration/tests/submodule/remove_nested.go +++ b/pkg/integration/tests/submodule/remove_nested.go @@ -39,9 +39,10 @@ var RemoveNested = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files().IsFocused(). Lines( - Contains("modules").IsSelected(), - MatchesRegexp(`D.*innerSubPath`), - MatchesRegexp(`M.*\.gitmodules`), + Equals("▼ /").IsSelected(), + Equals(" ▼ modules"), + Equals(" D innerSubPath"), + Equals(" M .gitmodules"), ). NavigateToLine(Contains(".gitmodules")) diff --git a/pkg/integration/tests/submodule/reset.go b/pkg/integration/tests/submodule/reset.go index 85b379214..1396ade1b 100644 --- a/pkg/integration/tests/submodule/reset.go +++ b/pkg/integration/tests/submodule/reset.go @@ -71,15 +71,17 @@ var Reset = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files().Focus(). Lines( - MatchesRegexp(` M.*my_submodule_path \(submodule\)`), - Contains("other_file").IsSelected(), + Equals("▼ /"), + Equals(" M my_submodule_path (submodule)"), + Equals(" ?? other_file").IsSelected(), ). // Verify we can't use range select on submodules Press(keys.Universal.ToggleRangeSelect). SelectPreviousItem(). Lines( - MatchesRegexp(` M.*my_submodule_path \(submodule\)`).IsSelected(), - Contains("other_file").IsSelected(), + Equals("▼ /"), + Equals(" M my_submodule_path (submodule)").IsSelected(), + Equals(" ?? other_file").IsSelected(), ). Press(keys.Universal.Remove). Tap(func() { @@ -87,8 +89,9 @@ var Reset = NewIntegrationTest(NewIntegrationTestArgs{ }). Press(keys.Universal.ToggleRangeSelect). Lines( - MatchesRegexp(` M.*my_submodule_path \(submodule\)`).IsSelected(), - Contains("other_file"), + Equals("▼ /"), + Equals(" M my_submodule_path (submodule)").IsSelected(), + Equals(" ?? other_file"), ). Press(keys.Universal.Remove). Tap(func() { @@ -98,7 +101,7 @@ var Reset = NewIntegrationTest(NewIntegrationTestArgs{ Confirm() }). Lines( - Contains("other_file").IsSelected(), + Equals("?? other_file").IsSelected(), ) t.Views().Submodules().Focus(). diff --git a/pkg/integration/tests/undo/undo_commit.go b/pkg/integration/tests/undo/undo_commit.go index a636385eb..7fe61238c 100644 --- a/pkg/integration/tests/undo/undo_commit.go +++ b/pkg/integration/tests/undo/undo_commit.go @@ -57,8 +57,9 @@ var UndoCommit = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). Lines( - Contains("A file"), - Contains(" M other-file"), + Equals("▼ /"), + Equals(" A file"), + Equals(" M other-file"), ) t.Views().Commits().Focus(). @@ -71,7 +72,7 @@ var UndoCommit = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). Lines( - Contains(" M other-file"), + Equals(" M other-file"), ) // Undo again, this time discarding the original change before redoing again @@ -84,14 +85,15 @@ var UndoCommit = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files().Focus(). Lines( - Contains("A file"), - Contains(" M other-file").IsSelected(), + Equals("▼ /"), + Equals(" A file"), + Equals(" M other-file").IsSelected(), ). Press(keys.Universal.PrevItem). Press(keys.Universal.Remove). Tap(confirmDiscardFile). Lines( - Contains(" M other-file"), + Equals(" M other-file"), ). Press(keys.Universal.Redo). Tap(confirmRedo) @@ -104,7 +106,7 @@ var UndoCommit = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Files(). Lines( - Contains(" M other-file"), + Equals(" M other-file"), ) }, })