Skip to content

Commit 71c5fa9

Browse files
authored
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 -->
2 parents a0dd3be + 7a1b631 commit 71c5fa9

File tree

8 files changed

+87
-12
lines changed

8 files changed

+87
-12
lines changed

pkg/commands/git_commands/working_tree.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,15 @@ func (self *WorkingTreeCommands) OpenMergeToolCmdObj() oscommands.ICmdObj {
3434

3535
// StageFile stages a file
3636
func (self *WorkingTreeCommands) StageFile(path string) error {
37-
return self.StageFiles([]string{path})
37+
return self.StageFiles([]string{path}, nil)
3838
}
3939

40-
func (self *WorkingTreeCommands) StageFiles(paths []string) error {
41-
cmdArgs := NewGitCmd("add").Arg("--").Arg(paths...).ToArgv()
40+
func (self *WorkingTreeCommands) StageFiles(paths []string, extraArgs []string) error {
41+
cmdArgs := NewGitCmd("add").
42+
Arg(extraArgs...).
43+
Arg("--").
44+
Arg(paths...).
45+
ToArgv()
4246

4347
return self.cmd.New(cmdArgs).Run()
4448
}

pkg/commands/git_commands/working_tree_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func TestWorkingTreeStageFiles(t *testing.T) {
3030

3131
instance := buildWorkingTreeCommands(commonDeps{runner: runner})
3232

33-
assert.NoError(t, instance.StageFiles([]string{"test.txt", "test2.txt"}))
33+
assert.NoError(t, instance.StageFiles([]string{"test.txt", "test2.txt"}, nil))
3434
runner.CheckForMissingCalls()
3535
}
3636

pkg/gui/controllers/files_controller.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,13 +421,19 @@ func (self *FilesController) pressWithLock(selectedNodes []*filetree.FileNode) e
421421
unstagedSelectedNodes := filterNodesHaveUnstagedChanges(selectedNodes)
422422

423423
if len(unstagedSelectedNodes) > 0 {
424+
var extraArgs []string
425+
426+
if self.context().GetFilter() == filetree.DisplayTracked {
427+
extraArgs = []string{"-u"}
428+
}
429+
424430
self.c.LogAction(self.c.Tr.Actions.StageFile)
425431

426432
if err := self.optimisticChange(unstagedSelectedNodes, self.optimisticStage); err != nil {
427433
return err
428434
}
429435

430-
if err := self.c.Git().WorkingTree.StageFiles(toPaths(unstagedSelectedNodes)); err != nil {
436+
if err := self.c.Git().WorkingTree.StageFiles(toPaths(unstagedSelectedNodes), extraArgs); err != nil {
431437
return err
432438
}
433439
} else {

pkg/gui/controllers/helpers/refresh_helper.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,7 @@ func (self *RefreshHelper) refreshStateFiles() error {
565565

566566
if len(pathsToStage) > 0 {
567567
self.c.LogAction(self.c.Tr.Actions.StageResolvedFiles)
568-
if err := self.c.Git().WorkingTree.StageFiles(pathsToStage); err != nil {
568+
if err := self.c.Git().WorkingTree.StageFiles(pathsToStage, nil); err != nil {
569569
return err
570570
}
571571
}

pkg/gui/filetree/file_tree.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,11 @@ func (self *FileTree) getFilesForDisplay() []*models.File {
8888
case DisplayUnstaged:
8989
return self.FilterFiles(func(file *models.File) bool { return file.HasUnstagedChanges })
9090
case DisplayTracked:
91-
return self.FilterFiles(func(file *models.File) bool { return file.Tracked })
91+
// untracked but staged files are technically not tracked by git
92+
// but including such files in the filtered mode helps see what files are getting committed
93+
return self.FilterFiles(func(file *models.File) bool { return file.Tracked || file.HasStagedChanges })
9294
case DisplayUntracked:
93-
return self.FilterFiles(func(file *models.File) bool { return !file.Tracked })
95+
return self.FilterFiles(func(file *models.File) bool { return !(file.Tracked || file.HasStagedChanges) })
9496
case DisplayConflicted:
9597
return self.FilterFiles(func(file *models.File) bool { return file.HasMergeConflicts })
9698
default:

pkg/integration/tests/filter_and_search/filter_by_file_status.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,16 @@ var FilterByFileStatus = NewIntegrationTest(NewIntegrationTestArgs{
2121

2222
shell.CreateFile("file-untracked", "bar")
2323
shell.UpdateFile("file-tracked", "baz")
24+
25+
shell.CreateFile("file-staged-but-untracked", "qux")
26+
shell.GitAdd("file-staged-but-untracked")
2427
},
2528
Run: func(t *TestDriver, keys config.KeybindingConfig) {
2629
t.Views().Files().
2730
Focus().
2831
Lines(
29-
Contains(`file-tracked`).IsSelected(),
32+
Equals("A file-staged-but-untracked").IsSelected(),
33+
Equals(" M file-tracked"),
3034
).
3135
Press(keys.Files.OpenStatusFilter).
3236
Tap(func() {
@@ -36,7 +40,7 @@ var FilterByFileStatus = NewIntegrationTest(NewIntegrationTestArgs{
3640
Confirm()
3741
}).
3842
Lines(
39-
Contains(`file-untracked`).IsSelected(),
43+
Equals("?? file-untracked").IsSelected(),
4044
).
4145
Press(keys.Files.OpenStatusFilter).
4246
Tap(func() {
@@ -46,7 +50,8 @@ var FilterByFileStatus = NewIntegrationTest(NewIntegrationTestArgs{
4650
Confirm()
4751
}).
4852
Lines(
49-
Contains(`file-tracked`).IsSelected(),
53+
Equals("A file-staged-but-untracked").IsSelected(),
54+
Equals(" M file-tracked"),
5055
).
5156
Press(keys.Files.OpenStatusFilter).
5257
Tap(func() {
@@ -56,7 +61,8 @@ var FilterByFileStatus = NewIntegrationTest(NewIntegrationTestArgs{
5661
Confirm()
5762
}).
5863
Lines(
59-
Contains(`file-tracked`).IsSelected(),
64+
Equals("A file-staged-but-untracked").IsSelected(),
65+
Equals(" M file-tracked"),
6066
)
6167
},
6268
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package filter_and_search
2+
3+
import (
4+
"github.com/jesseduffield/lazygit/pkg/config"
5+
. "github.com/jesseduffield/lazygit/pkg/integration/components"
6+
)
7+
8+
var StagingFolderStagesOnlyTrackedFilesInTrackedOnlyFilter = NewIntegrationTest(NewIntegrationTestArgs{
9+
Description: "Staging entire folder in tracked only view, should stage only tracked files",
10+
ExtraCmdArgs: []string{},
11+
Skip: false,
12+
SetupConfig: func(config *config.AppConfig) {
13+
},
14+
SetupRepo: func(shell *Shell) {
15+
shell.CreateDir("test")
16+
shell.CreateFileAndAdd("test/file-tracked", "foo")
17+
18+
shell.Commit("first commit")
19+
20+
shell.CreateFile("test/file-untracked", "bar")
21+
shell.UpdateFile("test/file-tracked", "baz")
22+
},
23+
Run: func(t *TestDriver, keys config.KeybindingConfig) {
24+
t.Views().Files().
25+
Focus().
26+
Lines(
27+
Equals("▼ test").IsSelected(),
28+
Equals(" M file-tracked"),
29+
Equals(" ?? file-untracked"),
30+
).
31+
Press(keys.Files.OpenStatusFilter).
32+
Tap(func() {
33+
t.ExpectPopup().Menu().
34+
Title(Equals("Filtering")).
35+
Select(Contains("Show only tracked files")).
36+
Confirm()
37+
}).
38+
Lines(
39+
Equals("▼ test").IsSelected(),
40+
Equals(" M file-tracked"),
41+
).
42+
PressPrimaryAction().
43+
Press(keys.Files.OpenStatusFilter).
44+
Tap(func() {
45+
t.ExpectPopup().Menu().
46+
Title(Equals("Filtering")).
47+
Select(Contains("No filter")).
48+
Confirm()
49+
}).
50+
Lines(
51+
Equals("▼ test").IsSelected(),
52+
Equals(" M file-tracked"), // 'M' is now in the left column, so file is staged
53+
Equals(" ?? file-untracked"),
54+
)
55+
},
56+
})

pkg/integration/tests/test_list.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ var tests = []*components.IntegrationTest{
207207
filter_and_search.NestedFilter,
208208
filter_and_search.NestedFilterTransient,
209209
filter_and_search.NewSearch,
210+
filter_and_search.StagingFolderStagesOnlyTrackedFilesInTrackedOnlyFilter,
210211
filter_by_author.SelectAuthor,
211212
filter_by_author.TypeAuthor,
212213
filter_by_path.CliArg,

0 commit comments

Comments
 (0)