Add tests for diffing a directory that files were renamed into or out of

Pathspec limiting happens before rename detection in git's tree diff, so
filtering the diff to a directory hides the delete-side entry of a rename
whose other end is outside that directory. Git then has nothing to pair
up, and reports a file moved into the directory as an addition and one
moved out of it as a deletion.

Selecting a directory is supposed to filter the commit's diff down, never
to change it, so both are wrong.
This commit is contained in:
Stefan Haller 2026-08-12 10:37:38 +02:00
parent c199ac69f5
commit 6913f2afce
3 changed files with 233 additions and 0 deletions

View file

@ -0,0 +1,112 @@
package commit
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var DirectoryDiffWithRenamedFiles = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Selecting a directory in the commit files panel shows the renames of files that were moved into or out of it",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.CreateDir("dir")
shell.CreateDir("dir/nested")
shell.CreateFileAndAdd("file1", "file1 content\n")
shell.CreateFileAndAdd("dir/file2", "file2 content\n")
shell.CreateFileAndAdd("dir/nested/file3", "file3 content\n")
shell.Commit("initial commit")
shell.RenameFileInGit("file1", "dir/file1")
shell.RenameFileInGit("dir/file2", "dir/file2-renamed")
shell.RenameFileInGit("dir/nested/file3", "file3")
shell.Commit("move files")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Commits().
Focus().
Lines(
Contains("move files").IsSelected(),
Contains("initial commit"),
).
PressEnter()
t.Views().CommitFiles().
IsFocused().
Lines(
Equals("▼ /").IsSelected(),
Equals(" ▼ dir"),
Equals(" R file1 → file1"),
Equals(" R file2 → file2-renamed"),
Equals(" R dir/nested/file3 → file3"),
)
t.Views().Main().ContainsLines(
Equals("diff --git a/file1 b/dir/file1"),
Equals("similarity index 100%"),
Equals("rename from file1"),
Equals("rename to dir/file1"),
Equals("diff --git a/dir/file2 b/dir/file2-renamed"),
Equals("similarity index 100%"),
Equals("rename from dir/file2"),
Equals("rename to dir/file2-renamed"),
Equals("diff --git a/dir/nested/file3 b/file3"),
Equals("similarity index 100%"),
Equals("rename from dir/nested/file3"),
Equals("rename to file3"),
)
t.Views().CommitFiles().
SelectNextItem().
SelectedLine(Equals(" ▼ dir"))
t.Views().Main().
/* EXPECTED:
ContainsLines(
Equals("diff --git a/file1 b/dir/file1"),
Equals("similarity index 100%"),
Equals("rename from file1"),
Equals("rename to dir/file1"),
Equals("diff --git a/dir/file2 b/dir/file2-renamed"),
Equals("similarity index 100%"),
Equals("rename from dir/file2"),
Equals("rename to dir/file2-renamed"),
Equals("diff --git a/dir/nested/file3 b/file3"),
Equals("similarity index 100%"),
Equals("rename from dir/nested/file3"),
Equals("rename to file3"),
)
ACTUAL: */
ContainsLines(
Equals("diff --git a/dir/file1 b/dir/file1"),
Equals("new file mode 100644"),
Contains("index"),
Equals("--- /dev/null"),
Equals("+++ b/dir/file1"),
Equals("@@ -0,0 +1 @@"),
Equals("+file1 content"),
Equals("diff --git a/dir/file2 b/dir/file2-renamed"),
Equals("similarity index 100%"),
Equals("rename from dir/file2"),
Equals("rename to dir/file2-renamed"),
Equals("diff --git a/dir/nested/file3 b/dir/nested/file3"),
Equals("deleted file mode 100644"),
Contains("index"),
Equals("--- a/dir/nested/file3"),
Equals("+++ /dev/null"),
Equals("@@ -1 +0,0 @@"),
Equals("-file3 content"),
)
t.Views().CommitFiles().
SelectNextItem().
SelectedLine(Equals(" R file1 → file1"))
t.Views().Main().ContainsLines(
Equals("diff --git a/file1 b/dir/file1"),
Equals("similarity index 100%"),
Equals("rename from file1"),
Equals("rename to dir/file1"),
)
},
})

View file

