From 6913f2afce25a539233b21de2b478a249bbbed15 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Wed, 12 Aug 2026 10:37:38 +0200 Subject: [PATCH] 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. --- .../directory_diff_with_renamed_files.go | 112 +++++++++++++++++ .../file/directory_diff_with_renamed_files.go | 119 ++++++++++++++++++ pkg/integration/tests/test_list.go | 2 + 3 files changed, 233 insertions(+) create mode 100644 pkg/integration/tests/commit/directory_diff_with_renamed_files.go create mode 100644 pkg/integration/tests/file/directory_diff_with_renamed_files.go diff --git a/pkg/integration/tests/commit/directory_diff_with_renamed_files.go b/pkg/integration/tests/commit/directory_diff_with_renamed_files.go new file mode 100644 index 000000000..ef3c71e5e --- /dev/null +++ b/pkg/integration/tests/commit/directory_diff_with_renamed_files.go @@ -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"), + ) + }, +}) diff --git a/pkg/integration/tests/file/directory_diff_with_renamed_files.go b/pkg/integration/tests/file/directory_diff_with_renamed_files.go new file mode 100644 index 000000000..bd4e667c2 --- /dev/null +++ b/pkg/integration/tests/file/directory_diff_with_renamed_files.go @@ -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"), + ) + }, +}) diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go index fac10efb4..0124de268 100644 --- a/pkg/integration/tests/test_list.go +++ b/pkg/integration/tests/test_list.go @@ -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,