mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-05-11 20:36:03 +02:00
Commit only tracked files in tracked filter view (#4386)
- **PR Description** When in tracked filter view, selecting a folder for staging should only stage files that are tracked by git. Previously, it staged even untracked files that were not in view. All staged (even untracked) files are shown in tracked filter view. Fixes #4245 - **Please check if the PR fulfills these requirements** * [x] Cheatsheets are up-to-date (run `go generate ./...`) * [x] Code has been formatted (see [here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#code-formatting)) * [x] Tests have been added/updated (see [here](https://github.com/jesseduffield/lazygit/blob/master/pkg/integration/README.md) for the integration test guide) * [ ] Text is internationalised (see [here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#internationalisation)) * [ ] If a new UserConfig entry was added, make sure it can be hot-reloaded (see [here](https://github.com/jesseduffield/lazygit/blob/master/docs/dev/Codebase_Guide.md#using-userconfig)) * [ ] Docs have been updated if necessary * [x] You've read through your own file changes for silly mistakes etc <!-- Be sure to name your PR with an imperative e.g. 'Add worktrees view' see https://github.com/jesseduffield/lazygit/releases/tag/v0.40.0 for examples -->
This commit is contained in:
commit
71c5fa9688
8 changed files with 87 additions and 12 deletions
|
@ -34,11 +34,15 @@ func (self *WorkingTreeCommands) OpenMergeToolCmdObj() oscommands.ICmdObj {
|
||||||
|
|
||||||
// StageFile stages a file
|
// StageFile stages a file
|
||||||
func (self *WorkingTreeCommands) StageFile(path string) error {
|
func (self *WorkingTreeCommands) StageFile(path string) error {
|
||||||
return self.StageFiles([]string{path})
|
return self.StageFiles([]string{path}, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *WorkingTreeCommands) StageFiles(paths []string) error {
|
func (self *WorkingTreeCommands) StageFiles(paths []string, extraArgs []string) error {
|
||||||
cmdArgs := NewGitCmd("add").Arg("--").Arg(paths...).ToArgv()
|
cmdArgs := NewGitCmd("add").
|
||||||
|
Arg(extraArgs...).
|
||||||
|
Arg("--").
|
||||||
|
Arg(paths...).
|
||||||
|
ToArgv()
|
||||||
|
|
||||||
return self.cmd.New(cmdArgs).Run()
|
return self.cmd.New(cmdArgs).Run()
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ func TestWorkingTreeStageFiles(t *testing.T) {
|
||||||
|
|
||||||
instance := buildWorkingTreeCommands(commonDeps{runner: runner})
|
instance := buildWorkingTreeCommands(commonDeps{runner: runner})
|
||||||
|
|
||||||
assert.NoError(t, instance.StageFiles([]string{"test.txt", "test2.txt"}))
|
assert.NoError(t, instance.StageFiles([]string{"test.txt", "test2.txt"}, nil))
|
||||||
runner.CheckForMissingCalls()
|
runner.CheckForMissingCalls()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -421,13 +421,19 @@ func (self *FilesController) pressWithLock(selectedNodes []*filetree.FileNode) e
|
||||||
unstagedSelectedNodes := filterNodesHaveUnstagedChanges(selectedNodes)
|
unstagedSelectedNodes := filterNodesHaveUnstagedChanges(selectedNodes)
|
||||||
|
|
||||||
if len(unstagedSelectedNodes) > 0 {
|
if len(unstagedSelectedNodes) > 0 {
|
||||||
|
var extraArgs []string
|
||||||
|
|
||||||
|
if self.context().GetFilter() == filetree.DisplayTracked {
|
||||||
|
extraArgs = []string{"-u"}
|
||||||
|
}
|
||||||
|
|
||||||
self.c.LogAction(self.c.Tr.Actions.StageFile)
|
self.c.LogAction(self.c.Tr.Actions.StageFile)
|
||||||
|
|
||||||
if err := self.optimisticChange(unstagedSelectedNodes, self.optimisticStage); err != nil {
|
if err := self.optimisticChange(unstagedSelectedNodes, self.optimisticStage); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := self.c.Git().WorkingTree.StageFiles(toPaths(unstagedSelectedNodes)); err != nil {
|
if err := self.c.Git().WorkingTree.StageFiles(toPaths(unstagedSelectedNodes), extraArgs); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -565,7 +565,7 @@ func (self *RefreshHelper) refreshStateFiles() error {
|
||||||
|
|
||||||
if len(pathsToStage) > 0 {
|
if len(pathsToStage) > 0 {
|
||||||
self.c.LogAction(self.c.Tr.Actions.StageResolvedFiles)
|
self.c.LogAction(self.c.Tr.Actions.StageResolvedFiles)
|
||||||
if err := self.c.Git().WorkingTree.StageFiles(pathsToStage); err != nil {
|
if err := self.c.Git().WorkingTree.StageFiles(pathsToStage, nil); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,9 +88,11 @@ func (self *FileTree) getFilesForDisplay() []*models.File {
|
||||||
case DisplayUnstaged:
|
case DisplayUnstaged:
|
||||||
return self.FilterFiles(func(file *models.File) bool { return file.HasUnstagedChanges })
|
return self.FilterFiles(func(file *models.File) bool { return file.HasUnstagedChanges })
|
||||||
case DisplayTracked:
|
case DisplayTracked:
|
||||||
return self.FilterFiles(func(file *models.File) bool { return file.Tracked })
|
// untracked but staged files are technically not tracked by git
|
||||||
|
// but including such files in the filtered mode helps see what files are getting committed
|
||||||
|
return self.FilterFiles(func(file *models.File) bool { return file.Tracked || file.HasStagedChanges })
|
||||||
case DisplayUntracked:
|
case DisplayUntracked:
|
||||||
return self.FilterFiles(func(file *models.File) bool { return !file.Tracked })
|
return self.FilterFiles(func(file *models.File) bool { return !(file.Tracked || file.HasStagedChanges) })
|
||||||
case DisplayConflicted:
|
case DisplayConflicted:
|
||||||
return self.FilterFiles(func(file *models.File) bool { return file.HasMergeConflicts })
|
return self.FilterFiles(func(file *models.File) bool { return file.HasMergeConflicts })
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -21,12 +21,16 @@ var FilterByFileStatus = NewIntegrationTest(NewIntegrationTestArgs{
|
||||||
|
|
||||||
shell.CreateFile("file-untracked", "bar")
|
shell.CreateFile("file-untracked", "bar")
|
||||||
shell.UpdateFile("file-tracked", "baz")
|
shell.UpdateFile("file-tracked", "baz")
|
||||||
|
|
||||||
|
shell.CreateFile("file-staged-but-untracked", "qux")
|
||||||
|
shell.GitAdd("file-staged-but-untracked")
|
||||||
},
|
},
|
||||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||||
t.Views().Files().
|
t.Views().Files().
|
||||||
Focus().
|
Focus().
|
||||||
Lines(
|
Lines(
|
||||||
Contains(`file-tracked`).IsSelected(),
|
Equals("A file-staged-but-untracked").IsSelected(),
|
||||||
|
Equals(" M file-tracked"),
|
||||||
).
|
).
|
||||||
Press(keys.Files.OpenStatusFilter).
|
Press(keys.Files.OpenStatusFilter).
|
||||||
Tap(func() {
|
Tap(func() {
|
||||||
|
@ -36,7 +40,7 @@ var FilterByFileStatus = NewIntegrationTest(NewIntegrationTestArgs{
|
||||||
Confirm()
|
Confirm()
|
||||||
}).
|
}).
|
||||||
Lines(
|
Lines(
|
||||||
Contains(`file-untracked`).IsSelected(),
|
Equals("?? file-untracked").IsSelected(),
|
||||||
).
|
).
|
||||||
Press(keys.Files.OpenStatusFilter).
|
Press(keys.Files.OpenStatusFilter).
|
||||||
Tap(func() {
|
Tap(func() {
|
||||||
|
@ -46,7 +50,8 @@ var FilterByFileStatus = NewIntegrationTest(NewIntegrationTestArgs{
|
||||||
Confirm()
|
Confirm()
|
||||||
}).
|
}).
|
||||||
Lines(
|
Lines(
|
||||||
Contains(`file-tracked`).IsSelected(),
|
Equals("A file-staged-but-untracked").IsSelected(),
|
||||||
|
Equals(" M file-tracked"),
|
||||||
).
|
).
|
||||||
Press(keys.Files.OpenStatusFilter).
|
Press(keys.Files.OpenStatusFilter).
|
||||||
Tap(func() {
|
Tap(func() {
|
||||||
|
@ -56,7 +61,8 @@ var FilterByFileStatus = NewIntegrationTest(NewIntegrationTestArgs{
|
||||||
Confirm()
|
Confirm()
|
||||||
}).
|
}).
|
||||||
Lines(
|
Lines(
|
||||||
Contains(`file-tracked`).IsSelected(),
|
Equals("A file-staged-but-untracked").IsSelected(),
|
||||||
|
Equals(" M file-tracked"),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
package filter_and_search
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/config"
|
||||||
|
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||||
|
)
|
||||||
|
|
||||||
|
var StagingFolderStagesOnlyTrackedFilesInTrackedOnlyFilter = NewIntegrationTest(NewIntegrationTestArgs{
|
||||||
|
Description: "Staging entire folder in tracked only view, should stage only tracked files",
|
||||||
|
ExtraCmdArgs: []string{},
|
||||||
|
Skip: false,
|
||||||
|
SetupConfig: func(config *config.AppConfig) {
|
||||||
|
},
|
||||||
|
SetupRepo: func(shell *Shell) {
|
||||||
|
shell.CreateDir("test")
|
||||||
|
shell.CreateFileAndAdd("test/file-tracked", "foo")
|
||||||
|
|
||||||
|
shell.Commit("first commit")
|
||||||
|
|
||||||
|
shell.CreateFile("test/file-untracked", "bar")
|
||||||
|
shell.UpdateFile("test/file-tracked", "baz")
|
||||||
|
},
|
||||||
|
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||||
|
t.Views().Files().
|
||||||
|
Focus().
|
||||||
|
Lines(
|
||||||
|
Equals("▼ test").IsSelected(),
|
||||||
|
Equals(" M file-tracked"),
|
||||||
|
Equals(" ?? file-untracked"),
|
||||||
|
).
|
||||||
|
Press(keys.Files.OpenStatusFilter).
|
||||||
|
Tap(func() {
|
||||||
|
t.ExpectPopup().Menu().
|
||||||
|
Title(Equals("Filtering")).
|
||||||
|
Select(Contains("Show only tracked files")).
|
||||||
|
Confirm()
|
||||||
|
}).
|
||||||
|
Lines(
|
||||||
|
Equals("▼ test").IsSelected(),
|
||||||
|
Equals(" M file-tracked"),
|
||||||
|
).
|
||||||
|
PressPrimaryAction().
|
||||||
|
Press(keys.Files.OpenStatusFilter).
|
||||||
|
Tap(func() {
|
||||||
|
t.ExpectPopup().Menu().
|
||||||
|
Title(Equals("Filtering")).
|
||||||
|
Select(Contains("No filter")).
|
||||||
|
Confirm()
|
||||||
|
}).
|
||||||
|
Lines(
|
||||||
|
Equals("▼ test").IsSelected(),
|
||||||
|
Equals(" M file-tracked"), // 'M' is now in the left column, so file is staged
|
||||||
|
Equals(" ?? file-untracked"),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
})
|
|
@ -207,6 +207,7 @@ var tests = []*components.IntegrationTest{
|
||||||
filter_and_search.NestedFilter,
|
filter_and_search.NestedFilter,
|
||||||
filter_and_search.NestedFilterTransient,
|
filter_and_search.NestedFilterTransient,
|
||||||
filter_and_search.NewSearch,
|
filter_and_search.NewSearch,
|
||||||
|
filter_and_search.StagingFolderStagesOnlyTrackedFilesInTrackedOnlyFilter,
|
||||||
filter_by_author.SelectAuthor,
|
filter_by_author.SelectAuthor,
|
||||||
filter_by_author.TypeAuthor,
|
filter_by_author.TypeAuthor,
|
||||||
filter_by_path.CliArg,
|
filter_by_path.CliArg,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue