From 0cd5257523aa201d5e42cb8afe915fb696b2d92e Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Sat, 29 Apr 2023 20:04:43 +1000 Subject: [PATCH] Retain commit message when cycling history When cycling history, we want to make it so that upon returning to the original prompt, you get your text back. Importantly, we don't want to use the existing preservedMessage field for that because that's only for preserving a NEW commit message, and we don't want the history stuff of the commit reword flow to overwrite that. --- pkg/gui/context/commit_message_context.go | 30 +++++++--- .../controllers/commit_message_controller.go | 4 +- pkg/gui/controllers/helpers/commits_helper.go | 13 ++-- .../helpers/working_tree_helper.go | 2 +- .../controllers/local_commits_controller.go | 2 +- pkg/integration/tests/commit/history.go | 53 +++++++++++++++++ .../tests/commit/history_complex.go | 59 +++++++++++++++++++ pkg/integration/tests/test_list.go | 2 + 8 files changed, 149 insertions(+), 16 deletions(-) create mode 100644 pkg/integration/tests/commit/history.go create mode 100644 pkg/integration/tests/commit/history_complex.go diff --git a/pkg/gui/context/commit_message_context.go b/pkg/gui/context/commit_message_context.go index a660ca23a..6be4763e5 100644 --- a/pkg/gui/context/commit_message_context.go +++ b/pkg/gui/context/commit_message_context.go @@ -26,6 +26,12 @@ type CommitMessageViewModel struct { preservedMessage string // invoked when pressing enter in the commit message panel onConfirm func(string) error + + // The message typed in before cycling through history + // We store this separately to 'preservedMessage' because 'preservedMessage' + // is specifically for committing staged files and we don't want this affected + // by cycling through history in the context of rewording an old commit. + historyMessage string } func NewCommitMessageContext( @@ -61,6 +67,22 @@ func (self *CommitMessageContext) GetPreserveMessage() bool { return self.viewModel.preserveMessage } +func (self *CommitMessageContext) GetPreservedMessage() string { + return self.viewModel.preservedMessage +} + +func (self *CommitMessageContext) SetPreservedMessage(message string) { + self.viewModel.preservedMessage = message +} + +func (self *CommitMessageContext) GetHistoryMessage() string { + return self.viewModel.historyMessage +} + +func (self *CommitMessageContext) SetHistoryMessage(message string) { + self.viewModel.historyMessage = message +} + func (self *CommitMessageContext) OnConfirm(message string) error { return self.viewModel.onConfirm(message) } @@ -71,11 +93,3 @@ func (self *CommitMessageContext) SetPanelState(index int, title string, preserv self.viewModel.onConfirm = onConfirm self.GetView().Title = title } - -func (self *CommitMessageContext) SetPreservedMessage(message string) { - self.viewModel.preservedMessage = message -} - -func (self *CommitMessageContext) GetPreservedMessage() string { - return self.viewModel.preservedMessage -} diff --git a/pkg/gui/controllers/commit_message_controller.go b/pkg/gui/controllers/commit_message_controller.go index 449001300..0772cc16b 100644 --- a/pkg/gui/controllers/commit_message_controller.go +++ b/pkg/gui/controllers/commit_message_controller.go @@ -80,8 +80,10 @@ func (self *CommitMessageController) handleCommitIndexChange(value int) error { newIndex := currentIndex + value if newIndex == context.NoCommitIndex { self.context().SetSelectedIndex(newIndex) - self.helpers.Commits.SetMessageAndDescriptionInView("") + self.helpers.Commits.SetMessageAndDescriptionInView(self.context().GetHistoryMessage()) return nil + } else if currentIndex == context.NoCommitIndex { + self.context().SetHistoryMessage(self.helpers.Commits.JoinCommitMessageAndDescription()) } validCommit, err := self.setCommitMessageAtIndex(newIndex) diff --git a/pkg/gui/controllers/helpers/commits_helper.go b/pkg/gui/controllers/helpers/commits_helper.go index 2b8c4688b..4126d9ee5 100644 --- a/pkg/gui/controllers/helpers/commits_helper.go +++ b/pkg/gui/controllers/helpers/commits_helper.go @@ -65,7 +65,7 @@ func (self *CommitsHelper) SetMessageAndDescriptionInView(message string) { self.renderCommitLength() } -func (self *CommitsHelper) joinCommitMessageAndDescription() string { +func (self *CommitsHelper) JoinCommitMessageAndDescription() string { if len(self.getCommitDescription()) == 0 { return self.getCommitSummary() } @@ -116,7 +116,7 @@ func (self *CommitsHelper) OnCommitSuccess() { } func (self *CommitsHelper) HandleCommitConfirm() error { - fullMessage := self.joinCommitMessageAndDescription() + fullMessage := self.JoinCommitMessageAndDescription() if fullMessage == "" { return self.c.ErrorMsg(self.c.Tr.CommitWithoutMessageErr) @@ -132,16 +132,19 @@ func (self *CommitsHelper) HandleCommitConfirm() error { func (self *CommitsHelper) CloseCommitMessagePanel() error { if self.contexts.CommitMessage.GetPreserveMessage() { - message := self.joinCommitMessageAndDescription() + message := self.JoinCommitMessageAndDescription() self.contexts.CommitMessage.SetPreservedMessage(message) } else { self.SetMessageAndDescriptionInView("") } - return self.EscapeCommitsPanel() + + self.contexts.CommitMessage.SetHistoryMessage("") + + return self.PopCommitMessageContexts() } -func (self *CommitsHelper) EscapeCommitsPanel() error { +func (self *CommitsHelper) PopCommitMessageContexts() error { return self.c.RemoveContexts(self.commitMessageContexts()) } diff --git a/pkg/gui/controllers/helpers/working_tree_helper.go b/pkg/gui/controllers/helpers/working_tree_helper.go index d205a98dc..6fa85bc35 100644 --- a/pkg/gui/controllers/helpers/working_tree_helper.go +++ b/pkg/gui/controllers/helpers/working_tree_helper.go @@ -124,7 +124,7 @@ func (self *WorkingTreeHelper) HandleCommitPressWithMessage(initialMessage strin func (self *WorkingTreeHelper) handleCommit(message string) error { cmdObj := self.git.Commit.CommitCmdObj(message) self.c.LogAction(self.c.Tr.Actions.Commit) - _ = self.commitsHelper.EscapeCommitsPanel() + _ = self.commitsHelper.PopCommitMessageContexts() return self.gpgHelper.WithGpgHandling(cmdObj, self.c.Tr.CommittingStatus, func() error { self.commitsHelper.OnCommitSuccess() return nil diff --git a/pkg/gui/controllers/local_commits_controller.go b/pkg/gui/controllers/local_commits_controller.go index d78e9cf40..3d0e6bc5c 100644 --- a/pkg/gui/controllers/local_commits_controller.go +++ b/pkg/gui/controllers/local_commits_controller.go @@ -231,7 +231,7 @@ func (self *LocalCommitsController) handleReword(message string) error { return self.c.Error(err) } self.helpers.Commits.OnCommitSuccess() - _ = self.helpers.Commits.EscapeCommitsPanel() + _ = self.helpers.Commits.PopCommitMessageContexts() return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC}) } diff --git a/pkg/integration/tests/commit/history.go b/pkg/integration/tests/commit/history.go new file mode 100644 index 000000000..9938ae35a --- /dev/null +++ b/pkg/integration/tests/commit/history.go @@ -0,0 +1,53 @@ +package commit + +import ( + "github.com/jesseduffield/lazygit/pkg/config" + . "github.com/jesseduffield/lazygit/pkg/integration/components" +) + +var History = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "Cycling through commit message history in the commit message panel", + ExtraCmdArgs: "", + Skip: false, + SetupConfig: func(config *config.AppConfig) {}, + SetupRepo: func(shell *Shell) { + shell.EmptyCommit("initial commit") + shell.EmptyCommit("commit 2") + shell.EmptyCommit("commit 3") + + shell.CreateFile("myfile", "myfile content") + }, + Run: func(t *TestDriver, keys config.KeybindingConfig) { + t.Views().Files(). + IsFocused(). + PressPrimaryAction(). // stage file + Press(keys.Files.CommitChanges) + + t.ExpectPopup().CommitMessagePanel(). + InitialText(Equals("")). + Type("my commit message"). + SelectPreviousMessage(). + Content(Equals("commit 3")). + SelectPreviousMessage(). + Content(Equals("commit 2")). + SelectPreviousMessage(). + Content(Equals("initial commit")). + SelectPreviousMessage(). + Content(Equals("initial commit")). // we hit the end + SelectNextMessage(). + Content(Equals("commit 2")). + SelectNextMessage(). + Content(Equals("commit 3")). + SelectNextMessage(). + Content(Equals("my commit message")). + SelectNextMessage(). + Content(Equals("my commit message")). // we hit the beginning + Type(" with extra added"). + Confirm() + + t.Views().Commits(). + TopLines( + Contains("my commit message with extra added").IsSelected(), + ) + }, +}) diff --git a/pkg/integration/tests/commit/history_complex.go b/pkg/integration/tests/commit/history_complex.go new file mode 100644 index 000000000..e88da4416 --- /dev/null +++ b/pkg/integration/tests/commit/history_complex.go @@ -0,0 +1,59 @@ +package commit + +import ( + "github.com/jesseduffield/lazygit/pkg/config" + . "github.com/jesseduffield/lazygit/pkg/integration/components" +) + +var HistoryComplex = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "More complex flow for cycling commit message history", + ExtraCmdArgs: "", + Skip: false, + SetupConfig: func(config *config.AppConfig) {}, + SetupRepo: func(shell *Shell) { + shell.EmptyCommit("initial commit") + shell.EmptyCommit("commit 2") + shell.EmptyCommit("commit 3") + + shell.CreateFileAndAdd("myfile", "myfile content") + }, + Run: func(t *TestDriver, keys config.KeybindingConfig) { + // We're going to start a new commit message, + // then leave and try to reword a commit, then + // come back to original message and confirm we haven't lost our message. + // This shows that we're storing the preserved message for a new commit separately + // to the message when cycling history. + + t.Views().Files(). + IsFocused(). + Press(keys.Files.CommitChanges) + + t.ExpectPopup().CommitMessagePanel(). + InitialText(Equals("")). + Type("my commit message"). + Cancel() + + t.Views().Commits(). + Focus(). + SelectedLine(Contains("commit 3")). + Press(keys.Commits.RenameCommit) + + t.ExpectPopup().CommitMessagePanel(). + InitialText(Equals("commit 3")). + SelectNextMessage(). + Content(Equals("")). + Type("reworded message"). + SelectPreviousMessage(). + Content(Equals("commit 3")). + SelectNextMessage(). + Content(Equals("reworded message")). + Cancel() + + t.Views().Files(). + Focus(). + Press(keys.Files.CommitChanges) + + t.ExpectPopup().CommitMessagePanel(). + InitialText(Equals("my commit message")) + }, +}) diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go index 10838c008..8c1d75c6e 100644 --- a/pkg/integration/tests/test_list.go +++ b/pkg/integration/tests/test_list.go @@ -49,6 +49,8 @@ var tests = []*components.IntegrationTest{ commit.CommitMultiline, commit.CreateTag, commit.DiscardOldFileChange, + commit.History, + commit.HistoryComplex, commit.NewBranch, commit.ResetAuthor, commit.Revert,