mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-08-24 02:24:25 -05:00
Only apply directory-level actions to visible files
This commit is contained in:
@@ -253,11 +253,14 @@ func (self *WorkingTreeCommands) Exclude(filename string) error {
|
||||
// WorktreeFileDiff returns the diff of a file
|
||||
func (self *WorkingTreeCommands) WorktreeFileDiff(file *models.File, plain bool, cached bool) string {
|
||||
// for now we assume an error means the file was deleted
|
||||
s, _ := self.WorktreeFileDiffCmdObj(file, plain, cached).RunWithOutput()
|
||||
s, _ := self.WorktreeFileDiffCmdObj(file, plain, cached, nil).RunWithOutput()
|
||||
return s
|
||||
}
|
||||
|
||||
func (self *WorkingTreeCommands) WorktreeFileDiffCmdObj(node models.IFile, plain bool, cached bool) *oscommands.CmdObj {
|
||||
// WorktreeFileDiffCmdObj returns a command object for diffing a file or directory
|
||||
// in the working tree. When pathOverrides is non-empty, those paths are used instead of
|
||||
// the node's path (used to diff only filtered/visible files within a directory).
|
||||
func (self *WorkingTreeCommands) WorktreeFileDiffCmdObj(node models.IFile, plain bool, cached bool, pathOverrides []string) *oscommands.CmdObj {
|
||||
colorArg := self.pagerConfig.GetColorArg()
|
||||
if plain {
|
||||
colorArg = "never"
|
||||
@@ -270,6 +273,11 @@ func (self *WorkingTreeCommands) WorktreeFileDiffCmdObj(node models.IFile, plain
|
||||
useExtDiff := extDiffCmd != "" && !plain
|
||||
useExtDiffGitConfig := self.pagerConfig.GetUseExternalDiffGitConfig() && !plain
|
||||
|
||||
paths := pathOverrides
|
||||
if len(paths) == 0 {
|
||||
paths = []string{node.GetPath()}
|
||||
}
|
||||
|
||||
cmdArgs := NewGitCmd("diff").
|
||||
ConfigIf(useExtDiff, "diff.external="+extDiffCmd).
|
||||
ArgIfElse(useExtDiff || useExtDiffGitConfig, "--ext-diff", "--no-ext-diff").
|
||||
@@ -282,7 +290,7 @@ func (self *WorkingTreeCommands) WorktreeFileDiffCmdObj(node models.IFile, plain
|
||||
ArgIf(noIndex, "--no-index").
|
||||
Arg("--").
|
||||
ArgIf(noIndex, "/dev/null").
|
||||
Arg(node.GetPath()).
|
||||
Arg(paths...).
|
||||
ArgIf(prevPath != "", prevPath).
|
||||
Dir(self.repoPaths.worktreePath).
|
||||
ToArgv()
|
||||
@@ -293,10 +301,10 @@ func (self *WorkingTreeCommands) WorktreeFileDiffCmdObj(node models.IFile, plain
|
||||
// ShowFileDiff get the diff of specified from and to. Typically this will be used for a single commit so it'll be 123abc^..123abc
|
||||
// but when we're in diff mode it could be any 'from' to any 'to'. The reverse flag is also here thanks to diff mode.
|
||||
func (self *WorkingTreeCommands) ShowFileDiff(from string, to string, reverse bool, fileName string, plain bool) (string, error) {
|
||||
return self.ShowFileDiffCmdObj(from, to, reverse, fileName, plain).RunWithOutput()
|
||||
return self.ShowFileDiffCmdObj(from, to, reverse, []string{fileName}, plain).RunWithOutput()
|
||||
}
|
||||
|
||||
func (self *WorkingTreeCommands) ShowFileDiffCmdObj(from string, to string, reverse bool, fileName string, plain bool) *oscommands.CmdObj {
|
||||
func (self *WorkingTreeCommands) ShowFileDiffCmdObj(from string, to string, reverse bool, fileNames []string, plain bool) *oscommands.CmdObj {
|
||||
contextSize := self.UserConfig().Git.DiffContextSize
|
||||
|
||||
colorArg := self.pagerConfig.GetColorArg()
|
||||
@@ -321,7 +329,7 @@ func (self *WorkingTreeCommands) ShowFileDiffCmdObj(from string, to string, reve
|
||||
ArgIf(reverse, "-R").
|
||||
ArgIf(!plain && self.UserConfig().Git.IgnoreWhitespaceInDiffView, "--ignore-all-space").
|
||||
Arg("--").
|
||||
Arg(fileName).
|
||||
Arg(fileNames...).
|
||||
Dir(self.repoPaths.worktreePath).
|
||||
ToArgv()
|
||||
|
||||
|
||||
@@ -152,7 +152,8 @@ func (self *CommitFilesController) GetOnRenderToMain() func() {
|
||||
from, to := self.context().GetFromAndToForDiff()
|
||||
from, reverse := self.c.Modes().Diffing.GetFromAndReverseArgsForDiff(from)
|
||||
|
||||
cmdObj := self.c.Git().WorkingTree.ShowFileDiffCmdObj(from, to, reverse, node.GetPath(), false)
|
||||
paths := self.pathsForDiff(node)
|
||||
cmdObj := self.c.Git().WorkingTree.ShowFileDiffCmdObj(from, to, reverse, paths, false)
|
||||
task := types.NewRunPtyTask(cmdObj.GetCmd())
|
||||
|
||||
self.c.RenderToMainViews(types.RefreshMainOpts{
|
||||
@@ -171,7 +172,7 @@ func (self *CommitFilesController) copyDiffToClipboard(path string, toastMessage
|
||||
from, to := self.context().GetFromAndToForDiff()
|
||||
from, reverse := self.c.Modes().Diffing.GetFromAndReverseArgsForDiff(from)
|
||||
|
||||
cmdObj := self.c.Git().WorkingTree.ShowFileDiffCmdObj(from, to, reverse, path, true)
|
||||
cmdObj := self.c.Git().WorkingTree.ShowFileDiffCmdObj(from, to, reverse, []string{path}, true)
|
||||
diff, err := cmdObj.RunWithOutput()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -400,15 +401,12 @@ func (self *CommitFilesController) toggleForPatch(selectedNodes []*filetree.Comm
|
||||
|
||||
selectedNodes = normalisedSelectedCommitFileNodes(selectedNodes)
|
||||
|
||||
// Collect all files to operate on. For directory nodes, this
|
||||
// includes all files under the directory, not just the ones
|
||||
// visible after filtering.
|
||||
filesToProcess := self.collectFilesForNodes(selectedNodes)
|
||||
|
||||
// Find if any file in the selection is unselected or partially added
|
||||
adding := lo.SomeBy(filesToProcess, func(file *models.CommitFile) bool {
|
||||
fileStatus := self.c.Git().Patch.PatchBuilder.GetFileStatus(file.Path, self.context().GetRef().RefName())
|
||||
return fileStatus == patch.PART || fileStatus == patch.UNSELECTED
|
||||
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.Path, self.context().GetRef().RefName())
|
||||
return fileStatus == patch.PART || fileStatus == patch.UNSELECTED
|
||||
})
|
||||
})
|
||||
|
||||
patchOperationFunction := self.c.Git().Patch.PatchBuilder.RemoveFile
|
||||
@@ -417,8 +415,11 @@ func (self *CommitFilesController) toggleForPatch(selectedNodes []*filetree.Comm
|
||||
patchOperationFunction = self.c.Git().Patch.PatchBuilder.AddFileWhole
|
||||
}
|
||||
|
||||
for _, file := range filesToProcess {
|
||||
if err := patchOperationFunction(file.Path); err != nil {
|
||||
for _, node := range selectedNodes {
|
||||
err := node.ForEachFile(func(file *models.CommitFile) error {
|
||||
return patchOperationFunction(file.Path)
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -550,6 +551,21 @@ func (self *CommitFilesController) GetOnClickFocusedMainView() func(mainViewName
|
||||
}
|
||||
}
|
||||
|
||||
// pathsForDiff returns the file paths to use for a diff command. When a text
|
||||
// filter is active and the node is a directory, only the visible (filtered)
|
||||
// file paths are returned so the diff reflects what the user sees.
|
||||
func (self *CommitFilesController) pathsForDiff(node *filetree.CommitFileNode) []string {
|
||||
if !node.IsFile() && self.context().IsFiltering() {
|
||||
var paths []string
|
||||
node.ForEachFile(func(file *models.CommitFile) error {
|
||||
paths = append(paths, file.Path)
|
||||
return nil
|
||||
})
|
||||
return paths
|
||||
}
|
||||
return []string{node.GetPath()}
|
||||
}
|
||||
|
||||
// NOTE: these functions are identical to those in files_controller.go (except for types) and
|
||||
// could also be cleaned up with some generics
|
||||
func normalisedSelectedCommitFileNodes(selectedNodes []*filetree.CommitFileNode) []*filetree.CommitFileNode {
|
||||
@@ -570,30 +586,6 @@ func isDescendentOfSelectedCommitFileNodes(node *filetree.CommitFileNode, select
|
||||
return false
|
||||
}
|
||||
|
||||
// collectFilesForNodes returns all commit files that should be operated on
|
||||
// for the given nodes. For directory nodes, this includes all files under
|
||||
// the directory from the full unfiltered list, so that toggling a directory
|
||||
// for a patch always affects all files regardless of any active text filter.
|
||||
func (self *CommitFilesController) collectFilesForNodes(nodes []*filetree.CommitFileNode) []*models.CommitFile {
|
||||
allCommitFiles := self.context().GetAllFiles()
|
||||
result := []*models.CommitFile{}
|
||||
|
||||
for _, node := range nodes {
|
||||
if node.IsFile() {
|
||||
result = append(result, node.File)
|
||||
} else {
|
||||
dirPath := node.GetPath()
|
||||
for _, file := range allCommitFiles {
|
||||
if dirPath == "" || strings.HasPrefix(file.Path, dirPath+"/") {
|
||||
result = append(result, file)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (self *CommitFilesController) isInTreeMode() *types.DisabledReason {
|
||||
if !self.context().CommitFileTreeViewModel.InTreeMode() {
|
||||
return &types.DisabledReason{Text: self.c.Tr.DisabledInFlatView}
|
||||
|
||||
@@ -294,7 +294,8 @@ func (self *FilesController) GetOnRenderToMain() func() {
|
||||
split := self.c.UserConfig().Gui.SplitDiff == "always" || (node.GetHasUnstagedChanges() && node.GetHasStagedChanges())
|
||||
mainShowsStaged := !split && node.GetHasStagedChanges()
|
||||
|
||||
cmdObj := self.c.Git().WorkingTree.WorktreeFileDiffCmdObj(node, false, mainShowsStaged)
|
||||
pathOverrides := self.pathOverridesForDiff(node)
|
||||
cmdObj := self.c.Git().WorkingTree.WorktreeFileDiffCmdObj(node, false, mainShowsStaged, pathOverrides)
|
||||
title := self.c.Tr.UnstagedChanges
|
||||
if mainShowsStaged {
|
||||
title = self.c.Tr.StagedChanges
|
||||
@@ -309,7 +310,7 @@ func (self *FilesController) GetOnRenderToMain() func() {
|
||||
}
|
||||
|
||||
if split {
|
||||
cmdObj := self.c.Git().WorkingTree.WorktreeFileDiffCmdObj(node, false, true)
|
||||
cmdObj := self.c.Git().WorkingTree.WorktreeFileDiffCmdObj(node, false, true, pathOverrides)
|
||||
|
||||
title := self.c.Tr.StagedChanges
|
||||
if mainShowsStaged {
|
||||
@@ -434,7 +435,19 @@ func (self *FilesController) pressWithLock(selectedNodes []*filetree.FileNode) e
|
||||
}
|
||||
}
|
||||
|
||||
// When filtering, expand directory nodes to individual visible file paths
|
||||
// so that only filtered files are staged/unstaged.
|
||||
toPaths := func(nodes []*filetree.FileNode) []string {
|
||||
if self.context().IsFiltering() {
|
||||
var paths []string
|
||||
for _, node := range nodes {
|
||||
node.ForEachFile(func(file *models.File) error {
|
||||
paths = append(paths, file.Path)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
return paths
|
||||
}
|
||||
return lo.Map(nodes, func(node *filetree.FileNode, _ int) string {
|
||||
return node.GetPath()
|
||||
})
|
||||
@@ -469,22 +482,29 @@ func (self *FilesController) pressWithLock(selectedNodes []*filetree.FileNode) e
|
||||
return err
|
||||
}
|
||||
|
||||
// need to partition the paths into tracked and untracked (where we assume directories are tracked). Then we'll run the commands separately.
|
||||
trackedNodes, untrackedNodes := utils.Partition(selectedNodes, func(node *filetree.FileNode) bool {
|
||||
// We treat all directories as tracked. I'm not actually sure why we do this but
|
||||
// it's been the existing behaviour for a while and nobody has complained
|
||||
return !node.IsFile() || node.GetIsTracked()
|
||||
})
|
||||
|
||||
if len(untrackedNodes) > 0 {
|
||||
if err := self.c.Git().WorkingTree.UnstageUntrackedFiles(toPaths(untrackedNodes)); err != nil {
|
||||
if self.context().IsFiltering() {
|
||||
// When filtering, only unstage visible files
|
||||
if err := self.unstageFilteredFiles(selectedNodes); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// need to partition the paths into tracked and untracked (where we assume directories are tracked). Then we'll run the commands separately.
|
||||
trackedNodes, untrackedNodes := utils.Partition(selectedNodes, func(node *filetree.FileNode) bool {
|
||||
// We treat all directories as tracked. I'm not actually sure why we do this but
|
||||
// it's been the existing behaviour for a while and nobody has complained
|
||||
return !node.IsFile() || node.GetIsTracked()
|
||||
})
|
||||
|
||||
if len(trackedNodes) > 0 {
|
||||
if err := self.c.Git().WorkingTree.UnstageTrackedFiles(toPaths(trackedNodes)); err != nil {
|
||||
return err
|
||||
if len(untrackedNodes) > 0 {
|
||||
if err := self.c.Git().WorkingTree.UnstageUntrackedFiles(toPaths(untrackedNodes)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(trackedNodes) > 0 {
|
||||
if err := self.c.Git().WorkingTree.UnstageTrackedFiles(toPaths(trackedNodes)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -503,6 +523,48 @@ func (self *FilesController) press(nodes []*filetree.FileNode) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// pathOverridesForDiff returns file paths to override the node's path in diff
|
||||
// commands when a text filter is active and the node is a directory. This
|
||||
// ensures the diff only shows filtered/visible files.
|
||||
func (self *FilesController) pathOverridesForDiff(node *filetree.FileNode) []string {
|
||||
if !node.IsFile() && self.context().IsFiltering() {
|
||||
var paths []string
|
||||
node.ForEachFile(func(file *models.File) error {
|
||||
paths = append(paths, file.Path)
|
||||
return nil
|
||||
})
|
||||
return paths
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// unstageFilteredFiles unstages only the visible (filtered) files from the
|
||||
// given nodes, correctly partitioning by tracked/untracked.
|
||||
func (self *FilesController) unstageFilteredFiles(nodes []*filetree.FileNode) error {
|
||||
var trackedPaths, untrackedPaths []string
|
||||
for _, node := range nodes {
|
||||
node.ForEachFile(func(file *models.File) error {
|
||||
if file.Tracked || file.HasStagedChanges {
|
||||
trackedPaths = append(trackedPaths, file.Path)
|
||||
} else {
|
||||
untrackedPaths = append(untrackedPaths, file.Path)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
if len(untrackedPaths) > 0 {
|
||||
if err := self.c.Git().WorkingTree.UnstageUntrackedFiles(untrackedPaths); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(trackedPaths) > 0 {
|
||||
if err := self.c.Git().WorkingTree.UnstageTrackedFiles(trackedPaths); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *FilesController) Context() types.Context {
|
||||
return self.context()
|
||||
}
|
||||
@@ -648,9 +710,21 @@ func (self *FilesController) toggleStagedAllWithLock() error {
|
||||
return err
|
||||
}
|
||||
|
||||
onlyTrackedFiles := self.context().GetStatusFilter() == filetree.DisplayTracked
|
||||
if err := self.c.Git().WorkingTree.StageAll(onlyTrackedFiles); err != nil {
|
||||
return err
|
||||
if self.context().IsFiltering() {
|
||||
// When filtering, only stage visible files
|
||||
var paths []string
|
||||
root.ForEachFile(func(file *models.File) error {
|
||||
paths = append(paths, file.Path)
|
||||
return nil
|
||||
})
|
||||
if err := self.c.Git().WorkingTree.StageFiles(paths, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
onlyTrackedFiles := self.context().GetStatusFilter() == filetree.DisplayTracked
|
||||
if err := self.c.Git().WorkingTree.StageAll(onlyTrackedFiles); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.c.LogAction(self.c.Tr.Actions.UnstageAllFiles)
|
||||
@@ -659,8 +733,15 @@ func (self *FilesController) toggleStagedAllWithLock() error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := self.c.Git().WorkingTree.UnstageAll(); err != nil {
|
||||
return err
|
||||
if self.context().IsFiltering() {
|
||||
// When filtering, only unstage visible files
|
||||
if err := self.unstageFilteredFiles([]*filetree.FileNode{root}); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := self.c.Git().WorkingTree.UnstageAll(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@ func (self *SubmodulesController) GetOnRenderToMain() func() {
|
||||
if file == nil {
|
||||
task = types.NewRenderStringTask(prefix)
|
||||
} else {
|
||||
cmdObj := self.c.Git().WorkingTree.WorktreeFileDiffCmdObj(file, false, !file.HasUnstagedChanges && file.HasStagedChanges)
|
||||
cmdObj := self.c.Git().WorkingTree.WorktreeFileDiffCmdObj(file, false, !file.HasUnstagedChanges && file.HasStagedChanges, nil)
|
||||
task = types.NewRunCommandTaskWithPrefix(cmdObj.GetCmd(), prefix)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package filter_and_search
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var FilterCommitFilesToggleDirectory = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Toggle a filtered directory for a custom patch only adds visible files",
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
SetupConfig: func(config *config.AppConfig) {},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.CreateDir("dir1")
|
||||
shell.CreateFileAndAdd("dir1/apple-grape", "apple-grape content\n")
|
||||
shell.CreateFileAndAdd("dir1/apple-orange", "apple-orange content\n")
|
||||
shell.CreateFileAndAdd("dir1/grape-orange", "grape-orange content\n")
|
||||
shell.Commit("first commit")
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
t.Views().Commits().
|
||||
Focus().
|
||||
Lines(
|
||||
Contains("first commit").IsSelected(),
|
||||
).
|
||||
PressEnter()
|
||||
|
||||
t.Views().CommitFiles().
|
||||
IsFocused().
|
||||
Lines(
|
||||
Contains("dir1").IsSelected(),
|
||||
Contains("apple-grape"),
|
||||
Contains("apple-orange"),
|
||||
Contains("grape-orange"),
|
||||
).
|
||||
// Filter to show only "apple" files (staying in tree view)
|
||||
FilterOrSearch("apple").
|
||||
Lines(
|
||||
// first item is always selected after filtering
|
||||
Contains("dir1").IsSelected(),
|
||||
Contains("apple-grape"),
|
||||
Contains("apple-orange"),
|
||||
).
|
||||
// dir1 is already selected; toggle for patch
|
||||
PressPrimaryAction().
|
||||
Lines(
|
||||
Contains("dir1").IsSelected(),
|
||||
Contains("● apple-grape"),
|
||||
Contains("● apple-orange"),
|
||||
)
|
||||
|
||||
t.Views().Information().Content(Contains("Building patch"))
|
||||
|
||||
// Verify only the filtered files are in the patch (not grape-orange)
|
||||
t.Views().Secondary().Content(
|
||||
Contains("apple-grape").
|
||||
Contains("apple-orange").
|
||||
DoesNotContain("grape-orange"),
|
||||
)
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,50 @@
|
||||
package filter_and_search
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var FilterFilesStageAll = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Toggle all staging with a filter only stages visible files",
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
SetupConfig: func(config *config.AppConfig) {},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.CreateDir("dir1")
|
||||
shell.CreateFile("dir1/apple-grape", "apple-grape content\n")
|
||||
shell.CreateFile("dir1/apple-orange", "apple-orange content\n")
|
||||
shell.CreateFile("dir1/grape-orange", "grape-orange content\n")
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
t.Views().Files().
|
||||
Focus().
|
||||
Lines(
|
||||
Contains("dir1").IsSelected(),
|
||||
Contains("apple-grape"),
|
||||
Contains("apple-orange"),
|
||||
Contains("grape-orange"),
|
||||
).
|
||||
// Filter to show only "apple" files
|
||||
FilterOrSearch("apple").
|
||||
Lines(
|
||||
// first item is always selected after filtering
|
||||
Contains("dir1").IsSelected(),
|
||||
Contains("apple-grape"),
|
||||
Contains("apple-orange"),
|
||||
).
|
||||
// Stage all visible files
|
||||
Press(keys.Files.ToggleStagedAll).
|
||||
// Clear the filter and verify only apple files are staged
|
||||
PressEscape()
|
||||
|
||||
t.Views().Files().
|
||||
IsFocused().
|
||||
Lines(
|
||||
Contains("dir1").IsSelected(),
|
||||
Contains("A apple-grape"),
|
||||
Contains("A apple-orange"),
|
||||
Contains("?? grape-orange"),
|
||||
)
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,50 @@
|
||||
package filter_and_search
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var FilterFilesStageDirectory = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Staging a filtered directory only stages visible files",
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
SetupConfig: func(config *config.AppConfig) {},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.CreateDir("dir1")
|
||||
shell.CreateFile("dir1/apple-grape", "apple-grape content\n")
|
||||
shell.CreateFile("dir1/apple-orange", "apple-orange content\n")
|
||||
shell.CreateFile("dir1/grape-orange", "grape-orange content\n")
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
t.Views().Files().
|
||||
Focus().
|
||||
Lines(
|
||||
Contains("dir1").IsSelected(),
|
||||
Contains("apple-grape"),
|
||||
Contains("apple-orange"),
|
||||
Contains("grape-orange"),
|
||||
).
|
||||
// Filter to show only "apple" files
|
||||
FilterOrSearch("apple").
|
||||
Lines(
|
||||
// first item is always selected after filtering
|
||||
Contains("dir1").IsSelected(),
|
||||
Contains("apple-grape"),
|
||||
Contains("apple-orange"),
|
||||
).
|
||||
// dir1 is already selected; stage it
|
||||
PressPrimaryAction().
|
||||
// Clear the filter to see all files and verify only apple files are staged
|
||||
PressEscape()
|
||||
|
||||
t.Views().Files().
|
||||
IsFocused().
|
||||
Lines(
|
||||
Contains("dir1"),
|
||||
Contains("A apple-grape"),
|
||||
Contains("A apple-orange"),
|
||||
Contains("?? grape-orange"),
|
||||
)
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,64 @@
|
||||
package patch_building
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var ToggleDirectory = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Toggle a directory for a custom patch",
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
SetupConfig: func(config *config.AppConfig) {},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.CreateDir("dir1")
|
||||
shell.CreateFileAndAdd("dir1/file1", "file1 content\n")
|
||||
shell.CreateFileAndAdd("dir1/file2", "file2 content\n")
|
||||
shell.CreateFileAndAdd("dir1/file3", "file3 content\n")
|
||||
shell.CreateFileAndAdd("other-file", "other content\n")
|
||||
shell.Commit("first commit")
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
t.Views().Commits().
|
||||
Focus().
|
||||
Lines(
|
||||
Contains("first commit").IsSelected(),
|
||||
).
|
||||
PressEnter()
|
||||
|
||||
t.Views().CommitFiles().
|
||||
IsFocused().
|
||||
Lines(
|
||||
Equals("▼ /").IsSelected(),
|
||||
Equals(" ▼ dir1"),
|
||||
Equals(" A file1"),
|
||||
Equals(" A file2"),
|
||||
Equals(" A file3"),
|
||||
Equals(" A other-file"),
|
||||
).
|
||||
NavigateToLine(Contains("dir1")).
|
||||
PressPrimaryAction().
|
||||
Lines(
|
||||
Equals("▼ /"),
|
||||
Equals(" ▼ dir1").IsSelected(),
|
||||
Equals(" ● file1"),
|
||||
Equals(" ● file2"),
|
||||
Equals(" ● file3"),
|
||||
Equals(" A other-file"),
|
||||
)
|
||||
|
||||
t.Views().Information().Content(Contains("Building patch"))
|
||||
|
||||
// Toggle the directory again to remove all files from the patch
|
||||
t.Views().CommitFiles().
|
||||
PressPrimaryAction().
|
||||
Lines(
|
||||
Equals("▼ /"),
|
||||
Equals(" ▼ dir1").IsSelected(),
|
||||
Equals(" A file1"),
|
||||
Equals(" A file2"),
|
||||
Equals(" A file3"),
|
||||
Equals(" A other-file"),
|
||||
)
|
||||
},
|
||||
})
|
||||
@@ -232,7 +232,10 @@ var tests = []*components.IntegrationTest{
|
||||
file.StageRangeSelect,
|
||||
filter_and_search.FilterByFileStatus,
|
||||
filter_and_search.FilterCommitFiles,
|
||||
filter_and_search.FilterCommitFilesToggleDirectory,
|
||||
filter_and_search.FilterFiles,
|
||||
filter_and_search.FilterFilesStageAll,
|
||||
filter_and_search.FilterFilesStageDirectory,
|
||||
filter_and_search.FilterFuzzy,
|
||||
filter_and_search.FilterMenu,
|
||||
filter_and_search.FilterMenuByKeybinding,
|
||||
@@ -354,6 +357,7 @@ var tests = []*components.IntegrationTest{
|
||||
patch_building.SelectAllFiles,
|
||||
patch_building.SpecificSelection,
|
||||
patch_building.StartNewPatch,
|
||||
patch_building.ToggleDirectory,
|
||||
patch_building.ToggleRange,
|
||||
reflog.Checkout,
|
||||
reflog.CherryPick,
|
||||
|
||||
Reference in New Issue
Block a user