From 442592a1494afc346e9e970dd2496fc28bef36b1 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Wed, 21 Aug 2024 08:31:35 +0200 Subject: [PATCH] Show diff for range selection in commits and sub-commits panel In other views that show lists of commits (reflog and stash) it doesn't make sense to show a range diff of selected entries because they don't form a linear sequence, so we keep the previous behavior of showing the diff for the free end of the selection range in those view. The same applies to the commits view if the selection range includes rebasing todos; these can have an arbitrary order, and a range diff doesn't make sense for those. --- pkg/gui/context/local_commits_context.go | 13 +++++++++ pkg/gui/context/sub_commits_context.go | 13 +++++++++ pkg/gui/controllers/helpers/diff_helper.go | 27 +++++++++++++++++++ .../controllers/local_commits_controller.go | 4 +-- pkg/gui/controllers/sub_commits_controller.go | 5 ++-- pkg/gui/types/ref.go | 5 ++++ pkg/i18n/english.go | 2 ++ 7 files changed, 64 insertions(+), 5 deletions(-) diff --git a/pkg/gui/context/local_commits_context.go b/pkg/gui/context/local_commits_context.go index eecb16107..6d1a72aae 100644 --- a/pkg/gui/context/local_commits_context.go +++ b/pkg/gui/context/local_commits_context.go @@ -128,6 +128,19 @@ func (self *LocalCommitsContext) GetSelectedRef() types.Ref { return commit } +func (self *LocalCommitsContext) GetSelectedRefRangeForDiffFiles() *types.RefRange { + commits, startIdx, endIdx := self.GetSelectedItems() + if commits == nil || startIdx == endIdx { + return nil + } + from := commits[len(commits)-1] + to := commits[0] + if from.IsTODO() || to.IsTODO() { + return nil + } + return &types.RefRange{From: from, To: to} +} + // Returns the commit hash of the selected commit, or an empty string if no // commit is selected func (self *LocalCommitsContext) GetSelectedCommitHash() string { diff --git a/pkg/gui/context/sub_commits_context.go b/pkg/gui/context/sub_commits_context.go index 6adb7a53e..cd19dcae2 100644 --- a/pkg/gui/context/sub_commits_context.go +++ b/pkg/gui/context/sub_commits_context.go @@ -186,6 +186,19 @@ func (self *SubCommitsContext) GetSelectedRef() types.Ref { return commit } +func (self *SubCommitsContext) GetSelectedRefRangeForDiffFiles() *types.RefRange { + commits, startIdx, endIdx := self.GetSelectedItems() + if commits == nil || startIdx == endIdx { + return nil + } + from := commits[len(commits)-1] + to := commits[0] + if from.Divergence != to.Divergence { + return nil + } + return &types.RefRange{From: from, To: to} +} + func (self *SubCommitsContext) GetCommits() []*models.Commit { return self.getModel() } diff --git a/pkg/gui/controllers/helpers/diff_helper.go b/pkg/gui/controllers/helpers/diff_helper.go index 1aad725fc..42cdb99dd 100644 --- a/pkg/gui/controllers/helpers/diff_helper.go +++ b/pkg/gui/controllers/helpers/diff_helper.go @@ -4,6 +4,7 @@ import ( "strings" "github.com/jesseduffield/lazygit/pkg/commands/git_commands" + "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/gui/context" "github.com/jesseduffield/lazygit/pkg/gui/modes/diffing" "github.com/jesseduffield/lazygit/pkg/gui/style" @@ -49,6 +50,32 @@ func (self *DiffHelper) DiffArgs() []string { return output } +// Returns an update task that can be passed to RenderToMainViews to render a +// diff for the selected commit(s). We need to pass both the selected commit +// and the refRange for a range selection. If the refRange is nil (meaning that +// either there's no range, or it can't be diffed for some reason), then we want +// to fall back to rendering the diff for the single commit. +func (self *DiffHelper) GetUpdateTaskForRenderingCommitsDiff(commit *models.Commit, refRange *types.RefRange) types.UpdateTask { + if refRange != nil { + from, to := refRange.From, refRange.To + args := []string{from.ParentRefName(), to.RefName(), "--stat", "-p"} + if self.c.GetAppState().IgnoreWhitespaceInDiffView { + args = append(args, "--ignore-all-space") + } + args = append(args, "--") + if path := self.c.Modes().Filtering.GetPath(); path != "" { + args = append(args, path) + } + cmdObj := self.c.Git().Diff.DiffCmdObj(args) + task := types.NewRunPtyTask(cmdObj.GetCmd()) + task.Prefix = style.FgYellow.Sprintf("%s %s-%s\n\n", self.c.Tr.ShowingDiffForRange, from.ShortRefName(), to.ShortRefName()) + return task + } + + cmdObj := self.c.Git().Commit.ShowCmdObj(commit.Hash, self.c.Modes().Filtering.GetPath()) + return types.NewRunPtyTask(cmdObj.GetCmd()) +} + func (self *DiffHelper) ExitDiffMode() error { self.c.Modes().Diffing = diffing.New() return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC}) diff --git a/pkg/gui/controllers/local_commits_controller.go b/pkg/gui/controllers/local_commits_controller.go index 2d4232f33..f0ca624c1 100644 --- a/pkg/gui/controllers/local_commits_controller.go +++ b/pkg/gui/controllers/local_commits_controller.go @@ -290,8 +290,8 @@ func (self *LocalCommitsController) GetOnRenderToMain() func() error { task = types.NewRenderStringTask( self.c.Tr.ExecCommandHere + "\n\n" + commit.Name) } else { - cmdObj := self.c.Git().Commit.ShowCmdObj(commit.Hash, self.c.Modes().Filtering.GetPath()) - task = types.NewRunPtyTask(cmdObj.GetCmd()) + refRange := self.context().GetSelectedRefRangeForDiffFiles() + task = self.c.Helpers().Diff.GetUpdateTaskForRenderingCommitsDiff(commit, refRange) } return self.c.RenderToMainViews(types.RefreshMainOpts{ diff --git a/pkg/gui/controllers/sub_commits_controller.go b/pkg/gui/controllers/sub_commits_controller.go index 9ce708272..0f3ca9907 100644 --- a/pkg/gui/controllers/sub_commits_controller.go +++ b/pkg/gui/controllers/sub_commits_controller.go @@ -46,9 +46,8 @@ func (self *SubCommitsController) GetOnRenderToMain() func() error { if commit == nil { task = types.NewRenderStringTask("No commits") } else { - cmdObj := self.c.Git().Commit.ShowCmdObj(commit.Hash, self.c.Modes().Filtering.GetPath()) - - task = types.NewRunPtyTask(cmdObj.GetCmd()) + refRange := self.context().GetSelectedRefRangeForDiffFiles() + task = self.c.Helpers().Diff.GetUpdateTaskForRenderingCommitsDiff(commit, refRange) } return self.c.RenderToMainViews(types.RefreshMainOpts{ diff --git a/pkg/gui/types/ref.go b/pkg/gui/types/ref.go index 4319f12e0..18fc7e998 100644 --- a/pkg/gui/types/ref.go +++ b/pkg/gui/types/ref.go @@ -7,3 +7,8 @@ type Ref interface { ParentRefName() string Description() string } + +type RefRange struct { + From Ref + To Ref +} diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index 831cfa27e..b09a14d79 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -581,6 +581,7 @@ type TranslationSet struct { OpenCommandLogMenu string OpenCommandLogMenuTooltip string ShowingGitDiff string + ShowingDiffForRange string CommitDiff string CopyCommitHashToClipboard string CommitHash string @@ -1569,6 +1570,7 @@ func EnglishTranslationSet() *TranslationSet { OpenCommandLogMenu: "View command log options", OpenCommandLogMenuTooltip: "View options for the command log e.g. show/hide the command log and focus the command log.", ShowingGitDiff: "Showing output for:", + ShowingDiffForRange: "Showing diff for range", CommitDiff: "Commit diff", CopyCommitHashToClipboard: "Copy commit hash to clipboard", CommitHash: "Commit hash",