diff --git a/pkg/commands/git_commands/commit.go b/pkg/commands/git_commands/commit.go index d067e9831..cd4443bb9 100644 --- a/pkg/commands/git_commands/commit.go +++ b/pkg/commands/git_commands/commit.go @@ -240,10 +240,10 @@ func (self *CommitCommands) AmendHeadCmdObj() *oscommands.CmdObj { return self.cmd.New(cmdArgs) } -func (self *CommitCommands) ShowCmdObj(hash string, filterPaths []string) *oscommands.CmdObj { +func (self *CommitCommands) ShowCmdObj(hash string, filterPaths []string, ignoreExternalDiff bool) *oscommands.CmdObj { cmdArgs := NewGitCmd("show"). Config("diff.noprefix=false"). - AddCommonDiffArgs(self.diffRendererConfigManager, self.UserConfig(), true). + AddCommonDiffArgs(self.diffRendererConfigManager, self.UserConfig(), !ignoreExternalDiff). Arg("--submodule"). Arg("--color=" + self.diffRendererConfigManager.GetColorArg()). Arg("--stat"). diff --git a/pkg/commands/git_commands/commit_test.go b/pkg/commands/git_commands/commit_test.go index 9b2ddecfb..c6e4fdda9 100644 --- a/pkg/commands/git_commands/commit_test.go +++ b/pkg/commands/git_commands/commit_test.go @@ -341,7 +341,7 @@ func TestCommitShowCmdObj(t *testing.T) { } instance := buildCommitCommands(commonDeps{userConfig: userConfig, appState: &config.AppState{}, runner: runner, repoPaths: &repoPaths}) - assert.NoError(t, instance.ShowCmdObj("1234567890", s.filterPaths).Run()) + assert.NoError(t, instance.ShowCmdObj("1234567890", s.filterPaths, false).Run()) runner.CheckForMissingCalls() }) } diff --git a/pkg/commands/git_commands/diff.go b/pkg/commands/git_commands/diff.go index 114d3f0c6..a379419a8 100644 --- a/pkg/commands/git_commands/diff.go +++ b/pkg/commands/git_commands/diff.go @@ -83,12 +83,14 @@ func (self *DiffCommands) probeEmitsMetadata(cmdObj *oscommands.CmdObj) bool { } // This is for generating diffs to be shown in the UI (e.g. rendering a range -// diff to the main view). It uses a custom diff renderer if one is configured. -func (self *DiffCommands) DiffCmdObj(diffArgs []string) *oscommands.CmdObj { +// diff to the main view). It uses a custom diff renderer if one is configured, unless +// ignoreExternalDiff is set (the focused main view's raw-diff fallback; keeps the +// colour, unlike a plain diff). +func (self *DiffCommands) DiffCmdObj(diffArgs []string, ignoreExternalDiff bool) *oscommands.CmdObj { return self.cmd.New( NewGitCmd("diff"). Config("diff.noprefix=false"). - AddCommonDiffArgs(self.diffRendererConfigManager, self.UserConfig(), true). + AddCommonDiffArgs(self.diffRendererConfigManager, self.UserConfig(), !ignoreExternalDiff). Arg("--submodule"). Arg(fmt.Sprintf("--color=%s", self.diffRendererConfigManager.GetColorArg())). Arg(diffArgs...). diff --git a/pkg/commands/git_commands/stash.go b/pkg/commands/git_commands/stash.go index ea23c5141..5142a405c 100644 --- a/pkg/commands/git_commands/stash.go +++ b/pkg/commands/git_commands/stash.go @@ -80,10 +80,10 @@ func (self *StashCommands) Hash(index int) (string, error) { return strings.Trim(hash, "\r\n"), err } -func (self *StashCommands) ShowStashEntryCmdObj(index int) *oscommands.CmdObj { +func (self *StashCommands) ShowStashEntryCmdObj(index int, ignoreExternalDiff bool) *oscommands.CmdObj { // "-u" is the same as "--include-untracked", but the latter fails in older git versions for some reason cmdArgs := NewGitCmd("stash").Arg("show"). - AddCommonDiffArgs(self.diffRendererConfigManager, self.UserConfig(), true). + AddCommonDiffArgs(self.diffRendererConfigManager, self.UserConfig(), !ignoreExternalDiff). Arg("-p"). Arg("--stat"). Arg("-u"). diff --git a/pkg/commands/git_commands/stash_test.go b/pkg/commands/git_commands/stash_test.go index 8f5629c98..46f2bacf4 100644 --- a/pkg/commands/git_commands/stash_test.go +++ b/pkg/commands/git_commands/stash_test.go @@ -174,7 +174,7 @@ func TestStashStashEntryCmdObj(t *testing.T) { } instance := buildStashCommands(commonDeps{userConfig: userConfig, appState: &config.AppState{}, repoPaths: &repoPaths}) - cmdStr := instance.ShowStashEntryCmdObj(s.index).Args() + cmdStr := instance.ShowStashEntryCmdObj(s.index, false).Args() assert.Equal(t, s.expected, cmdStr) }) } diff --git a/pkg/commands/git_commands/working_tree.go b/pkg/commands/git_commands/working_tree.go index fc45805da..966446992 100644 --- a/pkg/commands/git_commands/working_tree.go +++ b/pkg/commands/git_commands/working_tree.go @@ -434,10 +434,10 @@ func (self *WorkingTreeCommands) ShowFileDiff(from string, to string, reverse bo if previousPath != "" { fileNames = append(fileNames, previousPath) } - return self.ShowFileDiffCmdObj(from, to, reverse, fileNames, plain).RunWithOutput() + return self.ShowFileDiffCmdObj(from, to, reverse, fileNames, plain, false).RunWithOutput() } -func (self *WorkingTreeCommands) ShowFileDiffCmdObj(from string, to string, reverse bool, fileNames []string, plain bool) *oscommands.CmdObj { +func (self *WorkingTreeCommands) ShowFileDiffCmdObj(from string, to string, reverse bool, fileNames []string, plain bool, ignoreExternalDiff bool) *oscommands.CmdObj { colorArg := self.diffRendererConfigManager.GetColorArg() if plain { colorArg = "never" @@ -445,7 +445,7 @@ func (self *WorkingTreeCommands) ShowFileDiffCmdObj(from string, to string, reve cmdArgs := NewGitCmd("diff"). Config("diff.noprefix=false"). - AddCommonDiffArgs(self.diffRendererConfigManager, self.UserConfig(), !plain). + AddCommonDiffArgs(self.diffRendererConfigManager, self.UserConfig(), !plain && !ignoreExternalDiff). Arg("--submodule"). Arg(fmt.Sprintf("--color=%s", colorArg)). Arg(from). diff --git a/pkg/gui/controllers/commits_files_controller.go b/pkg/gui/controllers/commits_files_controller.go index 0435b183b..50de22093 100644 --- a/pkg/gui/controllers/commits_files_controller.go +++ b/pkg/gui/controllers/commits_files_controller.go @@ -176,7 +176,7 @@ func (self *CommitFilesController) GetOnRenderToMain() func() { from, reverse := self.c.Modes().Diffing.GetFromAndReverseArgsForDiff(from) paths := self.pathsForDiff(node) - cmdObj := self.c.Git().WorkingTree.ShowFileDiffCmdObj(from, to, reverse, paths, false) + cmdObj := self.c.Git().WorkingTree.ShowFileDiffCmdObj(from, to, reverse, paths, false, false) task := types.NewRunPtyTask(cmdObj.GetCmd()) // Keep the inclusion gutter in step with the content as this diff (re-)renders. @@ -201,7 +201,7 @@ func (self *CommitFilesController) copyDiffToClipboard(paths []string, toastMess from, to := self.context().GetFromAndToForDiff() from, reverse := self.c.Modes().Diffing.GetFromAndReverseArgsForDiff(from) - cmdObj := self.c.Git().WorkingTree.ShowFileDiffCmdObj(from, to, reverse, paths, true) + cmdObj := self.c.Git().WorkingTree.ShowFileDiffCmdObj(from, to, reverse, paths, true, false) diff, err := cmdObj.RunWithOutput() if err != nil { return err diff --git a/pkg/gui/controllers/files_controller.go b/pkg/gui/controllers/files_controller.go index fa1cde460..6310e8c69 100644 --- a/pkg/gui/controllers/files_controller.go +++ b/pkg/gui/controllers/files_controller.go @@ -353,7 +353,7 @@ func (self *FilesController) renderNonTextualConflict(node *filetree.FileNode) { message := self.conflictResolutionHint(node.File.GetMergeStateDescription(self.c.Tr)) if node.File.ShortStatus == "DU" || node.File.ShortStatus == "UD" { - cmdObj := self.c.Git().Diff.DiffCmdObj([]string{"--base", "--", node.GetPath()}) + cmdObj := self.c.Git().Diff.DiffCmdObj([]string{"--base", "--", node.GetPath()}, false) prefix := message + "\n\n" if node.File.ShortStatus == "DU" { prefix += self.c.Tr.MergeConflictIncomingDiff @@ -387,7 +387,7 @@ func (self *FilesController) renderWorkingTreeDiff(node *filetree.FileNode) { refreshOpts := types.RefreshMainOpts{ Pair: self.c.MainViewPairs().Normal, Main: &types.ViewUpdateOpts{ - Task: diffMainViewTask(renderRaw, cmdObj.GetCmd()), + Task: types.NewMainViewDiffTask(renderRaw, cmdObj.GetCmd()), SubTitle: self.c.Helpers().Diff.IgnoringWhitespaceSubTitle(), Title: title, }, @@ -404,7 +404,7 @@ func (self *FilesController) renderWorkingTreeDiff(node *filetree.FileNode) { refreshOpts.Secondary = &types.ViewUpdateOpts{ Title: title, SubTitle: self.c.Helpers().Diff.IgnoringWhitespaceSubTitle(), - Task: diffMainViewTask(renderRaw, cmdObj.GetCmd()), + Task: types.NewMainViewDiffTask(renderRaw, cmdObj.GetCmd()), } } diff --git a/pkg/gui/controllers/helpers/diff_helper.go b/pkg/gui/controllers/helpers/diff_helper.go index 6af3b2b5c..e8d3a7a70 100644 --- a/pkg/gui/controllers/helpers/diff_helper.go +++ b/pkg/gui/controllers/helpers/diff_helper.go @@ -72,12 +72,12 @@ func (self *DiffHelper) GetUpdateTaskForRenderingCommitsDiff(commit *models.Comm args = append(args, filterPath) } } - cmdObj := self.c.Git().Diff.DiffCmdObj(args) + cmdObj := self.c.Git().Diff.DiffCmdObj(args, false) prefix := style.FgYellow.Sprintf("%s %s-%s\n\n", self.c.Tr.ShowingDiffForRange, from.ShortRefName(), to.ShortRefName()) return types.NewRunPtyTaskWithPrefix(cmdObj.GetCmd(), prefix) } - cmdObj := self.c.Git().Commit.ShowCmdObj(commit.Hash(), self.FilterPathsForCommit(commit)) + cmdObj := self.c.Git().Commit.ShowCmdObj(commit.Hash(), self.FilterPathsForCommit(commit), false) return types.NewRunPtyTask(cmdObj.GetCmd()) } @@ -100,7 +100,7 @@ func (self *DiffHelper) ExitDiffMode() error { func (self *DiffHelper) RenderDiff() { args := self.DiffArgs() - cmdObj := self.c.Git().Diff.DiffCmdObj(args) + cmdObj := self.c.Git().Diff.DiffCmdObj(args, false) prefix := style.FgMagenta.Sprintf( "%s %s\n\n", self.c.Tr.ShowingGitDiff, diff --git a/pkg/gui/controllers/main_view_controller.go b/pkg/gui/controllers/main_view_controller.go index 5c0254882..0c67fc011 100644 --- a/pkg/gui/controllers/main_view_controller.go +++ b/pkg/gui/controllers/main_view_controller.go @@ -5,7 +5,6 @@ import ( "encoding/hex" "errors" "fmt" - "os/exec" "path/filepath" "strings" @@ -310,20 +309,6 @@ func placeOrHideInitialDiffSelection(c *ControllerCommon, mainContext *context.M showSelectionAtLine(view, target, true) } -// diffMainViewTask builds the task a side panel uses to render its diff into the main -// view, choosing between the normal pty task and the raw-diff fallback. When renderRaw -// is set (the focused main view needs to act on a diff the configured pager can't -// resolve, see StagingHelper.DiffMainViewShouldRenderRaw) it uses a plain command task, -// which — unlike the pty task — doesn't pipe the diff through a stdin pager (GIT_PAGER); -// the external diff command, if any, is suppressed in the cmd itself. The caller passes -// the same renderRaw to the diff-cmd builder so the two stay in step. -func diffMainViewTask(renderRaw bool, cmd *exec.Cmd) types.UpdateTask { - if renderRaw { - return types.NewRunCommandTask(cmd) - } - return types.NewRunPtyTask(cmd) -} - // updateFocusedMainViewSelectionVisibility shows or hides the focused-main-view selection // to match what a side panel is rendering into the main view, called from the panel's // render-to-main so the selection tracks content changes (a refresh after the last change diff --git a/pkg/gui/controllers/reflog_commits_controller.go b/pkg/gui/controllers/reflog_commits_controller.go index 2d0751a0b..a4115878a 100644 --- a/pkg/gui/controllers/reflog_commits_controller.go +++ b/pkg/gui/controllers/reflog_commits_controller.go @@ -45,7 +45,7 @@ func (self *ReflogCommitsController) GetOnRenderToMain() func() { if commit == nil { task = types.NewRenderStringTask("No reflog history") } else { - cmdObj := self.c.Git().Commit.ShowCmdObj(commit.Hash(), self.c.Helpers().Diff.FilterPathsForCommit(commit)) + cmdObj := self.c.Git().Commit.ShowCmdObj(commit.Hash(), self.c.Helpers().Diff.FilterPathsForCommit(commit), false) task = types.NewRunPtyTask(cmdObj.GetCmd()) } diff --git a/pkg/gui/controllers/stash_controller.go b/pkg/gui/controllers/stash_controller.go index 27c7b78a9..095bc8a75 100644 --- a/pkg/gui/controllers/stash_controller.go +++ b/pkg/gui/controllers/stash_controller.go @@ -94,7 +94,7 @@ func (self *StashController) GetOnRenderToMain() func() { } else { prefix := style.FgYellow.Sprintf("%s\n\n", stashEntry.Description()) task = types.NewRunPtyTaskWithPrefix( - self.c.Git().Stash.ShowStashEntryCmdObj(stashEntry.Index).GetCmd(), + self.c.Git().Stash.ShowStashEntryCmdObj(stashEntry.Index, false).GetCmd(), prefix, ) } diff --git a/pkg/gui/types/rendering.go b/pkg/gui/types/rendering.go index 70e47e033..00d5f3a46 100644 --- a/pkg/gui/types/rendering.go +++ b/pkg/gui/types/rendering.go @@ -98,3 +98,26 @@ func NewRunPtyTask(cmd *exec.Cmd) *RunPtyTask { func NewRunPtyTaskWithPrefix(cmd *exec.Cmd, prefix string) *RunPtyTask { return &RunPtyTask{Cmd: cmd, Prefix: prefix} } + +// NewMainViewDiffTask builds the task for rendering a diff into the main view, +// choosing between the normal pty task and the focused main view's raw-diff +// fallback. When renderRaw is set (the focused main view needs to act on a diff the +// configured pager can't resolve) it uses a plain command task, which — unlike the +// pty task — doesn't pipe the diff through a stdin pager (GIT_PAGER); the external +// diff command, if any, is suppressed in the cmd itself (its ignoreExternalDiff arg). +// The caller passes the same renderRaw to the diff-cmd builder so the two stay in step. +func NewMainViewDiffTask(renderRaw bool, cmd *exec.Cmd) UpdateTask { + if renderRaw { + return NewRunCommandTask(cmd) + } + return NewRunPtyTask(cmd) +} + +// NewMainViewDiffTaskWithPrefix is NewMainViewDiffTask for a diff rendered with a +// leading prefix (e.g. a range-diff or stash header). +func NewMainViewDiffTaskWithPrefix(renderRaw bool, cmd *exec.Cmd, prefix string) UpdateTask { + if renderRaw { + return NewRunCommandTaskWithPrefix(cmd, prefix) + } + return NewRunPtyTaskWithPrefix(cmd, prefix) +}