mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-10-06 05:57:38 -04:00
The pane beside a commit's diff showed the patch being built from it by assembling the text itself. That text could not be handed to a diff renderer the way a diff can: a stdin filter might have coped, but a tool that diffs two files could not. Its idea of how much context to show around a hunk was also its own rather than git's. Materialize the patch instead: write each of its files as it is before the patch into one tree and as it is after into another, and let git diff the two trees. The patch becomes a diff of real files, rendered by whatever renders the rest of them, with git's own context around it. Its lines can then be pointed at; taking them back out of the patch will need that. The trees are named a and b, so that with git's own prefixes suppressed the paths read like an ordinary diff's over the repo's own paths. They are written when the patch changes rather than when it is shown, the patch builder counting its own versions for that, and they go away with the patch. A renamed file is materialized under the name the patch expects to find it under. Where the patch carries the rename, that is the name the file had before, so the rename comes out as a rename. git names the trees themselves in the two rename lines, having only the two paths to go by. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
160 lines
4.4 KiB
Go
160 lines
4.4 KiB
Go
package patch_building
|
|
|
|
import (
|
|
"github.com/jesseduffield/lazygit/pkg/config"
|
|
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
|
)
|
|
|
|
var SpecificSelection = NewIntegrationTest(NewIntegrationTestArgs{
|
|
Description: "Build a custom patch with a specific selection of lines, adding individual lines, as well as a range and hunk, and adding a file directly",
|
|
ExtraCmdArgs: []string{},
|
|
Skip: false,
|
|
SetupConfig: func(config *config.AppConfig) {
|
|
config.GetUserConfig().Gui.UseHunkModeInStagingView = false
|
|
},
|
|
SetupRepo: func(shell *Shell) {
|
|
shell.CreateFileAndAdd("hunk-file", "1a\n1b\n1c\n1d\n1e\n1f\n1g\n1h\n1i\n1j\n1k\n1l\n1m\n1n\n1o\n1p\n1q\n1r\n1s\n1t\n1u\n1v\n1w\n1x\n1y\n1z\n")
|
|
shell.Commit("first commit")
|
|
|
|
// making changes in two separate places for the sake of having two hunks
|
|
shell.UpdateFileAndAdd("hunk-file", "aa\n1b\ncc\n1d\n1e\n1f\n1g\n1h\n1i\n1j\n1k\n1l\n1m\n1n\n1o\n1p\n1q\n1r\n1s\ntt\nuu\nvv\n1w\n1x\n1y\n1z\n")
|
|
|
|
shell.CreateFileAndAdd("line-file", "2a\n2b\n2c\n2d\n2e\n2f\n2g\n2h\n2i\n2j\n2k\n2l\n2m\n2n\n2o\n2p\n2q\n2r\n2s\n2t\n2u\n2v\n2w\n2x\n2y\n2z\n")
|
|
shell.CreateFileAndAdd("direct-file", "direct file content")
|
|
shell.Commit("second commit")
|
|
},
|
|
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
|
t.Views().Commits().
|
|
Focus().
|
|
Lines(
|
|
Contains("second commit").IsSelected(),
|
|
Contains("first commit"),
|
|
).
|
|
PressEnter()
|
|
|
|
t.Views().CommitFiles().
|
|
IsFocused().
|
|
Lines(
|
|
Equals("▼ /").IsSelected(),
|
|
Contains("direct-file"),
|
|
Contains("hunk-file"),
|
|
Contains("line-file"),
|
|
).
|
|
SelectNextItem().
|
|
PressPrimaryAction().
|
|
Tap(func() {
|
|
t.Views().Information().Content(Contains("Building patch"))
|
|
|
|
t.Views().Secondary().Content(Contains("direct file content"))
|
|
}).
|
|
NavigateToLine(Contains("hunk-file")).
|
|
PressEnter()
|
|
|
|
t.Views().PatchBuilding().
|
|
IsFocused().
|
|
SelectedLines(
|
|
Contains("-1a"),
|
|
).
|
|
Press(keys.Main.ToggleSelectHunk).
|
|
SelectedLines(
|
|
Contains(`-1a`),
|
|
Contains(`+aa`),
|
|
).
|
|
PressPrimaryAction().
|
|
SelectedLines(
|
|
Contains(`-1c`),
|
|
Contains(`+cc`),
|
|
).
|
|
Tap(func() {
|
|
t.Views().Information().Content(Contains("Building patch"))
|
|
|
|
t.Views().Secondary().Content(
|
|
// when we're inside the patch building panel, we only show the patch
|
|
// in the secondary panel that relates to the selected file
|
|
DoesNotContain("direct file content").
|
|
Contains("@@ -1,6 +1,6 @@").
|
|
Contains(" 1f"),
|
|
)
|
|
}).
|
|
// Cancel hunk select
|
|
PressEscape().
|
|
// Escape the view
|
|
PressEscape()
|
|
|
|
t.Views().CommitFiles().
|
|
IsFocused().
|
|
NavigateToLine(Contains("line-file")).
|
|
PressEnter()
|
|
|
|
t.Views().PatchBuilding().
|
|
IsFocused().
|
|
SelectedLines(
|
|
Contains("+2a"),
|
|
).
|
|
PressPrimaryAction().
|
|
SelectedLines(
|
|
Contains("+2b"),
|
|
).
|
|
NavigateToLine(Contains("+2c")).
|
|
Press(keys.Universal.ToggleRangeSelect).
|
|
NavigateToLine(Contains("+2e")).
|
|
PressPrimaryAction().
|
|
SelectedLines(
|
|
Contains("+2f"),
|
|
).
|
|
NavigateToLine(Contains("+2g")).
|
|
PressPrimaryAction().
|
|
SelectedLines(
|
|
Contains("+2h"),
|
|
).
|
|
Tap(func() {
|
|
t.Views().Information().Content(Contains("Building patch"))
|
|
|
|
t.Views().Secondary().ContainsLines(
|
|
Contains("+2a"),
|
|
Contains("+2c"),
|
|
Contains("+2d"),
|
|
Contains("+2e"),
|
|
Contains("+2g"),
|
|
)
|
|
}).
|
|
PressEscape().
|
|
Tap(func() {
|
|
t.Views().Secondary().ContainsLines(
|
|
// direct-file patch
|
|
Contains(`diff --git a/direct-file b/direct-file`),
|
|
Contains(`index`),
|
|
Contains(`--- a/direct-file`),
|
|
Contains(`+++ b/direct-file`),
|
|
Contains(`@@ -0,0 +1 @@`),
|
|
Contains(`+direct file content`),
|
|
Contains(`\ No newline at end of file`),
|
|
// hunk-file patch
|
|
Contains(`diff --git a/hunk-file b/hunk-file`),
|
|
Contains(`index`),
|
|
Contains(`--- a/hunk-file`),
|
|
Contains(`+++ b/hunk-file`),
|
|
// git works out the context of the patch's own hunks, which is why
|
|
// this is not the six lines the file's diff had
|
|
Contains(`@@ -1,4 +1,4 @@`),
|
|
Contains(`-1a`),
|
|
Contains(`+aa`),
|
|
Contains(` 1b`),
|
|
Contains(` 1c`),
|
|
Contains(` 1d`),
|
|
// line-file patch
|
|
Contains(`diff --git a/line-file b/line-file`),
|
|
Contains(`index`),
|
|
Contains(`--- a/line-file`),
|
|
Contains(`+++ b/line-file`),
|
|
Contains(`@@ -0,0 +1,5 @@`),
|
|
Contains(`+2a`),
|
|
Contains(`+2c`),
|
|
Contains(`+2d`),
|
|
Contains(`+2e`),
|
|
Contains(`+2g`),
|
|
)
|
|
})
|
|
},
|
|
})
|