mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-09-10 07:36:27 -04:00
With the recently added external change detection, it happens more often now that we refresh the commits list because an agent made a commit in the background. In this case, if we keep the selection index the same, it now points at a different commit, making the main view show a different commit too, which is confusing and annoying. To fix this, track the selected commit and range anchor by hash before reloading, then restore those rows if both hashes still exist. This also allows us to get rid of some bespoke code that did this for the specific cases of reverting a commit or cherry-picking commits, because those are now handled by the generic mechanism.
107 lines
3.1 KiB
Go
107 lines
3.1 KiB
Go
package helpers
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
|
"github.com/jesseduffield/lazygit/pkg/gocui"
|
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
|
)
|
|
|
|
type GpgHelper struct {
|
|
c *HelperCommon
|
|
}
|
|
|
|
func NewGpgHelper(c *HelperCommon) *GpgHelper {
|
|
return &GpgHelper{
|
|
c: c,
|
|
}
|
|
}
|
|
|
|
func (self *GpgHelper) WithGpgHandling(
|
|
cmdObj *oscommands.CmdObj,
|
|
configKey git_commands.GpgConfigKey,
|
|
waitingStatus string,
|
|
onSuccess func() error,
|
|
refreshScope []types.RefreshableView,
|
|
) error {
|
|
refreshOptions := types.RefreshOptions{Mode: types.ASYNC, Scope: refreshScope}
|
|
return self.withGpgHandling(
|
|
cmdObj, configKey, waitingStatus, onSuccess, refreshOptions, refreshOptions)
|
|
}
|
|
|
|
// WithGpgHandlingAndSelectHeadCommit is like WithGpgHandling, but on success it
|
|
// selects the new HEAD commit rather than restoring the previous selection. For
|
|
// committing, where the commit we just created is the one we want selected.
|
|
func (self *GpgHelper) WithGpgHandlingAndSelectHeadCommit(
|
|
cmdObj *oscommands.CmdObj,
|
|
configKey git_commands.GpgConfigKey,
|
|
waitingStatus string,
|
|
onSuccess func() error,
|
|
) error {
|
|
failureRefreshOptions := types.RefreshOptions{Mode: types.ASYNC}
|
|
successRefreshOptions := types.RefreshOptions{Mode: types.ASYNC, CommitSelection: types.SelectHeadCommit}
|
|
return self.withGpgHandling(
|
|
cmdObj, configKey, waitingStatus, onSuccess, failureRefreshOptions, successRefreshOptions)
|
|
}
|
|
|
|
// Currently there is a bug where if we switch to a subprocess from within
|
|
// WithWaitingStatus we get stuck there and can't return to lazygit. We could
|
|
// fix this bug, or just stop running subprocesses from within there, given that
|
|
// we don't need to see a loading status if we're in a subprocess.
|
|
func (self *GpgHelper) withGpgHandling(
|
|
cmdObj *oscommands.CmdObj,
|
|
configKey git_commands.GpgConfigKey,
|
|
waitingStatus string,
|
|
onSuccess func() error,
|
|
failureRefreshOptions types.RefreshOptions,
|
|
successRefreshOptions types.RefreshOptions,
|
|
) error {
|
|
useSubprocess := self.c.Git().Config.NeedsGpgSubprocess(configKey)
|
|
if useSubprocess {
|
|
success, err := self.c.RunSubprocess(cmdObj)
|
|
if success && onSuccess != nil {
|
|
if err := onSuccess(); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if success {
|
|
self.c.Refresh(successRefreshOptions)
|
|
} else {
|
|
self.c.Refresh(failureRefreshOptions)
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
return self.runAndStream(
|
|
cmdObj, waitingStatus, onSuccess, failureRefreshOptions, successRefreshOptions)
|
|
}
|
|
|
|
func (self *GpgHelper) runAndStream(
|
|
cmdObj *oscommands.CmdObj,
|
|
waitingStatus string,
|
|
onSuccess func() error,
|
|
failureRefreshOptions types.RefreshOptions,
|
|
successRefreshOptions types.RefreshOptions,
|
|
) error {
|
|
return self.c.WithWaitingStatus(waitingStatus, func(gocui.Task) error {
|
|
if err := cmdObj.StreamOutput().Run(); err != nil {
|
|
self.c.Refresh(failureRefreshOptions)
|
|
return fmt.Errorf(
|
|
self.c.Tr.GitCommandFailed, self.c.UserConfig().Keybinding.Universal.ExtrasMenu,
|
|
)
|
|
}
|
|
|
|
if onSuccess != nil {
|
|
if err := onSuccess(); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
self.c.Refresh(successRefreshOptions)
|
|
return nil
|
|
})
|
|
}
|