From c51e13941cefb96e322bb0b1cde7bfcc3f5ec53a Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Wed, 28 Aug 2024 16:28:18 +0200 Subject: [PATCH 01/15] Cleanup: remove unused translated text --- pkg/i18n/english.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index aa88d397a97..831cfa27e83 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -445,7 +445,6 @@ type TranslationSet struct { ScrollRight string DiscardPatch string DiscardPatchConfirm string - DiscardPatchSameCommitConfirm string CantPatchWhileRebasingError string ToggleAddToPatch string ToggleAddToPatchTooltip string @@ -1435,7 +1434,6 @@ func EnglishTranslationSet() *TranslationSet { ScrollRight: "Scroll right", DiscardPatch: "Discard patch", DiscardPatchConfirm: "You can only build a patch from one commit/stash-entry at a time. Discard current patch?", - DiscardPatchSameCommitConfirm: "You currently have changes added to a patch for this commit. Discard current patch?", CantPatchWhileRebasingError: "You cannot build a patch or run patch commands while in a merging or rebasing state", ToggleAddToPatch: "Toggle file included in patch", ToggleAddToPatchTooltip: "Toggle whether the file is included in the custom patch. See {{.doc}}.", From 770d51634c26a58fb411dad1f69414f24cfe5962 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Sun, 25 Aug 2024 17:37:08 +0200 Subject: [PATCH 02/15] Cleanup: remove diffFilesContext field of SwitchToDiffFilesController I found this indirection confusing when reading the code. It looks like SwitchToDiffFilesController is instantiated with different such contexts, but it's always Contexts.CommitFiles, so just use that directly. --- pkg/gui/controllers.go | 2 +- .../switch_to_diff_files_controller.go | 32 ++++++++----------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/pkg/gui/controllers.go b/pkg/gui/controllers.go index d2f156a90a0..c784b4a1dfa 100644 --- a/pkg/gui/controllers.go +++ b/pkg/gui/controllers.go @@ -259,7 +259,7 @@ func (gui *Gui) resetHelpersAndControllers() { gui.State.Contexts.Stash, } { controllers.AttachControllers(context, controllers.NewSwitchToDiffFilesController( - common, context, gui.State.Contexts.CommitFiles, + common, context, )) } diff --git a/pkg/gui/controllers/switch_to_diff_files_controller.go b/pkg/gui/controllers/switch_to_diff_files_controller.go index 92faefb7973..4b7e9e930bf 100644 --- a/pkg/gui/controllers/switch_to_diff_files_controller.go +++ b/pkg/gui/controllers/switch_to_diff_files_controller.go @@ -1,7 +1,6 @@ package controllers import ( - "github.com/jesseduffield/lazygit/pkg/gui/context" "github.com/jesseduffield/lazygit/pkg/gui/types" ) @@ -20,15 +19,13 @@ type CanSwitchToDiffFiles interface { type SwitchToDiffFilesController struct { baseController *ListControllerTrait[types.Ref] - c *ControllerCommon - context CanSwitchToDiffFiles - diffFilesContext *context.CommitFilesContext + c *ControllerCommon + context CanSwitchToDiffFiles } func NewSwitchToDiffFilesController( c *ControllerCommon, context CanSwitchToDiffFiles, - diffFilesContext *context.CommitFilesContext, ) *SwitchToDiffFilesController { return &SwitchToDiffFilesController{ baseController: baseController{}, @@ -40,9 +37,8 @@ func NewSwitchToDiffFilesController( panic("Not implemented") }, ), - c: c, - context: context, - diffFilesContext: diffFilesContext, + c: c, + context: context, } } @@ -72,16 +68,16 @@ func (self *SwitchToDiffFilesController) enter(ref types.Ref) error { } func (self *SwitchToDiffFilesController) viewFiles(opts SwitchToCommitFilesContextOpts) error { - diffFilesContext := self.diffFilesContext + commitFilesContext := self.c.Contexts().CommitFiles - diffFilesContext.SetSelection(0) - diffFilesContext.SetRef(opts.Ref) - diffFilesContext.SetTitleRef(opts.Ref.Description()) - diffFilesContext.SetCanRebase(opts.CanRebase) - diffFilesContext.SetParentContext(opts.Context) - diffFilesContext.SetWindowName(opts.Context.GetWindowName()) - diffFilesContext.ClearSearchString() - diffFilesContext.GetView().TitlePrefix = opts.Context.GetView().TitlePrefix + commitFilesContext.SetSelection(0) + commitFilesContext.SetRef(opts.Ref) + commitFilesContext.SetTitleRef(opts.Ref.Description()) + commitFilesContext.SetCanRebase(opts.CanRebase) + commitFilesContext.SetParentContext(opts.Context) + commitFilesContext.SetWindowName(opts.Context.GetWindowName()) + commitFilesContext.ClearSearchString() + commitFilesContext.GetView().TitlePrefix = opts.Context.GetView().TitlePrefix if err := self.c.Refresh(types.RefreshOptions{ Scope: []types.RefreshableView{types.COMMIT_FILES}, @@ -89,7 +85,7 @@ func (self *SwitchToDiffFilesController) viewFiles(opts SwitchToCommitFilesConte return err } - return self.c.Context().Push(diffFilesContext) + return self.c.Context().Push(commitFilesContext) } func (self *SwitchToDiffFilesController) itemRepresentsCommit(ref types.Ref) *types.DisabledReason { From 6ad4ffea3b90a7b8f739d43b2df6961e2bc0e507 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Wed, 28 Aug 2024 10:18:34 +0200 Subject: [PATCH 03/15] Cleanup: remove unnecessary viewFiles indirection viewFiles is only called from enter; it doesn't make much sense to fill in a SwitchToCommitFilesContextOpts struct to pass it to viewFiles for this one call. Simply inline viewFiles into enter and get rid of all that. --- .../switch_to_diff_files_controller.go | 20 ++++++------------- pkg/gui/controllers/types.go | 18 ----------------- 2 files changed, 6 insertions(+), 32 deletions(-) delete mode 100644 pkg/gui/controllers/types.go diff --git a/pkg/gui/controllers/switch_to_diff_files_controller.go b/pkg/gui/controllers/switch_to_diff_files_controller.go index 4b7e9e930bf..3a0898f5c06 100644 --- a/pkg/gui/controllers/switch_to_diff_files_controller.go +++ b/pkg/gui/controllers/switch_to_diff_files_controller.go @@ -60,24 +60,16 @@ func (self *SwitchToDiffFilesController) GetOnClick() func() error { } func (self *SwitchToDiffFilesController) enter(ref types.Ref) error { - return self.viewFiles(SwitchToCommitFilesContextOpts{ - Ref: ref, - CanRebase: self.context.CanRebase(), - Context: self.context, - }) -} - -func (self *SwitchToDiffFilesController) viewFiles(opts SwitchToCommitFilesContextOpts) error { commitFilesContext := self.c.Contexts().CommitFiles commitFilesContext.SetSelection(0) - commitFilesContext.SetRef(opts.Ref) - commitFilesContext.SetTitleRef(opts.Ref.Description()) - commitFilesContext.SetCanRebase(opts.CanRebase) - commitFilesContext.SetParentContext(opts.Context) - commitFilesContext.SetWindowName(opts.Context.GetWindowName()) + commitFilesContext.SetRef(ref) + commitFilesContext.SetTitleRef(ref.Description()) + commitFilesContext.SetCanRebase(self.context.CanRebase()) + commitFilesContext.SetParentContext(self.context) + commitFilesContext.SetWindowName(self.context.GetWindowName()) commitFilesContext.ClearSearchString() - commitFilesContext.GetView().TitlePrefix = opts.Context.GetView().TitlePrefix + commitFilesContext.GetView().TitlePrefix = self.context.GetView().TitlePrefix if err := self.c.Refresh(types.RefreshOptions{ Scope: []types.RefreshableView{types.COMMIT_FILES}, diff --git a/pkg/gui/controllers/types.go b/pkg/gui/controllers/types.go deleted file mode 100644 index f719b5de0d4..00000000000 --- a/pkg/gui/controllers/types.go +++ /dev/null @@ -1,18 +0,0 @@ -package controllers - -import ( - "github.com/jesseduffield/lazygit/pkg/gui/types" -) - -// all fields mandatory (except `CanRebase` because it's boolean) -type SwitchToCommitFilesContextOpts struct { - // this is something like a commit or branch - Ref types.Ref - - // from the local commits view we're allowed to do rebase stuff with any patch - // we generate from the diff files context, but we don't have that same ability - // with say the sub commits context or the reflog context. - CanRebase bool - - Context types.Context -} From 8e2ed8c5381a1ae7ddbf155e09d9e5e8cde0090c Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Wed, 28 Aug 2024 16:35:03 +0200 Subject: [PATCH 04/15] Extract helper function currentFromToReverseForPatchBuilding In the next commit it will be reused for checking whether we need to reset the patch; and extracting it makes it easier to extend it for non-sticky diff ranges later in the branch. --- pkg/gui/controllers/commits_files_controller.go | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/pkg/gui/controllers/commits_files_controller.go b/pkg/gui/controllers/commits_files_controller.go index 2a9ba8271ba..8091468a734 100644 --- a/pkg/gui/controllers/commits_files_controller.go +++ b/pkg/gui/controllers/commits_files_controller.go @@ -330,14 +330,21 @@ func (self *CommitFilesController) startPatchBuilder() error { commitFilesContext := self.context() canRebase := commitFilesContext.GetCanRebase() - ref := commitFilesContext.GetRef() - to := ref.RefName() - from, reverse := self.c.Modes().Diffing.GetFromAndReverseArgsForDiff(ref.ParentRefName()) + from, to, reverse := self.currentFromToReverseForPatchBuilding() self.c.Git().Patch.PatchBuilder.Start(from, to, reverse, canRebase) return nil } +func (self *CommitFilesController) currentFromToReverseForPatchBuilding() (string, string, bool) { + commitFilesContext := self.context() + + ref := commitFilesContext.GetRef() + to := ref.RefName() + from, reverse := self.c.Modes().Diffing.GetFromAndReverseArgsForDiff(ref.ParentRefName()) + return from, to, reverse +} + func (self *CommitFilesController) enter(node *filetree.CommitFileNode) error { return self.enterCommitFile(node, types.OnFocusOpts{ClickedWindowName: "", ClickedViewLineIdx: -1}) } From 14a29d6d6ff61ef253a2a7122de8ed25bde91ebf Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Wed, 28 Aug 2024 16:38:55 +0200 Subject: [PATCH 05/15] Bugfix: more comprehensive check whether custom patch must be reset We need to compare more than just the "To" ref. The NewPatchRequired function existed already for this purpose, it just wasn't used. --- pkg/gui/controllers/commits_files_controller.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/gui/controllers/commits_files_controller.go b/pkg/gui/controllers/commits_files_controller.go index 8091468a734..17c92224a56 100644 --- a/pkg/gui/controllers/commits_files_controller.go +++ b/pkg/gui/controllers/commits_files_controller.go @@ -307,7 +307,8 @@ func (self *CommitFilesController) toggleForPatch(selectedNodes []*filetree.Comm }) } - if self.c.Git().Patch.PatchBuilder.Active() && self.c.Git().Patch.PatchBuilder.To != self.context().GetRef().RefName() { + from, to, reverse := self.currentFromToReverseForPatchBuilding() + if self.c.Git().Patch.PatchBuilder.Active() && self.c.Git().Patch.PatchBuilder.NewPatchRequired(from, to, reverse) { return self.c.Confirm(types.ConfirmOpts{ Title: self.c.Tr.DiscardPatch, Prompt: self.c.Tr.DiscardPatchConfirm, @@ -364,7 +365,8 @@ func (self *CommitFilesController) enterCommitFile(node *filetree.CommitFileNode return self.c.Context().Push(self.c.Contexts().CustomPatchBuilder, opts) } - if self.c.Git().Patch.PatchBuilder.Active() && self.c.Git().Patch.PatchBuilder.To != self.context().GetRef().RefName() { + from, to, reverse := self.currentFromToReverseForPatchBuilding() + if self.c.Git().Patch.PatchBuilder.Active() && self.c.Git().Patch.PatchBuilder.NewPatchRequired(from, to, reverse) { return self.c.Confirm(types.ConfirmOpts{ Title: self.c.Tr.DiscardPatch, Prompt: self.c.Tr.DiscardPatchConfirm, From 567e898e22d85a26676cce9cee585f4cd44d39dd Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Fri, 23 Aug 2024 22:14:54 +0200 Subject: [PATCH 06/15] Bugfix: don't allow dropping patches from a custom patch that was made in diffing mode The three nested `if` statements may looks strange, and you might wonder why we don't have single one with &&. The answer is that later in this branch we will add an `else` block to the middle one. --- .../controllers/switch_to_diff_files_controller.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/pkg/gui/controllers/switch_to_diff_files_controller.go b/pkg/gui/controllers/switch_to_diff_files_controller.go index 3a0898f5c06..aa05640b334 100644 --- a/pkg/gui/controllers/switch_to_diff_files_controller.go +++ b/pkg/gui/controllers/switch_to_diff_files_controller.go @@ -62,10 +62,19 @@ func (self *SwitchToDiffFilesController) GetOnClick() func() error { func (self *SwitchToDiffFilesController) enter(ref types.Ref) error { commitFilesContext := self.c.Contexts().CommitFiles + canRebase := self.context.CanRebase() + if canRebase { + if self.c.Modes().Diffing.Active() { + if self.c.Modes().Diffing.Ref != ref.RefName() { + canRebase = false + } + } + } + commitFilesContext.SetSelection(0) commitFilesContext.SetRef(ref) commitFilesContext.SetTitleRef(ref.Description()) - commitFilesContext.SetCanRebase(self.context.CanRebase()) + commitFilesContext.SetCanRebase(canRebase) commitFilesContext.SetParentContext(self.context) commitFilesContext.SetWindowName(self.context.GetWindowName()) commitFilesContext.ClearSearchString() From a2c4fad410dbdaa53b94b60c6c41be3a0211bd84 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Mon, 26 Aug 2024 08:21:17 +0200 Subject: [PATCH 07/15] Bugfix: properly set title of subcommits panel when refreshing This fixes two problems: - Set the title ref to the commit description (like SwitchToDiffFilesController.enter does), rather than just the hash - SetTitleRef only sets the title of the DynamicTitleBuilder, but doesn't set it on the view; this only happens in ContextMgr.Activate, so you'd have to switch to a different side panel and then back to see the new title. --- pkg/gui/controllers/helpers/refresh_helper.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/gui/controllers/helpers/refresh_helper.go b/pkg/gui/controllers/helpers/refresh_helper.go index c43c3ddabb7..c1caf420743 100644 --- a/pkg/gui/controllers/helpers/refresh_helper.go +++ b/pkg/gui/controllers/helpers/refresh_helper.go @@ -286,7 +286,8 @@ func (self *RefreshHelper) refreshCommitsAndCommitFiles() { commit := self.c.Contexts().LocalCommits.GetSelected() if commit != nil && commit.RefName() != "" { self.c.Contexts().CommitFiles.SetRef(commit) - self.c.Contexts().CommitFiles.SetTitleRef(commit.RefName()) + self.c.Contexts().CommitFiles.SetTitleRef(commit.Description()) + self.c.Contexts().CommitFiles.GetView().Title = self.c.Contexts().CommitFiles.Title() _ = self.refreshCommitFilesContext() } } From 079c5a990547061b54d9a485a30b97fc016edcc3 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Tue, 27 Aug 2024 09:52:03 +0200 Subject: [PATCH 08/15] Add prefix to main view diff when in diffing mode Hopefully this will help alleviate the problem that diffing mode is sticky, and you often forget that it's still on. Make it magenta like the mode text in the information view. --- pkg/gui/controllers/helpers/diff_helper.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/pkg/gui/controllers/helpers/diff_helper.go b/pkg/gui/controllers/helpers/diff_helper.go index 94ac291b9e1..a80fb02925a 100644 --- a/pkg/gui/controllers/helpers/diff_helper.go +++ b/pkg/gui/controllers/helpers/diff_helper.go @@ -1,9 +1,12 @@ package helpers import ( + "strings" + "github.com/jesseduffield/lazygit/pkg/commands/git_commands" "github.com/jesseduffield/lazygit/pkg/gui/context" "github.com/jesseduffield/lazygit/pkg/gui/modes/diffing" + "github.com/jesseduffield/lazygit/pkg/gui/style" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/samber/lo" ) @@ -52,8 +55,14 @@ func (self *DiffHelper) ExitDiffMode() error { } func (self *DiffHelper) RenderDiff() error { - cmdObj := self.c.Git().Diff.DiffCmdObj(self.DiffArgs()) + args := self.DiffArgs() + cmdObj := self.c.Git().Diff.DiffCmdObj(args) task := types.NewRunPtyTask(cmdObj.GetCmd()) + task.Prefix = style.FgMagenta.Sprintf( + "%s %s\n\n", + self.c.Tr.ShowingGitDiff, + "git diff "+strings.Join(args, " "), + ) return self.c.RenderToMainViews(types.RefreshMainOpts{ Pair: self.c.MainViewPairs().Normal, From b07ce19b9a3f1eb7b965fe85ac4de5df6ce7779e Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Sun, 25 Aug 2024 14:04:54 +0200 Subject: [PATCH 09/15] Add --stat -p to diff args in diffing mode This is consistent with what we do for showing single commits (with git show), and I find it very useful. --- pkg/gui/controllers/helpers/diff_helper.go | 2 +- pkg/integration/tests/diff/diff.go | 6 +++--- pkg/integration/tests/diff/diff_and_apply_patch.go | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/gui/controllers/helpers/diff_helper.go b/pkg/gui/controllers/helpers/diff_helper.go index a80fb02925a..1aad725fc2a 100644 --- a/pkg/gui/controllers/helpers/diff_helper.go +++ b/pkg/gui/controllers/helpers/diff_helper.go @@ -22,7 +22,7 @@ func NewDiffHelper(c *HelperCommon) *DiffHelper { } func (self *DiffHelper) DiffArgs() []string { - output := []string{self.c.Modes().Diffing.Ref} + output := []string{"--stat", "-p", self.c.Modes().Diffing.Ref} right := self.currentDiffTerminal() if right != "" { diff --git a/pkg/integration/tests/diff/diff.go b/pkg/integration/tests/diff/diff.go index ef1eb40a690..06e32041884 100644 --- a/pkg/integration/tests/diff/diff.go +++ b/pkg/integration/tests/diff/diff.go @@ -35,11 +35,11 @@ var Diff = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Branches(). IsFocused(). Tap(func() { - t.Views().Information().Content(Contains("Showing output for: git diff branch-a branch-a")) + t.Views().Information().Content(Contains("Showing output for: git diff --stat -p branch-a branch-a")) }). SelectNextItem(). Tap(func() { - t.Views().Information().Content(Contains("Showing output for: git diff branch-a branch-b")) + t.Views().Information().Content(Contains("Showing output for: git diff --stat -p branch-a branch-b")) t.Views().Main().Content(Contains("+second line")) }). PressEnter() @@ -67,7 +67,7 @@ var Diff = NewIntegrationTest(NewIntegrationTestArgs{ Press(keys.Universal.DiffingMenu) t.ExpectPopup().Menu().Title(Equals("Diffing")).Select(Contains("Reverse diff direction")).Confirm() - t.Views().Information().Content(Contains("Showing output for: git diff branch-a branch-b -R")) + t.Views().Information().Content(Contains("Showing output for: git diff --stat -p branch-a branch-b -R")) t.Views().Main().Content(Contains("-second line")) }, }) diff --git a/pkg/integration/tests/diff/diff_and_apply_patch.go b/pkg/integration/tests/diff/diff_and_apply_patch.go index c0c95cc1762..6801e7bea47 100644 --- a/pkg/integration/tests/diff/diff_and_apply_patch.go +++ b/pkg/integration/tests/diff/diff_and_apply_patch.go @@ -32,13 +32,13 @@ var DiffAndApplyPatch = NewIntegrationTest(NewIntegrationTestArgs{ t.ExpectPopup().Menu().Title(Equals("Diffing")).Select(Equals("Diff branch-a")).Confirm() - t.Views().Information().Content(Contains("Showing output for: git diff branch-a branch-a")) + t.Views().Information().Content(Contains("Showing output for: git diff --stat -p branch-a branch-a")) t.Views().Branches(). IsFocused(). SelectNextItem(). Tap(func() { - t.Views().Information().Content(Contains("Showing output for: git diff branch-a branch-b")) + t.Views().Information().Content(Contains("Showing output for: git diff --stat -p branch-a branch-b")) t.Views().Main().Content(Contains("+second line")) }). PressEnter() From ac335907ae8c2fc8e3c7c3f78811caecad0d6c1b Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Wed, 28 Aug 2024 15:33:12 +0200 Subject: [PATCH 10/15] Add ShortRefName to Ref interface --- pkg/commands/models/branch.go | 4 ++++ pkg/commands/models/commit.go | 4 ++++ pkg/commands/models/remote_branch.go | 4 ++++ pkg/commands/models/stash_entry.go | 4 ++++ pkg/commands/models/tag.go | 4 ++++ pkg/gui/types/ref.go | 1 + 6 files changed, 21 insertions(+) diff --git a/pkg/commands/models/branch.go b/pkg/commands/models/branch.go index 04f869ebdbd..4dc48a88d8d 100644 --- a/pkg/commands/models/branch.go +++ b/pkg/commands/models/branch.go @@ -53,6 +53,10 @@ func (b *Branch) RefName() string { return b.Name } +func (b *Branch) ShortRefName() string { + return b.RefName() +} + func (b *Branch) ParentRefName() string { return b.RefName() + "^" } diff --git a/pkg/commands/models/commit.go b/pkg/commands/models/commit.go index 95e3b9b18a4..50bcfab8fb0 100644 --- a/pkg/commands/models/commit.go +++ b/pkg/commands/models/commit.go @@ -70,6 +70,10 @@ func (c *Commit) RefName() string { return c.Hash } +func (c *Commit) ShortRefName() string { + return c.Hash[:7] +} + func (c *Commit) ParentRefName() string { if c.IsFirstCommit() { return EmptyTreeCommitHash diff --git a/pkg/commands/models/remote_branch.go b/pkg/commands/models/remote_branch.go index 6a26f05f924..1e89ef582d4 100644 --- a/pkg/commands/models/remote_branch.go +++ b/pkg/commands/models/remote_branch.go @@ -18,6 +18,10 @@ func (r *RemoteBranch) RefName() string { return r.FullName() } +func (r *RemoteBranch) ShortRefName() string { + return r.RefName() +} + func (r *RemoteBranch) ParentRefName() string { return r.RefName() + "^" } diff --git a/pkg/commands/models/stash_entry.go b/pkg/commands/models/stash_entry.go index 2a1cc8435cb..a88ab61f6af 100644 --- a/pkg/commands/models/stash_entry.go +++ b/pkg/commands/models/stash_entry.go @@ -17,6 +17,10 @@ func (s *StashEntry) RefName() string { return fmt.Sprintf("stash@{%d}", s.Index) } +func (s *StashEntry) ShortRefName() string { + return s.RefName() +} + func (s *StashEntry) ParentRefName() string { return s.RefName() + "^" } diff --git a/pkg/commands/models/tag.go b/pkg/commands/models/tag.go index 24cb83254f9..876e2cd77ed 100644 --- a/pkg/commands/models/tag.go +++ b/pkg/commands/models/tag.go @@ -16,6 +16,10 @@ func (t *Tag) RefName() string { return t.Name } +func (t *Tag) ShortRefName() string { + return t.RefName() +} + func (t *Tag) ParentRefName() string { return t.RefName() + "^" } diff --git a/pkg/gui/types/ref.go b/pkg/gui/types/ref.go index e83d91b65f3..4319f12e0e0 100644 --- a/pkg/gui/types/ref.go +++ b/pkg/gui/types/ref.go @@ -3,6 +3,7 @@ package types type Ref interface { FullRefName() string RefName() string + ShortRefName() string ParentRefName() string Description() string } From 442592a1494afc346e9e970dd2496fc28bef36b1 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Wed, 21 Aug 2024 08:31:35 +0200 Subject: [PATCH 11/15] 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 eecb161077e..6d1a72aae3f 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 6adb7a53e98..cd19dcae228 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 1aad725fc2a..42cdb99dd40 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 2d4232f33a6..f0ca624c1a1 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 9ce708272f7..0f3ca990739 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 4319f12e0e0..18fc7e99832 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 831cfa27e83..b09a14d7913 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", From a6656e307c307f85a93ea3d47064029ed261346c Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Wed, 28 Aug 2024 12:53:22 +0200 Subject: [PATCH 12/15] Extract a method CommitFilesContext.ReInit Right now it doesn't do very much yet, but it's still worth it even in this state, I'd say. The function is going to become a bit longer in the next commit, though. --- pkg/gui/context/commit_files_context.go | 6 ++++++ pkg/gui/controllers/helpers/refresh_helper.go | 4 +--- pkg/gui/controllers/switch_to_diff_files_controller.go | 3 +-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/pkg/gui/context/commit_files_context.go b/pkg/gui/context/commit_files_context.go index 97c1728d180..1d936f015c7 100644 --- a/pkg/gui/context/commit_files_context.go +++ b/pkg/gui/context/commit_files_context.go @@ -78,3 +78,9 @@ func (self *CommitFilesContext) GetDiffTerminals() []string { func (self *CommitFilesContext) ModelSearchResults(searchStr string, caseSensitive bool) []gocui.SearchPosition { return nil } + +func (self *CommitFilesContext) ReInit(ref types.Ref) { + self.SetRef(ref) + self.SetTitleRef(ref.Description()) + self.GetView().Title = self.Title() +} diff --git a/pkg/gui/controllers/helpers/refresh_helper.go b/pkg/gui/controllers/helpers/refresh_helper.go index c1caf420743..40a6b03559c 100644 --- a/pkg/gui/controllers/helpers/refresh_helper.go +++ b/pkg/gui/controllers/helpers/refresh_helper.go @@ -285,9 +285,7 @@ func (self *RefreshHelper) refreshCommitsAndCommitFiles() { // For now the awkwardness remains. commit := self.c.Contexts().LocalCommits.GetSelected() if commit != nil && commit.RefName() != "" { - self.c.Contexts().CommitFiles.SetRef(commit) - self.c.Contexts().CommitFiles.SetTitleRef(commit.Description()) - self.c.Contexts().CommitFiles.GetView().Title = self.c.Contexts().CommitFiles.Title() + self.c.Contexts().CommitFiles.ReInit(commit) _ = self.refreshCommitFilesContext() } } diff --git a/pkg/gui/controllers/switch_to_diff_files_controller.go b/pkg/gui/controllers/switch_to_diff_files_controller.go index aa05640b334..1d0cc48f81c 100644 --- a/pkg/gui/controllers/switch_to_diff_files_controller.go +++ b/pkg/gui/controllers/switch_to_diff_files_controller.go @@ -71,9 +71,8 @@ func (self *SwitchToDiffFilesController) enter(ref types.Ref) error { } } + commitFilesContext.ReInit(ref) commitFilesContext.SetSelection(0) - commitFilesContext.SetRef(ref) - commitFilesContext.SetTitleRef(ref.Description()) commitFilesContext.SetCanRebase(canRebase) commitFilesContext.SetParentContext(self.context) commitFilesContext.SetWindowName(self.context.GetWindowName()) From ef7d1a86028fc84e00c669eab9abbd0b17998416 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Fri, 23 Aug 2024 20:55:37 +0200 Subject: [PATCH 13/15] Use non-sticky range diff when entering commit files panel We make the name of the GetSelectedRefRangeForDiffFiles very specific on purpose to make it clear that this is only for switching to diff files, so the implementations can make assumptions about that (unlike GetSelectedRef, which is used for different purposes and needs to stay more generic). --- pkg/gui/context/commit_files_context.go | 19 ++++++++++-- pkg/gui/context/reflog_commits_context.go | 5 +++ pkg/gui/context/stash_context.go | 5 +++ .../controllers/commits_files_controller.go | 15 ++++----- .../helpers/patch_building_helper.go | 5 ++- pkg/gui/controllers/helpers/refresh_helper.go | 8 ++--- .../switch_to_diff_files_controller.go | 31 +++++++++++++++---- .../filetree/commit_file_tree_view_model.go | 18 ++++++++++- 8 files changed, 81 insertions(+), 25 deletions(-) diff --git a/pkg/gui/context/commit_files_context.go b/pkg/gui/context/commit_files_context.go index 1d936f015c7..4e938248129 100644 --- a/pkg/gui/context/commit_files_context.go +++ b/pkg/gui/context/commit_files_context.go @@ -1,6 +1,8 @@ package context import ( + "fmt" + "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/gui/filetree" @@ -75,12 +77,25 @@ func (self *CommitFilesContext) GetDiffTerminals() []string { return []string{self.GetRef().RefName()} } +func (self *CommitFilesContext) GetFromAndToForDiff() (string, string) { + if refs := self.GetRefRange(); refs != nil { + return refs.From.ParentRefName(), refs.To.RefName() + } + ref := self.GetRef() + return ref.ParentRefName(), ref.RefName() +} + func (self *CommitFilesContext) ModelSearchResults(searchStr string, caseSensitive bool) []gocui.SearchPosition { return nil } -func (self *CommitFilesContext) ReInit(ref types.Ref) { +func (self *CommitFilesContext) ReInit(ref types.Ref, refRange *types.RefRange) { self.SetRef(ref) - self.SetTitleRef(ref.Description()) + self.SetRefRange(refRange) + if refRange != nil { + self.SetTitleRef(fmt.Sprintf("%s-%s", refRange.From.ShortRefName(), refRange.To.ShortRefName())) + } else { + self.SetTitleRef(ref.Description()) + } self.GetView().Title = self.Title() } diff --git a/pkg/gui/context/reflog_commits_context.go b/pkg/gui/context/reflog_commits_context.go index 403e5e91c72..db33481e59d 100644 --- a/pkg/gui/context/reflog_commits_context.go +++ b/pkg/gui/context/reflog_commits_context.go @@ -71,6 +71,11 @@ func (self *ReflogCommitsContext) GetSelectedRef() types.Ref { return commit } +func (self *ReflogCommitsContext) GetSelectedRefRangeForDiffFiles() *types.RefRange { + // It doesn't make much sense to show a range diff between two reflog entries. + return nil +} + func (self *ReflogCommitsContext) GetCommits() []*models.Commit { return self.getModel() } diff --git a/pkg/gui/context/stash_context.go b/pkg/gui/context/stash_context.go index c8d48768807..64c7c9fc979 100644 --- a/pkg/gui/context/stash_context.go +++ b/pkg/gui/context/stash_context.go @@ -61,6 +61,11 @@ func (self *StashContext) GetSelectedRef() types.Ref { return stash } +func (self *StashContext) GetSelectedRefRangeForDiffFiles() *types.RefRange { + // It doesn't make much sense to show a range diff between two stash entries. + return nil +} + func (self *StashContext) GetDiffTerminals() []string { itemId := self.GetSelectedItemId() diff --git a/pkg/gui/controllers/commits_files_controller.go b/pkg/gui/controllers/commits_files_controller.go index 17c92224a56..8c4f7cf14b2 100644 --- a/pkg/gui/controllers/commits_files_controller.go +++ b/pkg/gui/controllers/commits_files_controller.go @@ -136,9 +136,8 @@ func (self *CommitFilesController) GetOnRenderToMain() func() error { return nil } - ref := self.context().GetRef() - to := ref.RefName() - from, reverse := self.c.Modes().Diffing.GetFromAndReverseArgsForDiff(ref.ParentRefName()) + from, to := self.context().GetFromAndToForDiff() + from, reverse := self.c.Modes().Diffing.GetFromAndReverseArgsForDiff(from) cmdObj := self.c.Git().WorkingTree.ShowFileDiffCmdObj(from, to, reverse, node.GetPath(), false) task := types.NewRunPtyTask(cmdObj.GetCmd()) @@ -250,9 +249,8 @@ func (self *CommitFilesController) canEditFiles(nodes []*filetree.CommitFileNode } func (self *CommitFilesController) openDiffTool(node *filetree.CommitFileNode) error { - ref := self.context().GetRef() - to := ref.RefName() - from, reverse := self.c.Modes().Diffing.GetFromAndReverseArgsForDiff(ref.ParentRefName()) + from, to := self.context().GetFromAndToForDiff() + from, reverse := self.c.Modes().Diffing.GetFromAndReverseArgsForDiff(from) _, err := self.c.RunSubprocess(self.c.Git().Diff.OpenDiffToolCmdObj( git_commands.DiffToolCmdOptions{ Filepath: node.GetPath(), @@ -340,9 +338,8 @@ func (self *CommitFilesController) startPatchBuilder() error { func (self *CommitFilesController) currentFromToReverseForPatchBuilding() (string, string, bool) { commitFilesContext := self.context() - ref := commitFilesContext.GetRef() - to := ref.RefName() - from, reverse := self.c.Modes().Diffing.GetFromAndReverseArgsForDiff(ref.ParentRefName()) + from, to := commitFilesContext.GetFromAndToForDiff() + from, reverse := self.c.Modes().Diffing.GetFromAndReverseArgsForDiff(from) return from, to, reverse } diff --git a/pkg/gui/controllers/helpers/patch_building_helper.go b/pkg/gui/controllers/helpers/patch_building_helper.go index 4c2fc40d0b2..df6e34216f8 100644 --- a/pkg/gui/controllers/helpers/patch_building_helper.go +++ b/pkg/gui/controllers/helpers/patch_building_helper.go @@ -73,9 +73,8 @@ func (self *PatchBuildingHelper) RefreshPatchBuildingPanel(opts types.OnFocusOpt return nil } - ref := self.c.Contexts().CommitFiles.CommitFileTreeViewModel.GetRef() - to := ref.RefName() - from, reverse := self.c.Modes().Diffing.GetFromAndReverseArgsForDiff(ref.ParentRefName()) + from, to := self.c.Contexts().CommitFiles.GetFromAndToForDiff() + from, reverse := self.c.Modes().Diffing.GetFromAndReverseArgsForDiff(from) diff, err := self.c.Git().WorkingTree.ShowFileDiff(from, to, reverse, path, true) if err != nil { return err diff --git a/pkg/gui/controllers/helpers/refresh_helper.go b/pkg/gui/controllers/helpers/refresh_helper.go index 40a6b03559c..c1f187d07a8 100644 --- a/pkg/gui/controllers/helpers/refresh_helper.go +++ b/pkg/gui/controllers/helpers/refresh_helper.go @@ -285,7 +285,8 @@ func (self *RefreshHelper) refreshCommitsAndCommitFiles() { // For now the awkwardness remains. commit := self.c.Contexts().LocalCommits.GetSelected() if commit != nil && commit.RefName() != "" { - self.c.Contexts().CommitFiles.ReInit(commit) + refRange := self.c.Contexts().LocalCommits.GetSelectedRefRangeForDiffFiles() + self.c.Contexts().CommitFiles.ReInit(commit, refRange) _ = self.refreshCommitFilesContext() } } @@ -386,9 +387,8 @@ func (self *RefreshHelper) RefreshAuthors(commits []*models.Commit) { } func (self *RefreshHelper) refreshCommitFilesContext() error { - ref := self.c.Contexts().CommitFiles.GetRef() - to := ref.RefName() - from, reverse := self.c.Modes().Diffing.GetFromAndReverseArgsForDiff(ref.ParentRefName()) + from, to := self.c.Contexts().CommitFiles.GetFromAndToForDiff() + from, reverse := self.c.Modes().Diffing.GetFromAndReverseArgsForDiff(from) files, err := self.c.Git().Loaders.CommitFileLoader.GetFilesInDiff(from, to, reverse) if err != nil { diff --git a/pkg/gui/controllers/switch_to_diff_files_controller.go b/pkg/gui/controllers/switch_to_diff_files_controller.go index 1d0cc48f81c..b6cfe94d2b0 100644 --- a/pkg/gui/controllers/switch_to_diff_files_controller.go +++ b/pkg/gui/controllers/switch_to_diff_files_controller.go @@ -12,6 +12,7 @@ type CanSwitchToDiffFiles interface { types.IListContext CanRebase() bool GetSelectedRef() types.Ref + GetSelectedRefRangeForDiffFiles() *types.RefRange } // Not using our ListControllerTrait because our 'selected' item is not a list item @@ -46,8 +47,8 @@ func (self *SwitchToDiffFilesController) GetKeybindings(opts types.KeybindingsOp bindings := []*types.Binding{ { Key: opts.GetKey(opts.Config.Universal.GoInto), - Handler: self.withItem(self.enter), - GetDisabledReason: self.require(self.singleItemSelected(self.itemRepresentsCommit)), + Handler: self.enter, + GetDisabledReason: self.canEnter, Description: self.c.Tr.ViewItemFiles, }, } @@ -56,10 +57,18 @@ func (self *SwitchToDiffFilesController) GetKeybindings(opts types.KeybindingsOp } func (self *SwitchToDiffFilesController) GetOnClick() func() error { - return self.withItemGraceful(self.enter) + return func() error { + if self.canEnter() == nil { + return self.enter() + } + + return nil + } } -func (self *SwitchToDiffFilesController) enter(ref types.Ref) error { +func (self *SwitchToDiffFilesController) enter() error { + ref := self.context.GetSelectedRef() + refsRange := self.context.GetSelectedRefRangeForDiffFiles() commitFilesContext := self.c.Contexts().CommitFiles canRebase := self.context.CanRebase() @@ -68,10 +77,12 @@ func (self *SwitchToDiffFilesController) enter(ref types.Ref) error { if self.c.Modes().Diffing.Ref != ref.RefName() { canRebase = false } + } else if refsRange != nil { + canRebase = false } } - commitFilesContext.ReInit(ref) + commitFilesContext.ReInit(ref, refsRange) commitFilesContext.SetSelection(0) commitFilesContext.SetCanRebase(canRebase) commitFilesContext.SetParentContext(self.context) @@ -88,7 +99,15 @@ func (self *SwitchToDiffFilesController) enter(ref types.Ref) error { return self.c.Context().Push(commitFilesContext) } -func (self *SwitchToDiffFilesController) itemRepresentsCommit(ref types.Ref) *types.DisabledReason { +func (self *SwitchToDiffFilesController) canEnter() *types.DisabledReason { + refRange := self.context.GetSelectedRefRangeForDiffFiles() + if refRange != nil { + return nil + } + ref := self.context.GetSelectedRef() + if ref == nil { + return &types.DisabledReason{Text: self.c.Tr.NoItemSelected} + } if ref.RefName() == "" { return &types.DisabledReason{Text: self.c.Tr.SelectedItemDoesNotHaveFiles} } diff --git a/pkg/gui/filetree/commit_file_tree_view_model.go b/pkg/gui/filetree/commit_file_tree_view_model.go index 95cb1a14035..cbbb2fbcf3c 100644 --- a/pkg/gui/filetree/commit_file_tree_view_model.go +++ b/pkg/gui/filetree/commit_file_tree_view_model.go @@ -16,6 +16,8 @@ type ICommitFileTreeViewModel interface { GetRef() types.Ref SetRef(types.Ref) + GetRefRange() *types.RefRange // can be nil, in which case GetRef should be used + SetRefRange(*types.RefRange) // should be set to nil when selection is not a range GetCanRebase() bool SetCanRebase(bool) } @@ -25,9 +27,14 @@ type CommitFileTreeViewModel struct { types.IListCursor ICommitFileTree - // this is e.g. the commit for which we're viewing the files + // this is e.g. the commit for which we're viewing the files, if there is no + // range selection, or if the range selection can't be used for some reason ref types.Ref + // this is a commit range for which we're viewing the files. Can be nil, in + // which case ref is used. + refRange *types.RefRange + // we set this to true when you're viewing the files within the checked-out branch's commits. // If you're viewing the files of some random other branch we can't do any rebase stuff. canRebase bool @@ -42,6 +49,7 @@ func NewCommitFileTreeViewModel(getFiles func() []*models.CommitFile, log *logru ICommitFileTree: fileTree, IListCursor: listCursor, ref: nil, + refRange: nil, canRebase: false, } } @@ -54,6 +62,14 @@ func (self *CommitFileTreeViewModel) SetRef(ref types.Ref) { self.ref = ref } +func (self *CommitFileTreeViewModel) GetRefRange() *types.RefRange { + return self.refRange +} + +func (self *CommitFileTreeViewModel) SetRefRange(refsForRange *types.RefRange) { + self.refRange = refsForRange +} + func (self *CommitFileTreeViewModel) GetCanRebase() bool { return self.canRebase } From 717cb40f055a9c4c77e76f538288aba335459b54 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Wed, 28 Aug 2024 18:44:38 +0200 Subject: [PATCH 14/15] Cleanup: remove now unused ListControllerTrait from SwitchToDiffFilesController --- .../switch_to_diff_files_controller.go | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/pkg/gui/controllers/switch_to_diff_files_controller.go b/pkg/gui/controllers/switch_to_diff_files_controller.go index b6cfe94d2b0..2faa000bb8e 100644 --- a/pkg/gui/controllers/switch_to_diff_files_controller.go +++ b/pkg/gui/controllers/switch_to_diff_files_controller.go @@ -15,11 +15,10 @@ type CanSwitchToDiffFiles interface { GetSelectedRefRangeForDiffFiles() *types.RefRange } -// Not using our ListControllerTrait because our 'selected' item is not a list item -// but an attribute on it i.e. the ref of an item. +// Not using our ListControllerTrait because we have our own way of working with +// range selections that's different from ListControllerTrait's type SwitchToDiffFilesController struct { baseController - *ListControllerTrait[types.Ref] c *ControllerCommon context CanSwitchToDiffFiles } @@ -30,16 +29,8 @@ func NewSwitchToDiffFilesController( ) *SwitchToDiffFilesController { return &SwitchToDiffFilesController{ baseController: baseController{}, - ListControllerTrait: NewListControllerTrait[types.Ref]( - c, - context, - context.GetSelectedRef, - func() ([]types.Ref, int, int) { - panic("Not implemented") - }, - ), - c: c, - context: context, + c: c, + context: context, } } @@ -56,6 +47,10 @@ func (self *SwitchToDiffFilesController) GetKeybindings(opts types.KeybindingsOp return bindings } +func (self *SwitchToDiffFilesController) Context() types.Context { + return self.context +} + func (self *SwitchToDiffFilesController) GetOnClick() func() error { return func() error { if self.canEnter() == nil { From 32fef9aadb94f710d44e3e8ce1adf269c940ac7d Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Wed, 28 Aug 2024 19:47:45 +0200 Subject: [PATCH 15/15] Add a simple integration test for non-sticky range diff --- .../tests/diff/diff_non_sticky_range.go | 45 +++++++++++++++++++ pkg/integration/tests/test_list.go | 1 + 2 files changed, 46 insertions(+) create mode 100644 pkg/integration/tests/diff/diff_non_sticky_range.go diff --git a/pkg/integration/tests/diff/diff_non_sticky_range.go b/pkg/integration/tests/diff/diff_non_sticky_range.go new file mode 100644 index 00000000000..672f744a9c3 --- /dev/null +++ b/pkg/integration/tests/diff/diff_non_sticky_range.go @@ -0,0 +1,45 @@ +package diff + +import ( + "github.com/jesseduffield/lazygit/pkg/config" + . "github.com/jesseduffield/lazygit/pkg/integration/components" +) + +var DiffNonStickyRange = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "View the combined diff of multiple commits using a range selection", + ExtraCmdArgs: []string{}, + Skip: false, + SetupConfig: func(config *config.AppConfig) {}, + SetupRepo: func(shell *Shell) { + shell.EmptyCommit("initial commit") + shell.CreateFileAndAdd("file1", "first line\n") + shell.Commit("first commit") + shell.UpdateFileAndAdd("file1", "first line\nsecond line\n") + shell.Commit("second commit") + shell.UpdateFileAndAdd("file1", "first line\nsecond line\nthird line\n") + shell.Commit("third commit") + }, + Run: func(t *TestDriver, keys config.KeybindingConfig) { + t.Views().Commits(). + Focus(). + Lines( + Contains("third commit").IsSelected(), + Contains("second commit"), + Contains("first commit"), + Contains("initial commit"), + ). + Press(keys.Universal.RangeSelectDown). + Press(keys.Universal.RangeSelectDown). + Tap(func() { + t.Views().Main().Content(Contains("Showing diff for range "). + Contains("+first line\n+second line\n+third line")) + }). + PressEnter() + + t.Views().CommitFiles(). + IsFocused(). + SelectedLine(Contains("file1")) + + t.Views().Main().Content(Contains("+first line\n+second line\n+third line")) + }, +}) diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go index de074232f17..584d7a07d76 100644 --- a/pkg/integration/tests/test_list.go +++ b/pkg/integration/tests/test_list.go @@ -148,6 +148,7 @@ var tests = []*components.IntegrationTest{ diff.Diff, diff.DiffAndApplyPatch, diff.DiffCommits, + diff.DiffNonStickyRange, diff.IgnoreWhitespace, diff.RenameSimilarityThresholdChange, file.CopyMenu,