diff --git a/pkg/gui/context/commit_message_context.go b/pkg/gui/context/commit_message_context.go index aa70e60b808..53162515665 100644 --- a/pkg/gui/context/commit_message_context.go +++ b/pkg/gui/context/commit_message_context.go @@ -1,6 +1,8 @@ package context import ( + "os" + "path/filepath" "strconv" "strings" @@ -8,8 +10,11 @@ import ( "github.com/jesseduffield/lazygit/pkg/gui/keybindings" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/utils" + "github.com/spf13/afero" ) +const PreservedCommitMessageFileName = "LAZYGIT_PENDING_COMMIT" + type CommitMessageContext struct { c *ContextCommon types.Context @@ -33,8 +38,6 @@ type CommitMessageViewModel struct { // we remember the initial message so that we can tell whether we should preserve // the message; if it's still identical to the initial message, we don't initialMessage string - // the full preserved message (combined summary and description) - preservedMessage string // invoked when pressing enter in the commit message panel onConfirm func(string, string) error // invoked when pressing the switch-to-editor key binding @@ -75,16 +78,51 @@ func (self *CommitMessageContext) GetSelectedIndex() int { return self.viewModel.selectedindex } +func (self *CommitMessageContext) GetPreservedMessagePath() string { + return filepath.Join(self.c.Git().RepoPaths.WorktreeGitDirPath(), PreservedCommitMessageFileName) +} + func (self *CommitMessageContext) GetPreserveMessage() bool { return self.viewModel.preserveMessage } -func (self *CommitMessageContext) GetPreservedMessage() string { - return self.viewModel.preservedMessage +func (self *CommitMessageContext) getPreservedMessage() (string, error) { + buf, err := afero.ReadFile(self.c.Fs, self.GetPreservedMessagePath()) + if os.IsNotExist(err) { + return "", nil + } + if err != nil { + return "", err + } + return string(buf), nil +} + +func (self *CommitMessageContext) GetPreservedMessageAndLogError() string { + msg, err := self.getPreservedMessage() + if err != nil { + self.c.Log.Errorf("error when retrieving persisted commit message: %v", err) + } + return msg } -func (self *CommitMessageContext) SetPreservedMessage(message string) { - self.viewModel.preservedMessage = message +func (self *CommitMessageContext) setPreservedMessage(message string) error { + preservedFilePath := self.GetPreservedMessagePath() + + if len(message) == 0 { + err := self.c.Fs.Remove(preservedFilePath) + if os.IsNotExist(err) { + return nil + } + return err + } + + return afero.WriteFile(self.c.Fs, preservedFilePath, []byte(message), 0o644) +} + +func (self *CommitMessageContext) SetPreservedMessageAndLogError(message string) { + if err := self.setPreservedMessage(message); err != nil { + self.c.Log.Errorf("error when persisting commit message: %v", err) + } } func (self *CommitMessageContext) GetInitialMessage() string { diff --git a/pkg/gui/controllers/helpers/commits_helper.go b/pkg/gui/controllers/helpers/commits_helper.go index e66071b4d06..9c89da706e0 100644 --- a/pkg/gui/controllers/helpers/commits_helper.go +++ b/pkg/gui/controllers/helpers/commits_helper.go @@ -113,7 +113,7 @@ func (self *CommitsHelper) UpdateCommitPanelView(message string) { } if self.c.Contexts().CommitMessage.GetPreserveMessage() { - preservedMessage := self.c.Contexts().CommitMessage.GetPreservedMessage() + preservedMessage := self.c.Contexts().CommitMessage.GetPreservedMessageAndLogError() self.SetMessageAndDescriptionInView(preservedMessage) return } @@ -156,7 +156,7 @@ func (self *CommitsHelper) OpenCommitMessagePanel(opts *OpenCommitMessagePanelOp func (self *CommitsHelper) OnCommitSuccess() { // if we have a preserved message we want to clear it on success if self.c.Contexts().CommitMessage.GetPreserveMessage() { - self.c.Contexts().CommitMessage.SetPreservedMessage("") + self.c.Contexts().CommitMessage.SetPreservedMessageAndLogError("") } } @@ -179,7 +179,7 @@ func (self *CommitsHelper) CloseCommitMessagePanel() { if self.c.Contexts().CommitMessage.GetPreserveMessage() { message := self.JoinCommitMessageAndUnwrappedDescription() if message != self.c.Contexts().CommitMessage.GetInitialMessage() { - self.c.Contexts().CommitMessage.SetPreservedMessage(message) + self.c.Contexts().CommitMessage.SetPreservedMessageAndLogError(message) } } else { self.SetMessageAndDescriptionInView("") diff --git a/pkg/gui/controllers/helpers/working_tree_helper.go b/pkg/gui/controllers/helpers/working_tree_helper.go index f010205f550..6f6e0eaaba2 100644 --- a/pkg/gui/controllers/helpers/working_tree_helper.go +++ b/pkg/gui/controllers/helpers/working_tree_helper.go @@ -149,7 +149,7 @@ func (self *WorkingTreeHelper) HandleWIPCommitPress() error { } func (self *WorkingTreeHelper) HandleCommitPress() error { - message := self.c.Contexts().CommitMessage.GetPreservedMessage() + message := self.c.Contexts().CommitMessage.GetPreservedMessageAndLogError() if message == "" { commitPrefixConfig := self.commitPrefixConfigForRepo() diff --git a/pkg/integration/components/commit_description_panel_driver.go b/pkg/integration/components/commit_description_panel_driver.go index 253dc6f8762..0aa2007570f 100644 --- a/pkg/integration/components/commit_description_panel_driver.go +++ b/pkg/integration/components/commit_description_panel_driver.go @@ -52,6 +52,11 @@ func (self *CommitDescriptionPanelDriver) AddCoAuthor(author string) *CommitDesc return self } +func (self *CommitDescriptionPanelDriver) Clear() *CommitDescriptionPanelDriver { + self.getViewDriver().Clear() + return self +} + func (self *CommitDescriptionPanelDriver) Title(expected *TextMatcher) *CommitDescriptionPanelDriver { self.getViewDriver().Title(expected) diff --git a/pkg/integration/components/commit_message_panel_driver.go b/pkg/integration/components/commit_message_panel_driver.go index 68e1c639b33..047cc59b17d 100644 --- a/pkg/integration/components/commit_message_panel_driver.go +++ b/pkg/integration/components/commit_message_panel_driver.go @@ -39,20 +39,7 @@ func (self *CommitMessagePanelDriver) SwitchToDescription() *CommitDescriptionPa } func (self *CommitMessagePanelDriver) Clear() *CommitMessagePanelDriver { - // clearing multiple times in case there's multiple lines - // (the clear button only clears a single line at a time) - maxAttempts := 100 - for i := 0; i < maxAttempts+1; i++ { - if self.getViewDriver().getView().Buffer() == "" { - break - } - - self.t.press(ClearKey) - if i == maxAttempts { - panic("failed to clear commit message panel") - } - } - + self.getViewDriver().Clear() return self } diff --git a/pkg/integration/components/view_driver.go b/pkg/integration/components/view_driver.go index 189151f61db..44707289c3b 100644 --- a/pkg/integration/components/view_driver.go +++ b/pkg/integration/components/view_driver.go @@ -40,6 +40,24 @@ func (self *ViewDriver) Title(expected *TextMatcher) *ViewDriver { return self } +func (self *ViewDriver) Clear() *ViewDriver { + // clearing multiple times in case there's multiple lines + // (the clear button only clears a single line at a time) + maxAttempts := 100 + for i := 0; i < maxAttempts+1; i++ { + if self.getView().Buffer() == "" { + break + } + + self.t.press(ClearKey) + if i == maxAttempts { + panic("failed to clear view buffer") + } + } + + return self +} + // asserts that the view has lines matching the given matchers. One matcher must be passed for each line. // If you only care about the top n lines, use the TopLines method instead. // If you only care about a subset of lines, use the ContainsLines method instead. diff --git a/pkg/integration/tests/commit/preserve_commit_message.go b/pkg/integration/tests/commit/preserve_commit_message.go index e9297ab76bf..ab136090428 100644 --- a/pkg/integration/tests/commit/preserve_commit_message.go +++ b/pkg/integration/tests/commit/preserve_commit_message.go @@ -28,6 +28,8 @@ var PreserveCommitMessage = NewIntegrationTest(NewIntegrationTestArgs{ Type("second paragraph"). Cancel() + t.FileSystem().PathPresent(".git/LAZYGIT_PENDING_COMMIT") + t.Views().Files(). IsFocused(). Press(keys.Files.CommitChanges) @@ -35,6 +37,22 @@ var PreserveCommitMessage = NewIntegrationTest(NewIntegrationTestArgs{ t.ExpectPopup().CommitMessagePanel(). Content(Equals("my commit message")). SwitchToDescription(). - Content(Equals("first paragraph\n\nsecond paragraph")) + Content(Equals("first paragraph\n\nsecond paragraph")). + Clear(). + SwitchToSummary(). + Clear(). + Cancel() + + t.FileSystem().PathNotPresent(".git/LAZYGIT_PENDING_COMMIT") + + t.Views().Files(). + IsFocused(). + Press(keys.Files.CommitChanges) + + t.ExpectPopup().CommitMessagePanel(). + Type("my new commit message"). + Confirm() + + t.FileSystem().PathNotPresent(".git/LAZYGIT_PENDING_COMMIT") }, })