@ -0,0 +1,119 @@
package file
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var DirectoryDiffWithRenamedFiles = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Selecting a directory in the files panel shows the renames of files that were moved into or out of it",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.CreateDir("dir")
shell.CreateDir("dir/nested")
shell.CreateFileAndAdd("file1", "file1 content\n")
shell.CreateFileAndAdd("dir/file2", "file2 content\n")
shell.CreateFileAndAdd("dir/nested/file3", "file3 content\n")
shell.Commit("initial commit")
shell.RenameFileInGit("file1", "dir/file1")
shell.RenameFileInGit("dir/file2", "dir/file2-renamed")
shell.RenameFileInGit("dir/nested/file3", "file3")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Files().
IsFocused().
Lines(
Equals("▼ /").IsSelected(),
Equals(" ▼ dir"),
Equals(" R file1 → file1"),
Equals(" R file2 → file2-renamed"),
Equals(" R dir/nested/file3 → file3"),
)
t.Views().Main().ContainsLines(
Equals("diff --git a/file1 b/dir/file1"),
Equals("similarity index 100%"),
Equals("rename from file1"),
Equals("rename to dir/file1"),
Equals("diff --git a/dir/file2 b/dir/file2-renamed"),
Equals("similarity index 100%"),
Equals("rename from dir/file2"),
Equals("rename to dir/file2-renamed"),
Equals("diff --git a/dir/nested/file3 b/file3"),
Equals("similarity index 100%"),
Equals("rename from dir/nested/file3"),
Equals("rename to file3"),
)
t.Views().Files().
SelectNextItem().
SelectedLine(Equals(" ▼ dir"))
t.Views().Main().
/* EXPECTED:
ContainsLines(
Equals("diff --git a/file1 b/dir/file1"),
Equals("similarity index 100%"),
Equals("rename from file1"),
Equals("rename to dir/file1"),
Equals("diff --git a/dir/file2 b/dir/file2-renamed"),
Equals("similarity index 100%"),
Equals("rename from dir/file2"),
Equals("rename to dir/file2-renamed"),
Equals("diff --git a/dir/nested/file3 b/file3"),
Equals("similarity index 100%"),
Equals("rename from dir/nested/file3"),
Equals("rename to file3"),
)
ACTUAL: */
ContainsLines(
Equals("diff --git a/dir/file1 b/dir/file1"),
Equals("new file mode 100644"),
Contains("index"),
Equals("--- /dev/null"),
Equals("+++ b/dir/file1"),
Equals("@@ -0,0 +1 @@"),
Equals("+file1 content"),
Equals("diff --git a/dir/file2 b/dir/file2-renamed"),
Equals("similarity index 100%"),
Equals("rename from dir/file2"),
Equals("rename to dir/file2-renamed"),
Equals("diff --git a/dir/nested/file3 b/dir/nested/file3"),
Equals("deleted file mode 100644"),
Contains("index"),
Equals("--- a/dir/nested/file3"),
Equals("+++ /dev/null"),
Equals("@@ -1 +0,0 @@"),
Equals("-file3 content"),
)
// The same applies when a filter reduces the directory to a single file
t.Views().Files().
FilterOrSearch("file1").
Lines(
Equals("▼ dir").IsSelected(),
Equals(" R file1 → file1"),
)
t.Views().Main().
/* EXPECTED:
ContainsLines(
Equals("diff --git a/file1 b/dir/file1"),
Equals("similarity index 100%"),
Equals("rename from file1"),
Equals("rename to dir/file1"),
)
ACTUAL: */
ContainsLines(
Equals("diff --git a/dir/file1 b/dir/file1"),
Equals("new file mode 100644"),
Contains("index"),
Equals("--- /dev/null"),
Equals("+++ b/dir/file1"),
Equals("@@ -0,0 +1 @@"),
Equals("+file1 content"),
)
},
})

View file

@ -126,6 +126,7 @@ var tests = []*components.IntegrationTest{
commit.CreateAmendCommit,
commit.CreateFixupCommitInBranchStack,
commit.CreateTag,
commit.DirectoryDiffWithRenamedFiles,
commit.DisableCopyCommitMessageBody,
commit.DiscardOldFileChanges,
commit.DiscardRenamedFile,
@ -231,6 +232,7 @@ var tests = []*components.IntegrationTest{
file.CollapseExpand,
file.CopyMenu,
file.DirWithUntrackedFile,
file.DirectoryDiffWithRenamedFiles,
file.DiscardAllDirChanges,
file.DiscardAllDirChangesWhenFiltering,
file.DiscardRangeSelect,