Simplify error handling (#3502)

- **PR Description**

Simplify and canonicalize error handling across the code base.

Previously it was important to make sure that errors don't bubble up
into gocui, because it would panic there; so we had to show errors in
error panels in the right places (in controller code, usually). This is
error-prone because it's easy to forget (see #3490 for an example);
also, it's not always obvious where in the call chain the error panel
needs to be shown. Most of the time it's in controller code, but we had
plenty of calls to `Error()` in helpers, and I remember that I found
this very confusing when I was new to the code base.

Change this so that you can simply return errors everywhere. The
functions to show an error message manually have been removed for
clarity.

I tried to structure the commits so that you can review them one by one.

Closes #3491.
This commit is contained in:
Stefan Haller 2024-04-18 10:14:51 +02:00 committed by GitHub
commit 34f8f7293c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
76 changed files with 706 additions and 422 deletions

8
go.mod
View file

@ -16,7 +16,7 @@ require (
github.com/integrii/flaggy v1.4.0
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d
github.com/jesseduffield/gocui v0.3.1-0.20240309085756-86e0d5a312de
github.com/jesseduffield/gocui v0.3.1-0.20240418080333-8cd33929c513
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e
@ -47,7 +47,7 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emirpasic/gods v1.12.0 // indirect
github.com/fatih/color v1.9.0 // indirect
github.com/gdamore/encoding v1.0.0 // indirect
github.com/gdamore/encoding v1.0.1 // indirect
github.com/go-git/gcfg v1.5.0 // indirect
github.com/go-git/go-billy/v5 v5.0.0 // indirect
github.com/go-logfmt/logfmt v0.5.0 // indirect
@ -73,8 +73,8 @@ require (
github.com/xanzy/ssh-agent v0.2.1 // indirect
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/term v0.18.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/term v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
)

15
go.sum
View file

@ -87,8 +87,9 @@ github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI
github.com/fsmiamoto/git-todo-parser v0.0.5 h1:Bhzd/vz/6Qm3udfkd6NO9fWfD3TpwR9ucp3N75/J5I8=
github.com/fsmiamoto/git-todo-parser v0.0.5/go.mod h1:B+AgTbNE2BARvJqzXygThzqxLIaEWvwr2sxKYYb0Fas=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
github.com/gdamore/encoding v1.0.1 h1:YzKZckdBL6jVt2Gc+5p82qhrGiqMdG/eNs6Wy0u3Uhw=
github.com/gdamore/encoding v1.0.1/go.mod h1:0Z0cMFinngz9kS1QfMjCP8TY7em3bZYeeklsSDPivEo=
github.com/gdamore/tcell/v2 v2.7.4 h1:sg6/UnTM9jGpZU+oFYAsDahfchWAFW8Xx2yFinNSAYU=
github.com/gdamore/tcell/v2 v2.7.4/go.mod h1:dSXtXTSK0VsW1biw65DZLZ2NKr7j0qP/0J7ONmsraWg=
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
@ -187,8 +188,8 @@ github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68 h1:EQP2Tv8T
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68/go.mod h1:+LLj9/WUPAP8LqCchs7P+7X0R98HiFujVFANdNaxhGk=
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d h1:bO+OmbreIv91rCe8NmscRwhFSqkDJtzWCPV4Y+SQuXE=
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d/go.mod h1:nGNEErzf+NRznT+N2SWqmHnDnF9aLgANB1CUNEan09o=
github.com/jesseduffield/gocui v0.3.1-0.20240309085756-86e0d5a312de h1:2ww1SWgakihE8hFxZ7L3agVeGpA6qwW5vdnhFUXKMQo=
github.com/jesseduffield/gocui v0.3.1-0.20240309085756-86e0d5a312de/go.mod h1:XtEbqCbn45keRXEu+OMZkjN5gw6AEob59afsgHjokZ8=
github.com/jesseduffield/gocui v0.3.1-0.20240418080333-8cd33929c513 h1:Y1bw5iItrsDCumATc/rklIJ/6K+68ieiWZJedhrNuXo=
github.com/jesseduffield/gocui v0.3.1-0.20240418080333-8cd33929c513/go.mod h1:XtEbqCbn45keRXEu+OMZkjN5gw6AEob59afsgHjokZ8=
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 h1:jmpr7KpX2+2GRiE91zTgfq49QvgiqB0nbmlwZ8UnOx0=
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10/go.mod h1:aA97kHeNA+sj2Hbki0pvLslmE4CbDyhBeSSTUUnOuVo=
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 h1:CDuQmfOjAtb1Gms6a1p5L2P8RhbLUq5t8aL7PiQd2uY=
@ -469,14 +470,14 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View file

@ -87,9 +87,10 @@ func (self *BackgroundRoutineMgr) goEvery(interval time.Duration, stop chan stru
if self.pauseBackgroundRefreshes {
continue
}
self.gui.c.OnWorker(func(gocui.Task) {
self.gui.c.OnWorker(func(gocui.Task) error {
_ = function()
done <- struct{}{}
return nil
})
// waiting so that we don't bunch up refreshes if the refresh takes longer than the interval
<-done

View file

@ -1,6 +1,8 @@
package context
import (
"errors"
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
"github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/gui/types"
@ -148,7 +150,7 @@ func (self *MenuContext) GetKeybindings(opts types.KeybindingsOpts) []*types.Bin
func (self *MenuContext) OnMenuPress(selectedItem *types.MenuItem) error {
if selectedItem != nil && selectedItem.DisabledReason != nil {
if selectedItem.DisabledReason.ShowErrorInPanel {
return self.c.ErrorMsg(selectedItem.DisabledReason.Text)
return errors.New(selectedItem.DisabledReason.Text)
}
self.c.ErrorToast(self.c.Tr.DisabledMenuItemPrefix + selectedItem.DisabledReason.Text)

View file

@ -1,6 +1,7 @@
package controllers
import (
"errors"
"fmt"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
@ -172,7 +173,7 @@ func (self *BasicCommitsController) copyCommitAttribute(commit *models.Commit) e
func (self *BasicCommitsController) copyCommitHashToClipboard(commit *models.Commit) error {
self.c.LogAction(self.c.Tr.Actions.CopyCommitHashToClipboard)
if err := self.c.OS().CopyToClipboard(commit.Hash); err != nil {
return self.c.Error(err)
return err
}
self.c.Toast(fmt.Sprintf("'%s' %s", commit.Hash, self.c.Tr.CopiedToClipboard))
@ -182,12 +183,12 @@ func (self *BasicCommitsController) copyCommitHashToClipboard(commit *models.Com
func (self *BasicCommitsController) copyCommitURLToClipboard(commit *models.Commit) error {
url, err := self.c.Helpers().Host.GetCommitURL(commit.Hash)
if err != nil {
return self.c.Error(err)
return err
}
self.c.LogAction(self.c.Tr.Actions.CopyCommitURLToClipboard)
if err := self.c.OS().CopyToClipboard(url); err != nil {
return self.c.Error(err)
return err
}
self.c.Toast(self.c.Tr.CommitURLCopiedToClipboard)
@ -197,12 +198,12 @@ func (self *BasicCommitsController) copyCommitURLToClipboard(commit *models.Comm
func (self *BasicCommitsController) copyCommitDiffToClipboard(commit *models.Commit) error {
diff, err := self.c.Git().Commit.GetCommitDiff(commit.Hash)
if err != nil {
return self.c.Error(err)
return err
}
self.c.LogAction(self.c.Tr.Actions.CopyCommitDiffToClipboard)
if err := self.c.OS().CopyToClipboard(diff); err != nil {
return self.c.Error(err)
return err
}
self.c.Toast(self.c.Tr.CommitDiffCopiedToClipboard)
@ -212,14 +213,14 @@ func (self *BasicCommitsController) copyCommitDiffToClipboard(commit *models.Com
func (self *BasicCommitsController) copyAuthorToClipboard(commit *models.Commit) error {
author, err := self.c.Git().Commit.GetCommitAuthor(commit.Hash)
if err != nil {
return self.c.Error(err)
return err
}
formattedAuthor := fmt.Sprintf("%s <%s>", author.Name, author.Email)
self.c.LogAction(self.c.Tr.Actions.CopyCommitAuthorToClipboard)
if err := self.c.OS().CopyToClipboard(formattedAuthor); err != nil {
return self.c.Error(err)
return err
}
self.c.Toast(self.c.Tr.CommitAuthorCopiedToClipboard)
@ -229,12 +230,12 @@ func (self *BasicCommitsController) copyAuthorToClipboard(commit *models.Commit)
func (self *BasicCommitsController) copyCommitMessageToClipboard(commit *models.Commit) error {
message, err := self.c.Git().Commit.GetCommitMessage(commit.Hash)
if err != nil {
return self.c.Error(err)
return err
}
self.c.LogAction(self.c.Tr.Actions.CopyCommitMessageToClipboard)
if err := self.c.OS().CopyToClipboard(message); err != nil {
return self.c.Error(err)
return err
}
self.c.Toast(self.c.Tr.CommitMessageCopiedToClipboard)
@ -244,12 +245,12 @@ func (self *BasicCommitsController) copyCommitMessageToClipboard(commit *models.
func (self *BasicCommitsController) copyCommitSubjectToClipboard(commit *models.Commit) error {
message, err := self.c.Git().Commit.GetCommitSubject(commit.Hash)
if err != nil {
return self.c.Error(err)
return err
}
self.c.LogAction(self.c.Tr.Actions.CopyCommitSubjectToClipboard)
if err := self.c.OS().CopyToClipboard(message); err != nil {
return self.c.Error(err)
return err
}
self.c.Toast(self.c.Tr.CommitSubjectCopiedToClipboard)
@ -259,12 +260,12 @@ func (self *BasicCommitsController) copyCommitSubjectToClipboard(commit *models.
func (self *BasicCommitsController) openInBrowser(commit *models.Commit) error {
url, err := self.c.Helpers().Host.GetCommitURL(commit.Hash)
if err != nil {
return self.c.Error(err)
return err
}
self.c.LogAction(self.c.Tr.Actions.OpenCommitInBrowser)
if err := self.c.OS().OpenLink(url); err != nil {
return self.c.Error(err)
return err
}
return nil
@ -314,7 +315,7 @@ func (self *BasicCommitsController) handleOldCherryPickKey() error {
"paste": keybindings.Label(self.c.UserConfig.Keybinding.Commits.PasteCommits),
})
return self.c.ErrorMsg(msg)
return errors.New(msg)
}
func (self *BasicCommitsController) openDiffTool(commit *models.Commit) error {

View file

@ -96,7 +96,7 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
OnPress: func() error {
self.c.LogAction(self.c.Tr.Actions.BisectMark)
if err := self.c.Git().Bisect.Mark(hashToMark, info.NewTerm()); err != nil {
return self.c.Error(err)
return err
}
return self.afterMark(selectCurrentAfter, waitToReselect)
@ -109,7 +109,7 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
OnPress: func() error {
self.c.LogAction(self.c.Tr.Actions.BisectMark)
if err := self.c.Git().Bisect.Mark(hashToMark, info.OldTerm()); err != nil {
return self.c.Error(err)
return err
}
return self.afterMark(selectCurrentAfter, waitToReselect)
@ -122,7 +122,7 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
OnPress: func() error {
self.c.LogAction(self.c.Tr.Actions.BisectSkip)
if err := self.c.Git().Bisect.Skip(hashToMark); err != nil {
return self.c.Error(err)
return err
}
return self.afterMark(selectCurrentAfter, waitToReselect)
@ -137,7 +137,7 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
OnPress: func() error {
self.c.LogAction(self.c.Tr.Actions.BisectSkip)
if err := self.c.Git().Bisect.Skip(commit.Hash); err != nil {
return self.c.Error(err)
return err
}
return self.afterMark(selectCurrentAfter, waitToReselect)
@ -169,11 +169,11 @@ func (self *BisectController) openStartBisectMenu(info *git_commands.BisectInfo,
OnPress: func() error {
self.c.LogAction(self.c.Tr.Actions.StartBisect)
if err := self.c.Git().Bisect.Start(); err != nil {
return self.c.Error(err)
return err
}
if err := self.c.Git().Bisect.Mark(commit.Hash, info.NewTerm()); err != nil {
return self.c.Error(err)
return err
}
return self.c.Helpers().Bisect.PostBisectCommandRefresh()
@ -186,11 +186,11 @@ func (self *BisectController) openStartBisectMenu(info *git_commands.BisectInfo,
OnPress: func() error {
self.c.LogAction(self.c.Tr.Actions.StartBisect)
if err := self.c.Git().Bisect.Start(); err != nil {
return self.c.Error(err)
return err
}
if err := self.c.Git().Bisect.Mark(commit.Hash, info.OldTerm()); err != nil {
return self.c.Error(err)
return err
}
return self.c.Helpers().Bisect.PostBisectCommandRefresh()
@ -209,7 +209,7 @@ func (self *BisectController) openStartBisectMenu(info *git_commands.BisectInfo,
HandleConfirm: func(newTerm string) error {
self.c.LogAction(self.c.Tr.Actions.StartBisect)
if err := self.c.Git().Bisect.StartWithTerms(oldTerm, newTerm); err != nil {
return self.c.Error(err)
return err
}
return self.c.Helpers().Bisect.PostBisectCommandRefresh()
@ -232,7 +232,7 @@ func (self *BisectController) showBisectCompleteMessage(candidateHashes []string
formattedCommits, err := self.c.Git().Commit.GetCommitsOneline(candidateHashes)
if err != nil {
return self.c.Error(err)
return err
}
return self.c.Confirm(types.ConfirmOpts{
@ -241,7 +241,7 @@ func (self *BisectController) showBisectCompleteMessage(candidateHashes []string
HandleConfirm: func() error {
self.c.LogAction(self.c.Tr.Actions.ResetBisect)
if err := self.c.Git().Bisect.Reset(); err != nil {
return self.c.Error(err)
return err
}
return self.c.Helpers().Bisect.PostBisectCommandRefresh()
@ -252,11 +252,11 @@ func (self *BisectController) showBisectCompleteMessage(candidateHashes []string
func (self *BisectController) afterMark(selectCurrent bool, waitToReselect bool) error {
done, candidateHashes, err := self.c.Git().Bisect.IsDone()
if err != nil {
return self.c.Error(err)
return err
}
if err := self.afterBisectMarkRefresh(selectCurrent, waitToReselect); err != nil {
return self.c.Error(err)
return err
}
if done {
@ -267,16 +267,17 @@ func (self *BisectController) afterMark(selectCurrent bool, waitToReselect bool)
}
func (self *BisectController) afterBisectMarkRefresh(selectCurrent bool, waitToReselect bool) error {
selectFn := func() {
selectFn := func() error {
if selectCurrent {
self.selectCurrentBisectCommit()
}
return nil
}
if waitToReselect {
return self.c.Refresh(types.RefreshOptions{Mode: types.SYNC, Scope: []types.RefreshableView{}, Then: selectFn})
} else {
selectFn()
_ = selectFn()
return self.c.Helpers().Bisect.PostBisectCommandRefresh()
}

View file

@ -209,7 +209,7 @@ func (self *BranchesController) viewUpstreamOptions(selectedBranch *models.Branc
LabelColumns: []string{self.c.Tr.UnsetUpstream},
OnPress: func() error {
if err := self.c.Git().Branch.UnsetUpstream(selectedBranch.Name); err != nil {
return self.c.Error(err)
return err
}
if err := self.c.Refresh(types.RefreshOptions{
Mode: types.SYNC,
@ -218,7 +218,7 @@ func (self *BranchesController) viewUpstreamOptions(selectedBranch *models.Branc
types.COMMITS,
},
}); err != nil {
return self.c.Error(err)
return err
}
return nil
},
@ -231,11 +231,11 @@ func (self *BranchesController) viewUpstreamOptions(selectedBranch *models.Branc
return self.c.Helpers().Upstream.PromptForUpstreamWithoutInitialContent(selectedBranch, func(upstream string) error {
upstreamRemote, upstreamBranch, err := self.c.Helpers().Upstream.ParseUpstream(upstream)
if err != nil {
return self.c.Error(err)
return err
}
if err := self.c.Git().Branch.SetUpstream(upstreamRemote, upstreamBranch, selectedBranch.Name); err != nil {
return self.c.Error(err)
return err
}
if err := self.c.Refresh(types.RefreshOptions{
Mode: types.SYNC,
@ -244,7 +244,7 @@ func (self *BranchesController) viewUpstreamOptions(selectedBranch *models.Branc
types.COMMITS,
},
}); err != nil {
return self.c.Error(err)
return err
}
return nil
})
@ -279,7 +279,7 @@ func (self *BranchesController) viewUpstreamOptions(selectedBranch *models.Branc
OnPress: func() error {
err := self.c.Helpers().Refs.CreateGitResetMenu(upstream)
if err != nil {
return self.c.Error(err)
return err
}
return nil
},
@ -292,7 +292,7 @@ func (self *BranchesController) viewUpstreamOptions(selectedBranch *models.Branc
OpensMenu: true,
OnPress: func() error {
if err := self.c.Helpers().MergeAndRebase.RebaseOntoRef(selectedBranch.ShortUpstreamRefName()); err != nil {
return self.c.Error(err)
return err
}
return nil
},
@ -334,7 +334,7 @@ func (self *BranchesController) context() *context.BranchesContext {
func (self *BranchesController) press(selectedBranch *models.Branch) error {
if selectedBranch == self.c.Helpers().Refs.GetCheckedOutRef() {
return self.c.ErrorMsg(self.c.Tr.AlreadyCheckedOutBranch)
return errors.New(self.c.Tr.AlreadyCheckedOutBranch)
}
worktreeForRef, ok := self.worktreeForBranch(selectedBranch)
@ -378,7 +378,7 @@ func (self *BranchesController) promptToCheckoutWorktree(worktree *models.Worktr
func (self *BranchesController) handleCreatePullRequest(selectedBranch *models.Branch) error {
if !selectedBranch.IsTrackingRemote() {
return self.c.ErrorMsg(self.c.Tr.PullRequestNoUpstream)
return errors.New(self.c.Tr.PullRequestNoUpstream)
}
return self.createPullRequest(selectedBranch.UpstreamBranch, "")
}
@ -395,16 +395,16 @@ func (self *BranchesController) copyPullRequestURL() error {
branchExistsOnRemote := self.c.Git().Remote.CheckRemoteBranchExists(branch.Name)
if !branchExistsOnRemote {
return self.c.Error(errors.New(self.c.Tr.NoBranchOnRemote))
return errors.New(self.c.Tr.NoBranchOnRemote)
}
url, err := self.c.Helpers().Host.GetPullRequestURL(branch.Name, "")
if err != nil {
return self.c.Error(err)
return err
}
self.c.LogAction(self.c.Tr.Actions.CopyPullRequestURL)
if err := self.c.OS().CopyToClipboard(url); err != nil {
return self.c.Error(err)
return err
}
self.c.Toast(self.c.Tr.PullRequestURLCopiedToClipboard)
@ -423,7 +423,7 @@ func (self *BranchesController) forceCheckout() error {
HandleConfirm: func() error {
self.c.LogAction(self.c.Tr.Actions.ForceCheckoutBranch)
if err := self.c.Git().Branch.Checkout(branch.Name, git_commands.CheckoutOptions{Force: true}); err != nil {
_ = self.c.Error(err)
return err
}
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
},
@ -463,7 +463,7 @@ func (self *BranchesController) createNewBranchWithName(newBranchName string) er
}
if err := self.c.Git().Branch.New(newBranchName, branch.FullRefName()); err != nil {
return self.c.Error(err)
return err
}
self.context().SetSelection(0)
@ -524,7 +524,7 @@ func (self *BranchesController) localDelete(branch *models.Branch) error {
return self.forceDelete(branch)
}
if err != nil {
return self.c.Error(err)
return err
}
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.BRANCHES}})
})
@ -548,7 +548,7 @@ func (self *BranchesController) forceDelete(branch *models.Branch) error {
Prompt: message,
HandleConfirm: func() error {
if err := self.c.Git().Branch.LocalDelete(branch.Name, true); err != nil {
return self.c.ErrorMsg(err.Error())
return err
}
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.BRANCHES}})
},
@ -615,13 +615,13 @@ func (self *BranchesController) notRebasingOntoSelf(branch *models.Branch) *type
func (self *BranchesController) fastForward(branch *models.Branch) error {
if !branch.IsTrackingRemote() {
return self.c.ErrorMsg(self.c.Tr.FwdNoUpstream)
return errors.New(self.c.Tr.FwdNoUpstream)
}
if !branch.RemoteBranchStoredLocally() {
return self.c.ErrorMsg(self.c.Tr.FwdNoLocalUpstream)
return errors.New(self.c.Tr.FwdNoLocalUpstream)
}
if branch.HasCommitsToPush() {
return self.c.ErrorMsg(self.c.Tr.FwdCommitsToPush)
return errors.New(self.c.Tr.FwdCommitsToPush)
}
action := self.c.Tr.Actions.FastForwardBranch
@ -688,7 +688,7 @@ func (self *BranchesController) rename(branch *models.Branch) error {
HandleConfirm: func(newBranchName string) error {
self.c.LogAction(self.c.Tr.Actions.RenameBranch)
if err := self.c.Git().Branch.Rename(branch.Name, helpers.SanitizedBranchName(newBranchName)); err != nil {
return self.c.Error(err)
return err
}
// need to find where the branch is now so that we can re-select it. That means we need to refetch the branches synchronously and then find our branch
@ -766,7 +766,7 @@ func (self *BranchesController) createPullRequestMenu(selectedBranch *models.Bra
LabelColumns: fromToLabelColumns(checkedOutBranch.Name, selectedBranch.Name),
OnPress: func() error {
if !checkedOutBranch.IsTrackingRemote() || !selectedBranch.IsTrackingRemote() {
return self.c.ErrorMsg(self.c.Tr.PullRequestNoUpstream)
return errors.New(self.c.Tr.PullRequestNoUpstream)
}
return self.createPullRequest(checkedOutBranch.UpstreamBranch, selectedBranch.UpstreamBranch)
},
@ -783,13 +783,13 @@ func (self *BranchesController) createPullRequestMenu(selectedBranch *models.Bra
func (self *BranchesController) createPullRequest(from string, to string) error {
url, err := self.c.Helpers().Host.GetPullRequestURL(from, to)
if err != nil {
return self.c.Error(err)
return err
}
self.c.LogAction(self.c.Tr.Actions.OpenPullRequest)
if err := self.c.OS().OpenLink(url); err != nil {
return self.c.Error(err)
return err
}
return nil

View file

@ -1,6 +1,8 @@
package controllers
import (
"errors"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
@ -114,7 +116,7 @@ func (self *CommitMessageController) setCommitMessageAtIndex(index int) (bool, e
if err == git_commands.ErrInvalidCommitIndex {
return false, nil
}
return false, self.c.ErrorMsg(self.c.Tr.CommitWithoutMessageErr)
return false, errors.New(self.c.Tr.CommitWithoutMessageErr)
}
if self.c.UserConfig.Git.Commit.AutoWrapCommitMessage {
commitMessage = helpers.TryRemoveHardLineBreaks(commitMessage, self.c.UserConfig.Git.Commit.AutoWrapWidth)

View file

@ -1,6 +1,7 @@
package controllers
import (
"errors"
"strings"
"github.com/jesseduffield/gocui"
@ -170,7 +171,7 @@ func (self *CommitFilesController) onClickMain(opts gocui.ViewMouseBindingOpts)
func (self *CommitFilesController) checkout(node *filetree.CommitFileNode) error {
self.c.LogAction(self.c.Tr.Actions.CheckoutFile)
if err := self.c.Git().WorkingTree.CheckoutFile(self.context().GetRef().RefName(), node.GetPath()); err != nil {
return self.c.Error(err)
return err
}
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
@ -179,7 +180,7 @@ func (self *CommitFilesController) checkout(node *filetree.CommitFileNode) error
func (self *CommitFilesController) discard(selectedNodes []*filetree.CommitFileNode) error {
parentContext, ok := self.c.CurrentContext().GetParentContext()
if !ok || parentContext.GetKey() != context.LOCAL_COMMITS_CONTEXT_KEY {
return self.c.ErrorMsg(self.c.Tr.CanOnlyDiscardFromLocalCommits)
return errors.New(self.c.Tr.CanOnlyDiscardFromLocalCommits)
}
if ok, err := self.c.Helpers().PatchBuilding.ValidateNormalWorkingTreeState(); !ok {
@ -208,7 +209,7 @@ func (self *CommitFilesController) discard(selectedNodes []*filetree.CommitFileN
return nil
})
if err != nil {
return self.c.Error(err)
return err
}
}
@ -294,7 +295,7 @@ func (self *CommitFilesController) toggleForPatch(selectedNodes []*filetree.Comm
return patchOperationFunction(file.Name)
})
if err != nil {
return self.c.Error(err)
return err
}
}

View file

@ -65,7 +65,7 @@ func (self *ContextLinesController) Context() types.Context {
func (self *ContextLinesController) Increase() error {
if self.isShowingDiff() {
if err := self.checkCanChangeContext(); err != nil {
return self.c.Error(err)
return err
}
self.c.AppState.DiffContextSize++
@ -80,7 +80,7 @@ func (self *ContextLinesController) Decrease() error {
if self.isShowingDiff() && old_size > 1 {
if err := self.checkCanChangeContext(); err != nil {
return self.c.Error(err)
return err
}
self.c.AppState.DiffContextSize = old_size - 1

View file

@ -1,6 +1,7 @@
package controllers
import (
"errors"
"fmt"
"github.com/jesseduffield/gocui"
@ -15,11 +16,11 @@ type CustomPatchOptionsMenuAction struct {
func (self *CustomPatchOptionsMenuAction) Call() error {
if !self.c.Git().Patch.PatchBuilder.Active() {
return self.c.ErrorMsg(self.c.Tr.NoPatchError)
return errors.New(self.c.Tr.NoPatchError)
}
if self.c.Git().Patch.PatchBuilder.IsEmpty() {
return self.c.ErrorMsg(self.c.Tr.EmptyPatchError)
return errors.New(self.c.Tr.EmptyPatchError)
}
menuItems := []*types.MenuItem{
@ -115,7 +116,7 @@ func (self *CustomPatchOptionsMenuAction) getPatchCommitIndex() int {
func (self *CustomPatchOptionsMenuAction) validateNormalWorkingTreeState() (bool, error) {
if self.c.Git().Status.WorkingTreeState() != enums.REBASE_MODE_NONE {
return false, self.c.ErrorMsg(self.c.Tr.CantPatchWhileRebasingError)
return false, errors.New(self.c.Tr.CantPatchWhileRebasingError)
}
return true, nil
}
@ -234,7 +235,7 @@ func (self *CustomPatchOptionsMenuAction) handleApplyPatch(reverse bool) error {
}
self.c.LogAction(action)
if err := self.c.Git().Patch.ApplyCustomPatch(reverse); err != nil {
return self.c.Error(err)
return err
}
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
}
@ -244,7 +245,7 @@ func (self *CustomPatchOptionsMenuAction) copyPatchToClipboard() error {
self.c.LogAction(self.c.Tr.Actions.CopyPatchToClipboard)
if err := self.c.OS().CopyToClipboard(patch); err != nil {
return self.c.Error(err)
return err
}
self.c.Toast(self.c.Tr.PatchCopiedToClipboard)

View file

@ -1,6 +1,7 @@
package controllers
import (
"errors"
"strings"
"github.com/jesseduffield/gocui"
@ -388,7 +389,7 @@ func (self *FilesController) pressWithLock(selectedNodes []*filetree.FileNode) e
// if any files within have inline merge conflicts we can't stage or unstage,
// or it'll end up with those >>>>>> lines actually staged
if node.GetHasInlineMergeConflicts() {
return self.c.ErrorMsg(self.c.Tr.ErrStageDirWithInlineMergeConflicts)
return errors.New(self.c.Tr.ErrStageDirWithInlineMergeConflicts)
}
}
@ -410,7 +411,7 @@ func (self *FilesController) pressWithLock(selectedNodes []*filetree.FileNode) e
}
if err := self.c.Git().WorkingTree.StageFiles(toPaths(selectedNodes)); err != nil {
return self.c.Error(err)
return err
}
} else {
self.c.LogAction(self.c.Tr.Actions.UnstageFile)
@ -428,13 +429,13 @@ func (self *FilesController) pressWithLock(selectedNodes []*filetree.FileNode) e
if len(untrackedNodes) > 0 {
if err := self.c.Git().WorkingTree.UnstageUntrackedFiles(toPaths(untrackedNodes)); err != nil {
return self.c.Error(err)
return err
}
}
if len(trackedNodes) > 0 {
if err := self.c.Git().WorkingTree.UnstageTrackedFiles(toPaths(trackedNodes)); err != nil {
return self.c.Error(err)
return err
}
}
}
@ -496,7 +497,7 @@ func (self *FilesController) EnterFile(opts types.OnFocusOpts) error {
return self.switchToMerge()
}
if file.HasMergeConflicts {
return self.c.ErrorMsg(self.c.Tr.FileStagingRequirements)
return errors.New(self.c.Tr.FileStagingRequirements)
}
return self.c.PushContext(self.c.Contexts().Staging, opts)
@ -523,7 +524,7 @@ func (self *FilesController) toggleStagedAllWithLock() error {
// if any files within have inline merge conflicts we can't stage or unstage,
// or it'll end up with those >>>>>> lines actually staged
if root.GetHasInlineMergeConflicts() {
return self.c.ErrorMsg(self.c.Tr.ErrStageDirWithInlineMergeConflicts)
return errors.New(self.c.Tr.ErrStageDirWithInlineMergeConflicts)
}
if root.GetHasUnstagedChanges() {
@ -534,7 +535,7 @@ func (self *FilesController) toggleStagedAllWithLock() error {
}
if err := self.c.Git().WorkingTree.StageAll(); err != nil {
return self.c.Error(err)
return err
}
} else {
self.c.LogAction(self.c.Tr.Actions.UnstageAllFiles)
@ -544,7 +545,7 @@ func (self *FilesController) toggleStagedAllWithLock() error {
}
if err := self.c.Git().WorkingTree.UnstageAll(); err != nil {
return self.c.Error(err)
return err
}
}
@ -606,14 +607,14 @@ func (self *FilesController) ignoreOrExcludeFile(node *filetree.FileNode, trText
func (self *FilesController) ignore(node *filetree.FileNode) error {
if node.GetPath() == ".gitignore" {
return self.c.ErrorMsg(self.c.Tr.Actions.IgnoreFileErr)
return errors.New(self.c.Tr.Actions.IgnoreFileErr)
}
return self.ignoreOrExcludeFile(node, self.c.Tr.IgnoreTracked, self.c.Tr.IgnoreTrackedPrompt, self.c.Tr.Actions.IgnoreExcludeFile, self.c.Git().WorkingTree.Ignore)
}
func (self *FilesController) exclude(node *filetree.FileNode) error {
if node.GetPath() == ".gitignore" {
return self.c.ErrorMsg(self.c.Tr.Actions.ExcludeGitIgnoreErr)
return errors.New(self.c.Tr.Actions.ExcludeGitIgnoreErr)
}
return self.ignoreOrExcludeFile(node, self.c.Tr.ExcludeTracked, self.c.Tr.ExcludeTrackedPrompt, self.c.Tr.Actions.ExcludeFile, self.c.Git().WorkingTree.Exclude)
@ -627,7 +628,7 @@ func (self *FilesController) ignoreOrExcludeMenu(node *filetree.FileNode) error
LabelColumns: []string{self.c.Tr.IgnoreFile},
OnPress: func() error {
if err := self.ignore(node); err != nil {
return self.c.Error(err)
return err
}
return nil
},
@ -637,7 +638,7 @@ func (self *FilesController) ignoreOrExcludeMenu(node *filetree.FileNode) error
LabelColumns: []string{self.c.Tr.ExcludeFile},
OnPress: func() error {
if err := self.exclude(node); err != nil {
return self.c.Error(err)
return err
}
return nil
},
@ -658,7 +659,7 @@ func (self *FilesController) handleAmendCommitPress() error {
HandleConfirm: func() error {
return self.c.Helpers().WorkingTree.WithEnsureCommitableFiles(func() error {
if len(self.c.Model().Commits) == 0 {
return self.c.ErrorMsg(self.c.Tr.NoCommitToAmend)
return errors.New(self.c.Tr.NoCommitToAmend)
}
return self.c.Helpers().AmendHelper.AmendHead()
@ -765,7 +766,7 @@ func (self *FilesController) createStashMenu() error {
Label: self.c.Tr.StashAllChanges,
OnPress: func() error {
if !self.c.Helpers().WorkingTree.IsWorkingTreeDirty() {
return self.c.ErrorMsg(self.c.Tr.NoFilesToStash)
return errors.New(self.c.Tr.NoFilesToStash)
}
return self.handleStashSave(self.c.Git().Stash.Push, self.c.Tr.Actions.StashAllChanges)
},
@ -775,7 +776,7 @@ func (self *FilesController) createStashMenu() error {
Label: self.c.Tr.StashAllChangesKeepIndex,
OnPress: func() error {
if !self.c.Helpers().WorkingTree.IsWorkingTreeDirty() {
return self.c.ErrorMsg(self.c.Tr.NoFilesToStash)
return errors.New(self.c.Tr.NoFilesToStash)
}
// if there are no staged files it behaves the same as Stash.Save
return self.handleStashSave(self.c.Git().Stash.StashAndKeepIndex, self.c.Tr.Actions.StashAllChangesKeepIndex)
@ -794,7 +795,7 @@ func (self *FilesController) createStashMenu() error {
OnPress: func() error {
// there must be something in staging otherwise the current implementation mucks the stash up
if !self.c.Helpers().WorkingTree.AnyStagedFiles() {
return self.c.ErrorMsg(self.c.Tr.NoTrackedStagedFilesStash)
return errors.New(self.c.Tr.NoTrackedStagedFilesStash)
}
return self.handleStashSave(self.c.Git().Stash.SaveStagedChanges, self.c.Tr.Actions.StashStagedChanges)
},
@ -804,7 +805,7 @@ func (self *FilesController) createStashMenu() error {
Label: self.c.Tr.StashUnstagedChanges,
OnPress: func() error {
if !self.c.Helpers().WorkingTree.IsWorkingTreeDirty() {
return self.c.ErrorMsg(self.c.Tr.NoFilesToStash)
return errors.New(self.c.Tr.NoFilesToStash)
}
if self.c.Helpers().WorkingTree.AnyStagedFiles() {
return self.handleStashSave(self.c.Git().Stash.StashUnstagedChanges, self.c.Tr.Actions.StashUnstagedChanges)
@ -825,7 +826,7 @@ func (self *FilesController) openCopyMenu() error {
Label: self.c.Tr.CopyFileName,
OnPress: func() error {
if err := self.c.OS().CopyToClipboard(node.Name()); err != nil {
return self.c.Error(err)
return err
}
self.c.Toast(self.c.Tr.FileNameCopiedToast)
return nil
@ -837,7 +838,7 @@ func (self *FilesController) openCopyMenu() error {
Label: self.c.Tr.CopyFilePath,
OnPress: func() error {
if err := self.c.OS().CopyToClipboard(node.Path); err != nil {
return self.c.Error(err)
return err
}
self.c.Toast(self.c.Tr.FilePathCopiedToast)
return nil
@ -853,10 +854,10 @@ func (self *FilesController) openCopyMenu() error {
hasStaged := self.hasPathStagedChanges(node)
diff, err := self.c.Git().Diff.GetPathDiff(path, hasStaged)
if err != nil {
return self.c.Error(err)
return err
}
if err := self.c.OS().CopyToClipboard(diff); err != nil {
return self.c.Error(err)
return err
}
self.c.Toast(self.c.Tr.FileDiffCopiedToast)
return nil
@ -878,10 +879,10 @@ func (self *FilesController) openCopyMenu() error {
hasStaged := self.c.Helpers().WorkingTree.AnyStagedFiles()
diff, err := self.c.Git().Diff.GetAllDiff(hasStaged)
if err != nil {
return self.c.Error(err)
return err
}
if err := self.c.OS().CopyToClipboard(diff); err != nil {
return self.c.Error(err)
return err
}
self.c.Toast(self.c.Tr.AllFilesDiffCopiedToast)
return nil
@ -957,7 +958,7 @@ func (self *FilesController) handleStashSave(stashFunc func(message string) erro
self.c.LogAction(action)
if err := stashFunc(stashComment); err != nil {
return self.c.Error(err)
return err
}
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.STASH, types.FILES}})
},
@ -975,7 +976,7 @@ func (self *FilesController) onClickSecondary(opts gocui.ViewMouseBindingOpts) e
func (self *FilesController) fetch() error {
return self.c.WithWaitingStatus(self.c.Tr.FetchingStatus, func(task gocui.Task) error {
if err := self.fetchAux(task); err != nil {
_ = self.c.Error(err)
return err
}
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
})
@ -986,7 +987,7 @@ func (self *FilesController) fetchAux(task gocui.Task) (err error) {
err = self.c.Git().Sync.Fetch(task)
if err != nil && strings.Contains(err.Error(), "exit status 128") {
_ = self.c.ErrorMsg(self.c.Tr.PassUnameWrong)
return errors.New(self.c.Tr.PassUnameWrong)
}
_ = self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.BRANCHES, types.COMMITS, types.REMOTES, types.TAGS}, Mode: types.ASYNC})
@ -1073,7 +1074,7 @@ func (self *FilesController) remove(selectedNodes []*filetree.FileNode) error {
for _, node := range selectedNodes {
if err := self.c.Git().WorkingTree.DiscardAllDirChanges(node); err != nil {
return self.c.Error(err)
return err
}
}
@ -1101,7 +1102,7 @@ func (self *FilesController) remove(selectedNodes []*filetree.FileNode) error {
for _, node := range selectedNodes {
if err := self.c.Git().WorkingTree.DiscardUnstagedDirChanges(node); err != nil {
return self.c.Error(err)
return err
}
}
@ -1127,15 +1128,15 @@ func (self *FilesController) ResetSubmodule(submodule *models.SubmoduleConfig) e
file := self.c.Helpers().WorkingTree.FileForSubmodule(submodule)
if file != nil {
if err := self.c.Git().WorkingTree.UnStageFile(file.Names(), file.Tracked); err != nil {
return self.c.Error(err)
return err
}
}
if err := self.c.Git().Submodule.Stash(submodule); err != nil {
return self.c.Error(err)
return err
}
if err := self.c.Git().Submodule.Reset(submodule); err != nil {
return self.c.Error(err)
return err
}
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.FILES, types.SUBMODULES}})

View file

@ -120,8 +120,9 @@ func (self *FilteringMenuAction) setFiltering() error {
return err
}
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.COMMITS}, Then: func() {
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.COMMITS}, Then: func() error {
self.c.Contexts().LocalCommits.SetSelection(0)
self.c.Contexts().LocalCommits.FocusLine()
return nil
}})
}

View file

@ -1,6 +1,7 @@
package controllers
import (
"errors"
"fmt"
"github.com/jesseduffield/lazygit/pkg/commands/models"
@ -46,7 +47,7 @@ func (self *GitFlowController) GetKeybindings(opts types.KeybindingsOpts) []*typ
func (self *GitFlowController) handleCreateGitFlowMenu(branch *models.Branch) error {
if !self.c.Git().Flow.GitFlowEnabled() {
return self.c.ErrorMsg("You need to install git-flow and enable it in this repo to use git-flow features")
return errors.New("You need to install git-flow and enable it in this repo to use git-flow features")
}
startHandler := func(branchType string) func() error {
@ -103,7 +104,7 @@ func (self *GitFlowController) handleCreateGitFlowMenu(branch *models.Branch) er
func (self *GitFlowController) gitFlowFinishBranch(branchName string) error {
cmdObj, err := self.c.Git().Flow.FinishCmdObj(branchName)
if err != nil {
return self.c.Error(err)
return err
}
self.c.LogAction(self.c.Tr.Actions.GitFlowFinish)

View file

@ -59,26 +59,20 @@ func (self appStatusHelperTask) Continue() {
// withWaitingStatus wraps a function and shows a waiting status while the function is still executing
func (self *AppStatusHelper) WithWaitingStatus(message string, f func(gocui.Task) error) {
self.c.OnWorker(func(task gocui.Task) {
self.statusMgr().WithWaitingStatus(message, self.renderAppStatus, func(waitingStatusHandle *status.WaitingStatusHandle) {
if err := f(appStatusHelperTask{task, waitingStatusHandle}); err != nil {
self.c.OnUIThread(func() error {
return self.c.Error(err)
})
}
self.c.OnWorker(func(task gocui.Task) error {
return self.statusMgr().WithWaitingStatus(message, self.renderAppStatus, func(waitingStatusHandle *status.WaitingStatusHandle) error {
return f(appStatusHelperTask{task, waitingStatusHandle})
})
})
}
func (self *AppStatusHelper) WithWaitingStatusSync(message string, f func() error) {
self.statusMgr().WithWaitingStatus(message, func() {}, func(*status.WaitingStatusHandle) {
func (self *AppStatusHelper) WithWaitingStatusSync(message string, f func() error) error {
return self.statusMgr().WithWaitingStatus(message, func() {}, func(*status.WaitingStatusHandle) error {
stop := make(chan struct{})
defer func() { close(stop) }()
self.renderAppStatusSync(stop)
if err := f(); err != nil {
_ = self.c.Error(err)
}
return f()
})
}
@ -92,7 +86,7 @@ func (self *AppStatusHelper) GetStatusString() string {
}
func (self *AppStatusHelper) renderAppStatus() {
self.c.OnWorker(func(_ gocui.Task) {
self.c.OnWorker(func(_ gocui.Task) error {
ticker := time.NewTicker(time.Millisecond * time.Duration(self.c.UserConfig.Gui.Spinner.Rate))
defer ticker.Stop()
for range ticker.C {
@ -104,9 +98,10 @@ func (self *AppStatusHelper) renderAppStatus() {
})
if appStatus == "" {
return
break
}
}
return nil
})
}

View file

@ -19,7 +19,7 @@ func (self *BisectHelper) Reset() error {
HandleConfirm: func() error {
self.c.LogAction(self.c.Tr.Actions.ResetBisect)
if err := self.c.Git().Bisect.Reset(); err != nil {
return self.c.Error(err)
return err
}
return self.PostBisectCommandRefresh()

View file

@ -37,7 +37,7 @@ func (self *BranchesHelper) ConfirmDeleteRemote(remoteName string, branchName st
return self.c.WithWaitingStatus(self.c.Tr.DeletingStatus, func(task gocui.Task) error {
self.c.LogAction(self.c.Tr.Actions.DeleteRemoteBranch)
if err := self.c.Git().Remote.DeleteRemoteBranch(task, remoteName, branchName); err != nil {
return self.c.Error(err)
return err
}
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.BRANCHES, types.REMOTES}})
})

View file

@ -1,6 +1,7 @@
package helpers
import (
"errors"
"path/filepath"
"strings"
"time"
@ -167,7 +168,7 @@ func (self *CommitsHelper) HandleCommitConfirm() error {
summary, description := self.getCommitSummary(), self.getCommitDescription()
if summary == "" {
return self.c.ErrorMsg(self.c.Tr.CommitWithoutMessageErr)
return errors.New(self.c.Tr.CommitWithoutMessageErr)
}
err := self.c.Contexts().CommitMessage.OnConfirm(summary, description)

View file

@ -36,7 +36,7 @@ func (self *ConfirmationHelper) wrappedConfirmationFunction(cancel goContext.Can
if function != nil {
if err := function(); err != nil {
return self.c.Error(err)
return err
}
}

View file

@ -85,7 +85,7 @@ func (self *FilesHelper) OpenFile(filename string) error {
}
self.c.LogAction(self.c.Tr.Actions.OpenFile)
if err := self.c.OS().OpenFile(absPath); err != nil {
return self.c.Error(err)
return err
}
return nil
}

View file

@ -1,6 +1,8 @@
package helpers
import (
"errors"
"fmt"
"regexp"
"strings"
"sync"
@ -36,19 +38,19 @@ func (self *FixupHelper) HandleFindBaseCommitForFixupPress() error {
return err
}
if diff == "" {
return self.c.ErrorMsg(self.c.Tr.NoChangedFiles)
return errors.New(self.c.Tr.NoChangedFiles)
}
deletedLineInfos, hasHunksWithOnlyAddedLines := self.parseDiff(diff)
if len(deletedLineInfos) == 0 {
return self.c.ErrorMsg(self.c.Tr.NoDeletedLinesInDiff)
return errors.New(self.c.Tr.NoDeletedLinesInDiff)
}
hashes := self.blameDeletedLines(deletedLineInfos)
if len(hashes) == 0 {
// This should never happen
return self.c.ErrorMsg(self.c.Tr.NoBaseCommitsFound)
return errors.New(self.c.Tr.NoBaseCommitsFound)
}
if len(hashes) > 1 {
subjects, err := self.c.Git().Commit.GetHashesAndCommitMessagesFirstLine(hashes)
@ -58,7 +60,7 @@ func (self *FixupHelper) HandleFindBaseCommitForFixupPress() error {
message := lo.Ternary(hasStagedChanges,
self.c.Tr.MultipleBaseCommitsFoundStaged,
self.c.Tr.MultipleBaseCommitsFoundUnstaged)
return self.c.ErrorMsg(message + "\n\n" + subjects)
return fmt.Errorf("%s\n\n%s", message, subjects)
}
commit, index, ok := lo.FindIndexOf(self.c.Model().Commits, func(commit *models.Commit) bool {
@ -70,13 +72,13 @@ func (self *FixupHelper) HandleFindBaseCommitForFixupPress() error {
// If the commit is not found, it's most likely because it's already
// merged, and more than 300 commits away. Check if the last known
// commit is already merged; if so, show the "already merged" error.
return self.c.ErrorMsg(self.c.Tr.BaseCommitIsAlreadyOnMainBranch)
return errors.New(self.c.Tr.BaseCommitIsAlreadyOnMainBranch)
}
// If we get here, the current branch must have more then 300 commits. Unlikely...
return self.c.ErrorMsg(self.c.Tr.BaseCommitIsNotInCurrentView)
return errors.New(self.c.Tr.BaseCommitIsNotInCurrentView)
}
if commit.Status == models.StatusMerged {
return self.c.ErrorMsg(self.c.Tr.BaseCommitIsAlreadyOnMainBranch)
return errors.New(self.c.Tr.BaseCommitIsAlreadyOnMainBranch)
}
doIt := func() error {

View file

@ -45,10 +45,8 @@ func (self *GpgHelper) runAndStream(cmdObj oscommands.ICmdObj, waitingStatus str
return self.c.WithWaitingStatus(waitingStatus, func(gocui.Task) error {
if err := cmdObj.StreamOutput().Run(); err != nil {
_ = self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
return self.c.Error(
fmt.Errorf(
self.c.Tr.GitCommandFailed, self.c.UserConfig.Keybinding.Universal.ExtrasMenu,
),
return fmt.Errorf(
self.c.Tr.GitCommandFailed, self.c.UserConfig.Keybinding.Universal.ExtrasMenu,
)
}

View file

@ -68,17 +68,11 @@ func (self *InlineStatusHelper) WithInlineStatus(opts InlineStatusOpts, f func(g
view := context.GetView()
visible := view.Visible && self.windowHelper.TopViewInWindow(context.GetWindowName(), false) == view
if visible && context.IsItemVisible(opts.Item) {
self.c.OnWorker(func(task gocui.Task) {
self.c.OnWorker(func(task gocui.Task) error {
self.start(opts)
defer self.stop(opts)
err := f(inlineStatusHelperTask{task, self, opts})
if err != nil {
self.c.OnUIThread(func() error {
return self.c.Error(err)
})
}
self.stop(opts)
return f(inlineStatusHelperTask{task, self, opts})
})
} else {
message := presentation.ItemOperationToString(opts.Operation, self.c.Tr)

View file

@ -1,6 +1,7 @@
package helpers
import (
"errors"
"fmt"
"os"
"path/filepath"
@ -78,7 +79,7 @@ func (self *MergeAndRebaseHelper) genericMergeCommand(command string) error {
status := self.c.Git().Status.WorkingTreeState()
if status != enums.REBASE_MODE_MERGING && status != enums.REBASE_MODE_REBASING {
return self.c.ErrorMsg(self.c.Tr.NotMergingOrRebasing)
return errors.New(self.c.Tr.NotMergingOrRebasing)
}
self.c.LogAction(fmt.Sprintf("Merge/Rebase: %s", command))
@ -169,9 +170,9 @@ func (self *MergeAndRebaseHelper) CheckForConflicts(result error) error {
if isMergeConflictErr(result.Error()) {
return self.PromptForConflictHandling()
} else {
return self.c.ErrorMsg(result.Error())
}
return result
}
func (self *MergeAndRebaseHelper) PromptForConflictHandling() error {
@ -298,11 +299,11 @@ func (self *MergeAndRebaseHelper) RebaseOntoRef(ref string) error {
func (self *MergeAndRebaseHelper) MergeRefIntoCheckedOutBranch(refName string) error {
if self.c.Git().Branch.IsHeadDetached() {
return self.c.ErrorMsg("Cannot merge branch in detached head state. You might have checked out a commit directly or a remote branch, in which case you should checkout the local branch you want to be on")
return errors.New("Cannot merge branch in detached head state. You might have checked out a commit directly or a remote branch, in which case you should checkout the local branch you want to be on")
}
checkedOutBranchName := self.refsHelper.GetCheckedOutRef().Name
if checkedOutBranchName == refName {
return self.c.ErrorMsg(self.c.Tr.CantMergeBranchIntoItself)
return errors.New(self.c.Tr.CantMergeBranchIntoItself)
}
prompt := utils.ResolvePlaceholderString(
self.c.Tr.ConfirmMerge,

View file

@ -129,7 +129,7 @@ func (self *MergeConflictsHelper) RefreshMergeState() error {
hasConflicts, err := self.SetConflictsAndRender(self.c.Contexts().MergeConflicts.GetState().GetPath())
if err != nil {
return self.c.Error(err)
return err
}
if !hasConflicts {

View file

@ -171,7 +171,7 @@ func (self *ModeHelper) ClearFiltering() error {
return self.c.Refresh(types.RefreshOptions{
Scope: []types.RefreshableView{types.COMMITS},
Then: func() {
Then: func() error {
// Find the commit that was last selected in filtering mode, and select it again after refreshing
if !self.c.Contexts().LocalCommits.SelectCommitByHash(selectedCommitHash) {
// If we couldn't find it (either because no commit was selected
@ -180,6 +180,7 @@ func (self *ModeHelper) ClearFiltering() error {
// before we entered filtering
self.c.Contexts().LocalCommits.SelectCommitByHash(self.c.Modes().Filtering.GetSelectedCommitHash())
}
return nil
},
})
}

View file

@ -1,6 +1,8 @@
package helpers
import (
"errors"
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
"github.com/jesseduffield/lazygit/pkg/gui/patch_exploring"
"github.com/jesseduffield/lazygit/pkg/gui/types"
@ -24,7 +26,7 @@ func NewPatchBuildingHelper(
func (self *PatchBuildingHelper) ValidateNormalWorkingTreeState() (bool, error) {
if self.c.Git().Status.WorkingTreeState() != enums.REBASE_MODE_NONE {
return false, self.c.ErrorMsg(self.c.Tr.CantPatchWhileRebasingError)
return false, errors.New(self.c.Tr.CantPatchWhileRebasingError)
}
return true, nil
}

View file

@ -76,7 +76,7 @@ func (self *RefreshHelper) Refresh(options types.RefreshOptions) error {
)
}
f := func() {
f := func() error {
var scopeSet *set.Set[types.RefreshableView]
if len(options.Scope) == 0 {
// not refreshing staging/patch-building unless explicitly requested because we only need
@ -104,8 +104,9 @@ func (self *RefreshHelper) Refresh(options types.RefreshOptions) error {
// everything happens fast and it's better to have everything update
// in the one frame
if !self.c.InDemo() && options.Mode == types.ASYNC {
self.c.OnWorker(func(t gocui.Task) {
self.c.OnWorker(func(t gocui.Task) error {
f()
return nil
})
} else {
wg.Add(1)
@ -187,20 +188,22 @@ func (self *RefreshHelper) Refresh(options types.RefreshOptions) error {
wg.Wait()
if options.Then != nil {
options.Then()
if err := options.Then(); err != nil {
return err
}
}
return nil
}
if options.Mode == types.BLOCK_UI {
self.c.OnUIThread(func() error {
f()
return nil
return f()
})
} else {
f()
return nil
}
return nil
return f()
}
func getScopeNames(scopes []types.RefreshableView) []string {
@ -246,10 +249,11 @@ func getModeName(mode types.RefreshMode) string {
func (self *RefreshHelper) refreshReflogCommitsConsideringStartup() {
switch self.c.State().GetRepoState().GetStartupStage() {
case types.INITIAL:
self.c.OnWorker(func(_ gocui.Task) {
self.c.OnWorker(func(_ gocui.Task) error {
_ = self.refreshReflogCommits()
self.refreshBranches(false, true)
self.c.State().GetRepoState().SetStartupStage(types.COMPLETE)
return nil
})
case types.COMPLETE:
@ -381,7 +385,7 @@ func (self *RefreshHelper) refreshCommitFilesContext() error {
files, err := self.c.Git().Loaders.CommitFileLoader.GetFilesInDiff(from, to, reverse)
if err != nil {
return self.c.Error(err)
return err
}
self.c.Model().CommitFiles = files
self.c.Contexts().CommitFiles.CommitFileTreeViewModel.SetTree()
@ -406,7 +410,7 @@ func (self *RefreshHelper) refreshRebaseCommits() error {
func (self *RefreshHelper) refreshTags() error {
tags, err := self.c.Git().Loaders.TagLoader.GetTags()
if err != nil {
return self.c.Error(err)
return err
}
self.c.Model().Tags = tags
@ -448,7 +452,7 @@ func (self *RefreshHelper) refreshBranches(refreshWorktrees bool, keepBranchSele
branches, err := self.c.Git().Loaders.BranchLoader.Load(reflogCommits)
if err != nil {
_ = self.c.Error(err)
self.c.Log.Error(err)
}
self.c.Model().Branches = branches
@ -543,7 +547,7 @@ func (self *RefreshHelper) refreshStateFiles() error {
if len(pathsToStage) > 0 {
self.c.LogAction(self.c.Tr.Actions.StageResolvedFiles)
if err := self.c.Git().WorkingTree.StageFiles(pathsToStage); err != nil {
return self.c.Error(err)
return err
}
}
@ -603,7 +607,7 @@ func (self *RefreshHelper) refreshReflogCommits() error {
commits, onlyObtainedNewReflogCommits, err := self.c.Git().Loaders.ReflogCommitLoader.
GetReflogCommits(lastReflogCommit, filterPath, filterAuthor)
if err != nil {
return self.c.Error(err)
return err
}
if onlyObtainedNewReflogCommits {
@ -634,7 +638,7 @@ func (self *RefreshHelper) refreshRemotes() error {
remotes, err := self.c.Git().Loaders.RemoteLoader.GetRemotes()
if err != nil {
return self.c.Error(err)
return err
}
self.c.Model().Remotes = remotes

View file

@ -69,10 +69,10 @@ func (self *RefsHelper) CheckoutRef(ref string, options types.CheckoutRefOptions
Prompt: self.c.Tr.AutoStashPrompt,
HandleConfirm: func() error {
if err := self.c.Git().Stash.Push(self.c.Tr.StashPrefix + ref); err != nil {
return self.c.Error(err)
return err
}
if err := self.c.Git().Branch.Checkout(ref, cmdOptions); err != nil {
return self.c.Error(err)
return err
}
onSuccess()
@ -80,16 +80,14 @@ func (self *RefsHelper) CheckoutRef(ref string, options types.CheckoutRefOptions
if err := self.c.Refresh(refreshOptions); err != nil {
return err
}
return self.c.Error(err)
return err
}
return self.c.Refresh(refreshOptions)
},
})
}
if err := self.c.Error(err); err != nil {
return err
}
return err
}
onSuccess()
@ -142,7 +140,7 @@ func (self *RefsHelper) CheckoutRemoteBranch(fullBranchName string, localBranchN
// "git checkout -b", but we want to benefit from all the
// nice features of the CheckoutRef function.
if err := self.c.Git().Branch.CreateWithUpstream(localBranchName, fullBranchName); err != nil {
return self.c.Error(err)
return err
}
// Do a sync refresh to make sure the new branch is visible,
// so that we see an inline status when checking it out
@ -176,7 +174,7 @@ func (self *RefsHelper) GetCheckedOutRef() *models.Branch {
func (self *RefsHelper) ResetToRef(ref string, strength string, envVars []string) error {
if err := self.c.Git().Commit.ResetToCommit(ref, strength, envVars); err != nil {
return self.c.Error(err)
return err
}
self.c.Contexts().LocalCommits.SetSelection(0)

View file

@ -1,6 +1,7 @@
package helpers
import (
"errors"
"fmt"
"os"
"path/filepath"
@ -156,7 +157,7 @@ func (self *ReposHelper) DispatchSwitchTo(path string, errMsg string, contextKey
if err := os.Chdir(path); err != nil {
if os.IsNotExist(err) {
return self.c.ErrorMsg(errMsg)
return errors.New(errMsg)
}
return err
}

View file

@ -1,6 +1,7 @@
package helpers
import (
"errors"
"fmt"
"strings"
@ -39,7 +40,7 @@ func (self *SnakeHelper) renderSnakeGame(cells [][]snake.CellType, alive bool) {
view := self.c.Views().Snake
if !alive {
_ = self.c.ErrorMsg(self.c.Tr.YouDied)
self.c.OnUIThread(func() error { return errors.New(self.c.Tr.YouDied) })
return
}

View file

@ -25,12 +25,12 @@ func (self *TagsHelper) OpenCreateTagPrompt(ref string, onCreate func()) error {
if description != "" {
self.c.LogAction(self.c.Tr.Actions.CreateAnnotatedTag)
if err := self.c.Git().Tag.CreateAnnotated(tagName, ref, description, force); err != nil {
return self.c.Error(err)
return err
}
} else {
self.c.LogAction(self.c.Tr.Actions.CreateLightweightTag)
if err := self.c.Git().Tag.CreateLightweight(tagName, ref, force); err != nil {
return self.c.Error(err)
return err
}
}

View file

@ -1,6 +1,8 @@
package helpers
import (
"errors"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/updates"
@ -41,10 +43,10 @@ func (self *UpdateHelper) CheckForUpdateInForeground() error {
return self.c.WithWaitingStatus(self.c.Tr.CheckingForUpdates, func(gocui.Task) error {
self.updater.CheckForNewUpdate(func(newVersion string, err error) error {
if err != nil {
return self.c.Error(err)
return err
}
if newVersion == "" {
return self.c.ErrorMsg(self.c.Tr.FailedToRetrieveLatestVersionErr)
return errors.New(self.c.Tr.FailedToRetrieveLatestVersionErr)
}
return self.showUpdatePrompt(newVersion)
}, true)
@ -71,7 +73,7 @@ func (self *UpdateHelper) onUpdateFinish(err error) error {
"errMessage": err.Error(),
},
)
return self.c.ErrorMsg(errMessage)
return errors.New(errMessage)
}
return self.c.Alert(self.c.Tr.UpdateCompletedTitle, self.c.Tr.UpdateCompleted)
})

View file

@ -1,6 +1,7 @@
package helpers
import (
"errors"
"fmt"
"regexp"
@ -137,7 +138,7 @@ func (self *WorkingTreeHelper) HandleCommitEditorPress() error {
func (self *WorkingTreeHelper) HandleWIPCommitPress() error {
skipHookPrefix := self.c.UserConfig.Git.SkipHookPrefix
if skipHookPrefix == "" {
return self.c.ErrorMsg(self.c.Tr.SkipHookPrefixNotConfigured)
return errors.New(self.c.Tr.SkipHookPrefixNotConfigured)
}
return self.HandleCommitPressWithMessage(skipHookPrefix)
@ -153,7 +154,7 @@ func (self *WorkingTreeHelper) HandleCommitPress() error {
prefixReplace := commitPrefixConfig.Replace
rgx, err := regexp.Compile(prefixPattern)
if err != nil {
return self.c.ErrorMsg(fmt.Sprintf("%s: %s", self.c.Tr.CommitPrefixPatternError, err.Error()))
return fmt.Errorf("%s: %s", self.c.Tr.CommitPrefixPatternError, err.Error())
}
prefix := rgx.ReplaceAllString(self.refHelper.GetCheckedOutRef().Name, prefixReplace)
message = prefix
@ -165,11 +166,11 @@ func (self *WorkingTreeHelper) HandleCommitPress() error {
func (self *WorkingTreeHelper) WithEnsureCommitableFiles(handler func() error) error {
if err := self.prepareFilesForCommit(); err != nil {
return self.c.Error(err)
return err
}
if len(self.c.Model().Files) == 0 {
return self.c.ErrorMsg(self.c.Tr.NoFilesStagedTitle)
return errors.New(self.c.Tr.NoFilesStagedTitle)
}
if !self.AnyStagedFiles() {
@ -186,10 +187,10 @@ func (self *WorkingTreeHelper) promptToStageAllAndRetry(retry func() error) erro
HandleConfirm: func() error {
self.c.LogAction(self.c.Tr.Actions.StageAllFiles)
if err := self.c.Git().WorkingTree.StageAll(); err != nil {
return self.c.Error(err)
return err
}
if err := self.syncRefresh(); err != nil {
return self.c.Error(err)
return err
}
return retry()

View file

@ -1,6 +1,7 @@
package helpers
import (
"errors"
"strings"
"github.com/jesseduffield/gocui"
@ -139,7 +140,7 @@ func (self *WorktreeHelper) NewWorktreeCheckout(base string, canCheckoutBase boo
Title: self.c.Tr.NewBranchName,
HandleConfirm: func(branchName string) error {
if branchName == "" {
return self.c.ErrorMsg(self.c.Tr.BranchNameCannotBeBlank)
return errors.New(self.c.Tr.BranchNameCannotBeBlank)
}
opts.Branch = branchName
@ -154,7 +155,7 @@ func (self *WorktreeHelper) NewWorktreeCheckout(base string, canCheckoutBase boo
func (self *WorktreeHelper) Switch(worktree *models.Worktree, contextKey types.ContextKey) error {
if worktree.IsCurrent {
return self.c.ErrorMsg(self.c.Tr.AlreadyInWorktree)
return errors.New(self.c.Tr.AlreadyInWorktree)
}
self.c.LogAction(self.c.Tr.SwitchToWorktree)
@ -186,13 +187,13 @@ func (self *WorktreeHelper) Remove(worktree *models.Worktree, force bool) error
if err := self.c.Git().Worktree.Delete(worktree.Path, force); err != nil {
errMessage := err.Error()
if !strings.Contains(errMessage, "--force") {
return self.c.Error(err)
return err
}
if !force {
return self.Remove(worktree, true)
}
return self.c.ErrorMsg(errMessage)
return err
}
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.WORKTREES, types.BRANCHES, types.FILES}})
})
@ -206,7 +207,7 @@ func (self *WorktreeHelper) Detach(worktree *models.Worktree) error {
err := self.c.Git().Worktree.Detach(worktree.Path)
if err != nil {
return self.c.Error(err)
return err
}
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.WORKTREES, types.BRANCHES, types.FILES}})
})

View file

@ -1,6 +1,10 @@
package controllers
import "github.com/jesseduffield/lazygit/pkg/gui/types"
import (
"errors"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
// Embed this into your list controller to get some convenience methods for
// ensuring a single item is selected, etc.
@ -106,7 +110,7 @@ func (self *ListControllerTrait[T]) withItem(callback func(T) error) func() erro
var zeroValue T
commit := self.getSelectedItem()
if commit == zeroValue {
return self.c.ErrorMsg(self.c.Tr.NoItemSelected)
return errors.New(self.c.Tr.NoItemSelected)
}
return callback(commit)
@ -117,7 +121,7 @@ func (self *ListControllerTrait[T]) withItems(callback func([]T) error) func() e
return func() error {
items, _, _ := self.getSelectedItems()
if len(items) == 0 {
return self.c.ErrorMsg(self.c.Tr.NoItemSelected)
return errors.New(self.c.Tr.NoItemSelected)
}
return callback(items)
@ -129,7 +133,7 @@ func (self *ListControllerTrait[T]) withItemsRange(callback func([]T, int, int)
return func() error {
items, startIdx, endIdx := self.getSelectedItems()
if len(items) == 0 {
return self.c.ErrorMsg(self.c.Tr.NoItemSelected)
return errors.New(self.c.Tr.NoItemSelected)
}
return callback(items, startIdx, endIdx)

View file

@ -352,7 +352,7 @@ func (self *LocalCommitsController) fixup(selectedCommits []*models.Commit, star
func (self *LocalCommitsController) reword(commit *models.Commit) error {
commitMessage, err := self.c.Git().Commit.GetCommitMessage(commit.Hash)
if err != nil {
return self.c.Error(err)
return err
}
if self.c.UserConfig.Git.Commit.AutoWrapCommitMessage {
commitMessage = helpers.TryRemoveHardLineBreaks(commitMessage, self.c.UserConfig.Git.Commit.AutoWrapWidth)
@ -399,7 +399,7 @@ func (self *LocalCommitsController) switchFromCommitMessagePanelToEditor(filepat
func (self *LocalCommitsController) handleReword(summary string, description string) error {
err := self.c.Git().Rebase.RewordCommit(self.c.Model().Commits, self.c.Contexts().LocalCommits.GetSelectedLineIdx(), summary, description)
if err != nil {
return self.c.Error(err)
return err
}
self.c.Helpers().Commits.OnCommitSuccess()
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
@ -416,7 +416,7 @@ func (self *LocalCommitsController) doRewordEditor() error {
self.c.Model().Commits, self.context().GetSelectedLineIdx(),
)
if err != nil {
return self.c.Error(err)
return err
}
if subProcess != nil {
return self.c.RunSubprocessAndRefresh(subProcess)
@ -495,7 +495,7 @@ func (self *LocalCommitsController) edit(selectedCommits []*models.Commit) error
func (self *LocalCommitsController) quickStartInteractiveRebase() error {
commitToEdit, err := self.findCommitForQuickStartInteractiveRebase()
if err != nil {
return self.c.Error(err)
return err
}
return self.startInteractiveRebaseWithEdit([]*models.Commit{commitToEdit})
@ -513,7 +513,7 @@ func (self *LocalCommitsController) startInteractiveRebaseWithEdit(
err := self.c.Git().Rebase.EditRebase(commitsToEdit[len(commitsToEdit)-1].Hash)
return self.c.Helpers().MergeAndRebase.CheckMergeOrRebaseWithRefreshOptions(
err,
types.RefreshOptions{Mode: types.BLOCK_UI, Then: func() {
types.RefreshOptions{Mode: types.BLOCK_UI, Then: func() error {
todos := make([]*models.Commit, 0, len(commitsToEdit)-1)
for _, c := range commitsToEdit[:len(commitsToEdit)-1] {
// Merge commits can't be set to "edit", so just skip them
@ -524,7 +524,7 @@ func (self *LocalCommitsController) startInteractiveRebaseWithEdit(
if len(todos) > 0 {
err := self.updateTodos(todo.Edit, todos)
if err != nil {
_ = self.c.Error(err)
return err
}
}
@ -540,6 +540,7 @@ func (self *LocalCommitsController) startInteractiveRebaseWithEdit(
if ok1 && ok2 {
self.context().SetSelectionRangeAndMode(newSelectedIdx, newRangeStartIdx, rangeSelectMode)
}
return nil
}})
})
}
@ -587,7 +588,7 @@ func (self *LocalCommitsController) interactiveRebase(action todo.TodoCommand, s
// begin a rebase. It then updates the todo file with that action
func (self *LocalCommitsController) updateTodos(action todo.TodoCommand, selectedCommits []*models.Commit) error {
if err := self.c.Git().Rebase.EditRebaseTodo(selectedCommits, action); err != nil {
return self.c.Error(err)
return err
}
return self.c.Refresh(types.RefreshOptions{
@ -620,7 +621,7 @@ func (self *LocalCommitsController) isRebasing() bool {
func (self *LocalCommitsController) moveDown(selectedCommits []*models.Commit, startIdx int, endIdx int) error {
if self.isRebasing() {
if err := self.c.Git().Rebase.MoveTodosDown(selectedCommits); err != nil {
return self.c.Error(err)
return err
}
self.context().MoveSelection(1)
@ -643,7 +644,7 @@ func (self *LocalCommitsController) moveDown(selectedCommits []*models.Commit, s
func (self *LocalCommitsController) moveUp(selectedCommits []*models.Commit, startIdx int, endIdx int) error {
if self.isRebasing() {
if err := self.c.Git().Rebase.MoveTodosUp(selectedCommits); err != nil {
return self.c.Error(err)
return err
}
self.context().MoveSelection(-1)
@ -733,7 +734,7 @@ func (self *LocalCommitsController) resetAuthor() error {
return self.c.WithWaitingStatus(self.c.Tr.AmendingStatus, func(gocui.Task) error {
self.c.LogAction(self.c.Tr.Actions.ResetCommitAuthor)
if err := self.c.Git().Rebase.ResetCommitAuthor(self.c.Model().Commits, self.context().GetSelectedLineIdx()); err != nil {
return self.c.Error(err)
return err
}
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
@ -748,7 +749,7 @@ func (self *LocalCommitsController) setAuthor() error {
return self.c.WithWaitingStatus(self.c.Tr.AmendingStatus, func(gocui.Task) error {
self.c.LogAction(self.c.Tr.Actions.SetCommitAuthor)
if err := self.c.Git().Rebase.SetCommitAuthor(self.c.Model().Commits, self.context().GetSelectedLineIdx(), value); err != nil {
return self.c.Error(err)
return err
}
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
@ -765,7 +766,7 @@ func (self *LocalCommitsController) addCoAuthor() error {
return self.c.WithWaitingStatus(self.c.Tr.AmendingStatus, func(gocui.Task) error {
self.c.LogAction(self.c.Tr.Actions.AddCommitCoAuthor)
if err := self.c.Git().Rebase.AddCommitCoAuthor(self.c.Model().Commits, self.context().GetSelectedLineIdx(), value); err != nil {
return self.c.Error(err)
return err
}
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
})
@ -803,7 +804,7 @@ func (self *LocalCommitsController) createRevertMergeCommitMenu(commit *models.C
i := i
message, err := self.c.Git().Commit.GetCommitMessageFirstLine(parentHash)
if err != nil {
return self.c.Error(err)
return err
}
menuItems[i] = &types.MenuItem{
@ -851,7 +852,7 @@ func (self *LocalCommitsController) createFixupCommit(commit *models.Commit) err
self.c.LogAction(self.c.Tr.Actions.CreateFixupCommit)
return self.c.WithWaitingStatusSync(self.c.Tr.CreatingFixupCommitStatus, func() error {
if err := self.c.Git().Commit.CreateFixupCommit(commit.Hash); err != nil {
return self.c.Error(err)
return err
}
self.context().MoveSelectedLine(1)
@ -886,7 +887,7 @@ func (self *LocalCommitsController) createFixupCommit(commit *models.Commit) err
func (self *LocalCommitsController) createAmendCommit(commit *models.Commit, includeFileChanges bool) error {
commitMessage, err := self.c.Git().Commit.GetCommitMessage(commit.Hash)
if err != nil {
return self.c.Error(err)
return err
}
if self.c.UserConfig.Git.Commit.AutoWrapCommitMessage {
commitMessage = helpers.TryRemoveHardLineBreaks(commitMessage, self.c.UserConfig.Git.Commit.AutoWrapWidth)
@ -903,7 +904,7 @@ func (self *LocalCommitsController) createAmendCommit(commit *models.Commit, inc
self.c.LogAction(self.c.Tr.Actions.CreateFixupCommit)
return self.c.WithWaitingStatusSync(self.c.Tr.CreatingFixupCommitStatus, func() error {
if err := self.c.Git().Commit.CreateAmendCommit(originalSubject, summary, description, includeFileChanges); err != nil {
return self.c.Error(err)
return err
}
self.context().MoveSelectedLine(1)
@ -944,7 +945,7 @@ func (self *LocalCommitsController) squashAllFixupsAboveSelectedCommit(commit *m
func (self *LocalCommitsController) squashAllFixupsInCurrentBranch() error {
commit, rebaseStartIdx, err := self.findCommitForSquashFixupsInCurrentBranch()
if err != nil {
return self.c.Error(err)
return err
}
return self.squashFixupsImpl(commit, rebaseStartIdx)
@ -1153,10 +1154,8 @@ func (self *LocalCommitsController) GetOnFocus() func(types.OnFocusOpts) error {
context := self.context()
if context.GetSelectedLineIdx() > COMMIT_THRESHOLD && context.GetLimitCommits() {
context.SetLimitCommits(false)
self.c.OnWorker(func(_ gocui.Task) {
if err := self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.COMMITS}}); err != nil {
_ = self.c.Error(err)
}
self.c.OnWorker(func(_ gocui.Task) error {
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.COMMITS}})
})
}

View file

@ -286,7 +286,7 @@ func (self *PatchExplorerController) CopySelectedToClipboard() error {
self.c.LogAction(self.c.Tr.Actions.CopySelectedTextToClipboard)
if err := self.c.OS().CopyToClipboard(selected); err != nil {
return self.c.Error(err)
return err
}
return nil

View file

@ -169,7 +169,7 @@ func (self *RemoteBranchesController) setAsUpstream(selectedBranch *models.Remot
HandleConfirm: func() error {
self.c.LogAction(self.c.Tr.Actions.SetBranchUpstream)
if err := self.c.Git().Branch.SetUpstream(selectedBranch.RemoteName, selectedBranch.Name, checkedOutBranch.Name); err != nil {
return self.c.Error(err)
return err
}
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.BRANCHES, types.REMOTES}})

View file

@ -179,7 +179,7 @@ func (self *RemotesController) remove(remote *models.Remote) error {
HandleConfirm: func() error {
self.c.LogAction(self.c.Tr.Actions.RemoveRemote)
if err := self.c.Git().Remote.RemoveRemote(remote.Name); err != nil {
return self.c.Error(err)
return err
}
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.BRANCHES, types.REMOTES}})
@ -202,7 +202,7 @@ func (self *RemotesController) edit(remote *models.Remote) error {
if updatedRemoteName != remote.Name {
self.c.LogAction(self.c.Tr.Actions.UpdateRemote)
if err := self.c.Git().Remote.RenameRemote(remote.Name, updatedRemoteName); err != nil {
return self.c.Error(err)
return err
}
}
@ -225,7 +225,7 @@ func (self *RemotesController) edit(remote *models.Remote) error {
HandleConfirm: func(updatedRemoteUrl string) error {
self.c.LogAction(self.c.Tr.Actions.UpdateRemote)
if err := self.c.Git().Remote.UpdateRemoteUrl(updatedRemoteName, updatedRemoteUrl); err != nil {
return self.c.Error(err)
return err
}
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.BRANCHES, types.REMOTES}})
},
@ -238,7 +238,7 @@ func (self *RemotesController) fetch(remote *models.Remote) error {
return self.c.WithInlineStatus(remote, types.ItemOperationFetching, context.REMOTES_CONTEXT_KEY, func(task gocui.Task) error {
err := self.c.Git().Sync.FetchRemote(task, remote.Name)
if err != nil {
_ = self.c.Error(err)
return err
}
return self.c.Refresh(types.RefreshOptions{

View file

@ -244,7 +244,7 @@ func (self *StagingController) applySelection(reverse bool) error {
},
)
if err != nil {
return self.c.Error(err)
return err
}
if state.SelectingRange() {
@ -317,7 +317,7 @@ func (self *StagingController) editHunk() error {
Cached: true,
},
); err != nil {
return self.c.Error(err)
return err
}
return nil

View file

@ -109,7 +109,7 @@ func (self *StashController) handleStashApply(stashEntry *models.StashEntry) err
err := self.c.Git().Stash.Apply(stashEntry.Index)
_ = self.postStashRefresh()
if err != nil {
return self.c.Error(err)
return err
}
return nil
}
@ -133,7 +133,7 @@ func (self *StashController) handleStashPop(stashEntry *models.StashEntry) error
err := self.c.Git().Stash.Pop(stashEntry.Index)
_ = self.postStashRefresh()
if err != nil {
return self.c.Error(err)
return err
}
return nil
}
@ -160,7 +160,7 @@ func (self *StashController) handleStashDrop(stashEntry *models.StashEntry) erro
err := self.c.Git().Stash.Drop(stashEntry.Index)
_ = self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.STASH}})
if err != nil {
return self.c.Error(err)
return err
}
return nil
},

View file

@ -68,10 +68,8 @@ func (self *SubCommitsController) GetOnFocus() func(types.OnFocusOpts) error {
context := self.context()
if context.GetSelectedLineIdx() > COMMIT_THRESHOLD && context.GetLimitCommits() {
context.SetLimitCommits(false)
self.c.OnWorker(func(_ gocui.Task) {
if err := self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.SUB_COMMITS}}); err != nil {
_ = self.c.Error(err)
}
self.c.OnWorker(func(_ gocui.Task) error {
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.SUB_COMMITS}})
})
}

View file

@ -163,7 +163,7 @@ func (self *SubmodulesController) add() error {
self.c.LogAction(self.c.Tr.Actions.AddSubmodule)
err := self.c.Git().Submodule.Add(submoduleName, submodulePath, submoduleUrl)
if err != nil {
_ = self.c.Error(err)
return err
}
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.SUBMODULES}})
@ -185,7 +185,7 @@ func (self *SubmodulesController) editURL(submodule *models.SubmoduleConfig) err
self.c.LogAction(self.c.Tr.Actions.UpdateSubmoduleUrl)
err := self.c.Git().Submodule.UpdateUrl(submodule, newUrl)
if err != nil {
_ = self.c.Error(err)
return err
}
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.SUBMODULES}})
@ -199,7 +199,7 @@ func (self *SubmodulesController) init(submodule *models.SubmoduleConfig) error
self.c.LogAction(self.c.Tr.Actions.InitialiseSubmodule)
err := self.c.Git().Submodule.Init(submodule.Path)
if err != nil {
_ = self.c.Error(err)
return err
}
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.SUBMODULES}})
@ -217,7 +217,7 @@ func (self *SubmodulesController) openBulkActionsMenu() error {
self.c.LogAction(self.c.Tr.Actions.BulkInitialiseSubmodules)
err := self.c.Git().Submodule.BulkInitCmdObj().Run()
if err != nil {
return self.c.Error(err)
return err
}
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.SUBMODULES}})
@ -231,7 +231,7 @@ func (self *SubmodulesController) openBulkActionsMenu() error {
return self.c.WithWaitingStatus(self.c.Tr.RunningCommand, func(gocui.Task) error {
self.c.LogAction(self.c.Tr.Actions.BulkUpdateSubmodules)
if err := self.c.Git().Submodule.BulkUpdateCmdObj().Run(); err != nil {
return self.c.Error(err)
return err
}
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.SUBMODULES}})
@ -245,7 +245,7 @@ func (self *SubmodulesController) openBulkActionsMenu() error {
return self.c.WithWaitingStatus(self.c.Tr.RunningCommand, func(gocui.Task) error {
self.c.LogAction(self.c.Tr.Actions.BulkDeinitialiseSubmodules)
if err := self.c.Git().Submodule.BulkDeinitCmdObj().Run(); err != nil {
return self.c.Error(err)
return err
}
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.SUBMODULES}})
@ -262,7 +262,7 @@ func (self *SubmodulesController) update(submodule *models.SubmoduleConfig) erro
self.c.LogAction(self.c.Tr.Actions.UpdateSubmodule)
err := self.c.Git().Submodule.Update(submodule.Path)
if err != nil {
_ = self.c.Error(err)
return err
}
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.SUBMODULES}})
@ -276,7 +276,7 @@ func (self *SubmodulesController) remove(submodule *models.SubmoduleConfig) erro
HandleConfirm: func() error {
self.c.LogAction(self.c.Tr.Actions.RemoveSubmodule)
if err := self.c.Git().Submodule.Delete(submodule); err != nil {
return self.c.Error(err)
return err
}
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.SUBMODULES, types.FILES}})

View file

@ -1,6 +1,7 @@
package controllers
import (
"errors"
"fmt"
"strings"
@ -101,7 +102,7 @@ func (self *SyncController) push(currentBranch *models.Branch) error {
return self.c.Helpers().Upstream.PromptForUpstreamWithInitialContent(currentBranch, func(upstream string) error {
upstreamRemote, upstreamBranch, err := self.c.Helpers().Upstream.ParseUpstream(upstream)
if err != nil {
return self.c.Error(err)
return err
}
return self.pushAux(currentBranch, pushOpts{
@ -121,7 +122,7 @@ func (self *SyncController) pull(currentBranch *models.Branch) error {
if !currentBranch.IsTrackingRemote() {
return self.c.Helpers().Upstream.PromptForUpstreamWithInitialContent(currentBranch, func(upstream string) error {
if err := self.setCurrentBranchUpstream(upstream); err != nil {
return self.c.Error(err)
return err
}
return self.PullAux(currentBranch, PullFilesOptions{Action: action})
@ -197,7 +198,7 @@ func (self *SyncController) pushAux(currentBranch *models.Branch, opts pushOpts)
})
if err != nil {
if strings.Contains(err.Error(), "Updates were rejected") {
return self.c.ErrorMsg(self.c.Tr.UpdatesRejected)
return errors.New(self.c.Tr.UpdatesRejected)
}
return err
}
@ -208,7 +209,7 @@ func (self *SyncController) pushAux(currentBranch *models.Branch, opts pushOpts)
func (self *SyncController) requestToForcePush(currentBranch *models.Branch, opts pushOpts) error {
forcePushDisabled := self.c.UserConfig.Git.DisableForcePushing
if forcePushDisabled {
return self.c.ErrorMsg(self.c.Tr.ForcePushDisabled)
return errors.New(self.c.Tr.ForcePushDisabled)
}
return self.c.Confirm(types.ConfirmOpts{

View file

@ -1,6 +1,8 @@
package controllers
import (
"errors"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/samber/lo"
@ -20,7 +22,7 @@ func (self *ToggleWhitespaceAction) Call() error {
if lo.Contains(contextsThatDontSupportIgnoringWhitespace, self.c.CurrentContext().GetKey()) {
// Ignoring whitespace is not supported in these views. Let the user
// know that it's not going to work in case they try to turn it on.
return self.c.ErrorMsg(self.c.Tr.IgnoreWhitespaceNotSupportedHere)
return errors.New(self.c.Tr.IgnoreWhitespaceNotSupportedHere)
}
self.c.GetAppState().IgnoreWhitespaceInDiffView = !self.c.GetAppState().IgnoreWhitespaceInDiffView

View file

@ -1,6 +1,7 @@
package controllers
import (
"errors"
"fmt"
"github.com/jesseduffield/gocui"
@ -78,7 +79,7 @@ func (self *UndoController) reflogUndo() error {
undoingStatus := self.c.Tr.UndoingStatus
if self.c.Git().Status.WorkingTreeState() == enums.REBASE_MODE_REBASING {
return self.c.ErrorMsg(self.c.Tr.CantUndoWhileRebasing)
return errors.New(self.c.Tr.CantUndoWhileRebasing)
}
return self.parseReflogForActions(func(counter int, action reflogAction) (bool, error) {
@ -126,7 +127,7 @@ func (self *UndoController) reflogRedo() error {
redoingStatus := self.c.Tr.RedoingStatus
if self.c.Git().Status.WorkingTreeState() == enums.REBASE_MODE_REBASING {
return self.c.ErrorMsg(self.c.Tr.CantRedoWhileRebasing)
return errors.New(self.c.Tr.CantRedoWhileRebasing)
}
return self.parseReflogForActions(func(counter int, action reflogAction) (bool, error) {
@ -234,10 +235,7 @@ type hardResetOptions struct {
// only to be used in the undo flow for now (does an autostash)
func (self *UndoController) hardResetWithAutoStash(commitHash string, options hardResetOptions) error {
reset := func() error {
if err := self.c.Helpers().Refs.ResetToRef(commitHash, "hard", options.EnvVars); err != nil {
return self.c.Error(err)
}
return nil
return self.c.Helpers().Refs.ResetToRef(commitHash, "hard", options.EnvVars)
}
// if we have any modified tracked files we need to ask the user if they want us to stash for them
@ -250,20 +248,17 @@ func (self *UndoController) hardResetWithAutoStash(commitHash string, options ha
HandleConfirm: func() error {
return self.c.WithWaitingStatus(options.WaitingStatus, func(gocui.Task) error {
if err := self.c.Git().Stash.Push(self.c.Tr.StashPrefix + commitHash); err != nil {
return self.c.Error(err)
return err
}
if err := reset(); err != nil {
return err
}
err := self.c.Git().Stash.Pop(0)
if err := self.c.Refresh(types.RefreshOptions{}); err != nil {
if err != nil {
return err
}
if err != nil {
return self.c.Error(err)
}
return nil
return self.c.Refresh(types.RefreshOptions{})
})
},
})

View file

@ -2,6 +2,7 @@ package controllers
import (
"bytes"
"errors"
"fmt"
"math"
"math/rand"
@ -31,7 +32,7 @@ func (self *FilesController) createResetMenu() error {
OnPress: func() error {
self.c.LogAction(self.c.Tr.Actions.NukeWorkingTree)
if err := self.c.Git().WorkingTree.ResetAndClean(); err != nil {
return self.c.Error(err)
return err
}
if self.c.UserConfig.Gui.AnimateExplosion {
@ -53,7 +54,7 @@ func (self *FilesController) createResetMenu() error {
OnPress: func() error {
self.c.LogAction(self.c.Tr.Actions.DiscardUnstagedFileChanges)
if err := self.c.Git().WorkingTree.DiscardAnyUnstagedFileChanges(); err != nil {
return self.c.Error(err)
return err
}
return self.c.Refresh(
@ -70,7 +71,7 @@ func (self *FilesController) createResetMenu() error {
OnPress: func() error {
self.c.LogAction(self.c.Tr.Actions.RemoveUntrackedFiles)
if err := self.c.Git().WorkingTree.RemoveUntrackedFiles(); err != nil {
return self.c.Error(err)
return err
}
return self.c.Refresh(
@ -88,13 +89,13 @@ func (self *FilesController) createResetMenu() error {
OnPress: func() error {
self.c.LogAction(self.c.Tr.Actions.RemoveStagedFiles)
if !self.c.Helpers().WorkingTree.IsWorkingTreeDirty() {
return self.c.ErrorMsg(self.c.Tr.NoTrackedStagedFilesStash)
return errors.New(self.c.Tr.NoTrackedStagedFilesStash)
}
if err := self.c.Git().Stash.SaveStagedChanges("[lazygit] tmp stash"); err != nil {
return self.c.Error(err)
return err
}
if err := self.c.Git().Stash.DropNewest(); err != nil {
return self.c.Error(err)
return err
}
return self.c.Refresh(
@ -111,7 +112,7 @@ func (self *FilesController) createResetMenu() error {
OnPress: func() error {
self.c.LogAction(self.c.Tr.Actions.SoftReset)
if err := self.c.Git().WorkingTree.ResetSoft("HEAD"); err != nil {
return self.c.Error(err)
return err
}
return self.c.Refresh(
@ -128,7 +129,7 @@ func (self *FilesController) createResetMenu() error {
OnPress: func() error {
self.c.LogAction(self.c.Tr.Actions.MixedReset)
if err := self.c.Git().WorkingTree.ResetMixed("HEAD"); err != nil {
return self.c.Error(err)
return err
}
return self.c.Refresh(
@ -145,7 +146,7 @@ func (self *FilesController) createResetMenu() error {
OnPress: func() error {
self.c.LogAction(self.c.Tr.Actions.HardReset)
if err := self.c.Git().WorkingTree.ResetHard("HEAD"); err != nil {
return self.c.Error(err)
return err
}
return self.c.Refresh(
@ -180,7 +181,7 @@ func (self *FilesController) Explode(v *gocui.View, onDone func()) {
style.FgBlack.SetBold(),
}
self.c.OnWorker(func(_ gocui.Task) {
self.c.OnWorker(func(_ gocui.Task) error {
max := 25
for i := 0; i < max; i++ {
image := getExplodeImage(width, height, i, max)
@ -198,6 +199,7 @@ func (self *FilesController) Explode(v *gocui.View, onDone func()) {
onDone()
return nil
})
return nil
})
}

View file

@ -1,6 +1,7 @@
package controllers
import (
"errors"
"fmt"
"strings"
"text/tabwriter"
@ -117,11 +118,11 @@ func (self *WorktreesController) add() error {
func (self *WorktreesController) remove(worktree *models.Worktree) error {
if worktree.IsMain {
return self.c.ErrorMsg(self.c.Tr.CantDeleteMainWorktree)
return errors.New(self.c.Tr.CantDeleteMainWorktree)
}
if worktree.IsCurrent {
return self.c.ErrorMsg(self.c.Tr.CantDeleteCurrentWorktree)
return errors.New(self.c.Tr.CantDeleteCurrentWorktree)
}
return self.c.Helpers().Worktree.Remove(worktree, false)

View file

@ -150,7 +150,7 @@ func (gui *Gui) handleCopySelectedSideContextItemToClipboardWithTruncation(maxWi
gui.c.LogAction(gui.c.Tr.Actions.CopyToClipboard)
if err := gui.os.CopyToClipboard(itemId); err != nil {
return gui.c.Error(err)
return err
}
truncatedItemId := utils.TruncateWithEllipsis(strings.Replace(itemId, "\n", " ", -1), 50)

View file

@ -516,8 +516,8 @@ func NewGui(
func() types.Context { return gui.State.ContextMgr.Current() },
gui.createMenu,
func(message string, f func(gocui.Task) error) { gui.helpers.AppStatus.WithWaitingStatus(message, f) },
func(message string, f func() error) {
gui.helpers.AppStatus.WithWaitingStatusSync(message, f)
func(message string, f func() error) error {
return gui.helpers.AppStatus.WithWaitingStatusSync(message, f)
},
func(message string, kind types.ToastKind) { gui.helpers.AppStatus.Toast(message, kind) },
func() string { return gui.Views.Confirmation.TextArea.GetContent() },
@ -652,6 +652,8 @@ func (gui *Gui) Run(startArgs appTypes.StartArgs) error {
gui.g = g
defer gui.g.Close()
g.ErrorHandler = gui.PopupHandler.ErrorHandler
// if the deadlock package wants to report a deadlock, we first need to
// close the gui so that we can actually read what it prints.
deadlock.Opts.LogBuf = utils.NewOnceWriter(os.Stderr, func() {
@ -789,7 +791,7 @@ func (gui *Gui) runSubprocessWithSuspense(subprocess oscommands.ICmdObj) (bool,
defer gui.Mutexes.SubprocessMutex.Unlock()
if err := gui.g.Suspend(); err != nil {
return false, gui.c.Error(err)
return false, err
}
gui.BackgroundRoutineMgr.PauseBackgroundRefreshes(true)
@ -802,7 +804,7 @@ func (gui *Gui) runSubprocessWithSuspense(subprocess oscommands.ICmdObj) (bool,
}
if cmdErr != nil {
return false, gui.c.Error(cmdErr)
return false, cmdErr
}
return true, nil
@ -956,7 +958,7 @@ func (gui *Gui) onUIThread(f func() error) {
})
}
func (gui *Gui) onWorker(f func(gocui.Task)) {
func (gui *Gui) onWorker(f func(gocui.Task) error) {
gui.g.OnWorker(f)
}

View file

@ -151,7 +151,7 @@ func (self *guiCommon) OnUIThread(f func() error) {
self.gui.onUIThread(f)
}
func (self *guiCommon) OnWorker(f func(gocui.Task)) {
func (self *guiCommon) OnWorker(f func(gocui.Task) error) {
self.gui.onWorker(f)
}

View file

@ -1,6 +1,7 @@
package gui
import (
"errors"
"log"
"github.com/jesseduffield/gocui"
@ -442,7 +443,7 @@ func (gui *Gui) callKeybindingHandler(binding *types.Binding) error {
}
if disabledReason != nil {
if disabledReason.ShowErrorInPanel {
return gui.c.ErrorMsg(disabledReason.Text)
return errors.New(disabledReason.Text)
}
gui.c.ErrorToast(gui.Tr.DisabledMenuItemPrefix + disabledReason.Text)

View file

@ -8,20 +8,17 @@ import (
"github.com/jesseduffield/lazygit/pkg/common"
"github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/sasha-s/go-deadlock"
)
type PopupHandler struct {
*common.Common
index int
deadlock.Mutex
createPopupPanelFn func(context.Context, types.CreatePopupPanelOpts) error
onErrorFn func() error
popContextFn func() error
currentContextFn func() types.Context
createMenuFn func(types.CreateMenuOptions) error
withWaitingStatusFn func(message string, f func(gocui.Task) error)
withWaitingStatusSyncFn func(message string, f func() error)
withWaitingStatusSyncFn func(message string, f func() error) error
toastFn func(message string, kind types.ToastKind)
getPromptInputFn func() string
inDemo func() bool
@ -37,14 +34,13 @@ func NewPopupHandler(
currentContextFn func() types.Context,
createMenuFn func(types.CreateMenuOptions) error,
withWaitingStatusFn func(message string, f func(gocui.Task) error),
withWaitingStatusSyncFn func(message string, f func() error),
withWaitingStatusSyncFn func(message string, f func() error) error,
toastFn func(message string, kind types.ToastKind),
getPromptInputFn func() string,
inDemo func() bool,
) *PopupHandler {
return &PopupHandler{
Common: common,
index: 0,
createPopupPanelFn: createPopupPanelFn,
onErrorFn: onErrorFn,
popContextFn: popContextFn,
@ -80,25 +76,12 @@ func (self *PopupHandler) WithWaitingStatus(message string, f func(gocui.Task) e
}
func (self *PopupHandler) WithWaitingStatusSync(message string, f func() error) error {
self.withWaitingStatusSyncFn(message, f)
return nil
return self.withWaitingStatusSyncFn(message, f)
}
func (self *PopupHandler) Error(err error) error {
if err == gocui.ErrQuit {
return err
}
return self.ErrorMsg(err.Error())
}
func (self *PopupHandler) ErrorMsg(message string) error {
self.Lock()
self.index++
self.Unlock()
func (self *PopupHandler) ErrorHandler(err error) error {
// Need to set bold here explicitly; otherwise it gets cancelled by the red colouring.
coloredMessage := style.FgRed.SetBold().Sprint(strings.TrimSpace(message))
coloredMessage := style.FgRed.SetBold().Sprint(strings.TrimSpace(err.Error()))
if err := self.onErrorFn(); err != nil {
return err
}
@ -111,10 +94,6 @@ func (self *PopupHandler) Alert(title string, message string) error {
}
func (self *PopupHandler) Confirm(opts types.ConfirmOpts) error {
self.Lock()
self.index++
self.Unlock()
return self.createPopupPanelFn(context.Background(), types.CreatePopupPanelOpts{
Title: opts.Title,
Prompt: opts.Prompt,
@ -124,10 +103,6 @@ func (self *PopupHandler) Confirm(opts types.ConfirmOpts) error {
}
func (self *PopupHandler) Prompt(opts types.PromptOpts) error {
self.Lock()
self.index++
self.Unlock()
return self.createPopupPanelFn(context.Background(), types.CreatePopupPanelOpts{
Title: opts.Title,
Prompt: opts.InitialContent,

View file

@ -1,6 +1,7 @@
package custom_commands
import (
"errors"
"fmt"
"strings"
"text/template"
@ -74,7 +75,7 @@ func (self *HandlerCreator) call(customCommand config.CustomCommand) func() erro
f = func() error {
resolvedPrompt, err := self.resolver.resolvePrompt(&prompt, resolveTemplate)
if err != nil {
return self.c.Error(err)
return err
}
return self.inputPrompt(resolvedPrompt, wrappedF)
}
@ -82,7 +83,7 @@ func (self *HandlerCreator) call(customCommand config.CustomCommand) func() erro
f = func() error {
resolvedPrompt, err := self.resolver.resolvePrompt(&prompt, resolveTemplate)
if err != nil {
return self.c.Error(err)
return err
}
return self.menuPrompt(resolvedPrompt, wrappedF)
}
@ -90,7 +91,7 @@ func (self *HandlerCreator) call(customCommand config.CustomCommand) func() erro
f = func() error {
resolvedPrompt, err := self.resolver.resolvePrompt(&prompt, resolveTemplate)
if err != nil {
return self.c.Error(err)
return err
}
return self.menuPromptFromCommand(resolvedPrompt, wrappedF)
}
@ -98,12 +99,12 @@ func (self *HandlerCreator) call(customCommand config.CustomCommand) func() erro
f = func() error {
resolvedPrompt, err := self.resolver.resolvePrompt(&prompt, resolveTemplate)
if err != nil {
return self.c.Error(err)
return err
}
return self.confirmPrompt(resolvedPrompt, g)
}
default:
return self.c.ErrorMsg("custom command prompt must have a type of 'input', 'menu', 'menuFromCommand', or 'confirm'")
return errors.New("custom command prompt must have a type of 'input', 'menu', 'menuFromCommand', or 'confirm'")
}
}
@ -114,7 +115,7 @@ func (self *HandlerCreator) call(customCommand config.CustomCommand) func() erro
func (self *HandlerCreator) inputPrompt(prompt *config.CustomCommandPrompt, wrappedF func(string) error) error {
findSuggestionsFn, err := self.generateFindSuggestionsFunc(prompt)
if err != nil {
return self.c.Error(err)
return err
}
return self.c.Prompt(types.PromptOpts{
@ -208,13 +209,13 @@ func (self *HandlerCreator) menuPromptFromCommand(prompt *config.CustomCommandPr
// Run and save output
message, err := self.c.Git().Custom.RunWithOutput(prompt.Command)
if err != nil {
return self.c.Error(err)
return err
}
// Need to make a menu out of what the cmd has displayed
candidates, err := self.menuGenerator.call(message, prompt.Filter, prompt.ValueFormat, prompt.LabelFormat)
if err != nil {
return self.c.Error(err)
return err
}
menuItems := lo.Map(candidates, func(candidate *commandMenuItem, _ int) *types.MenuItem {
@ -253,7 +254,7 @@ func (self *HandlerCreator) finalHandler(customCommand config.CustomCommand, ses
resolveTemplate := self.getResolveTemplateFn(form, promptResponses, sessionState)
cmdStr, err := resolveTemplate(customCommand.Command)
if err != nil {
return self.c.Error(err)
return err
}
cmdObj := self.c.OS().Cmd.NewShell(cmdStr)
@ -284,7 +285,7 @@ func (self *HandlerCreator) finalHandler(customCommand config.CustomCommand, ses
return self.mergeAndRebaseHelper.CheckForConflicts(err)
}
return self.c.Error(err)
return err
}
if customCommand.ShowOutput {

View file

@ -48,13 +48,12 @@ func NewStatusManager() *StatusManager {
return &StatusManager{}
}
func (self *StatusManager) WithWaitingStatus(message string, renderFunc func(), f func(*WaitingStatusHandle)) {
func (self *StatusManager) WithWaitingStatus(message string, renderFunc func(), f func(*WaitingStatusHandle) error) error {
handle := &WaitingStatusHandle{statusManager: self, message: message, renderFunc: renderFunc, id: -1}
handle.Show()
defer handle.Hide()
f(handle)
handle.Hide()
return f(handle)
}
func (self *StatusManager) AddToastStatus(message string, kind types.ToastKind) int {

View file

@ -85,7 +85,7 @@ type IGuiCommon interface {
OnUIThread(f func() error)
// Runs a function in a goroutine. Use this whenever you want to run a goroutine and keep track of the fact
// that lazygit is still busy. See docs/dev/Busy.md
OnWorker(f func(gocui.Task))
OnWorker(f func(gocui.Task) error)
// Function to call at the end of our 'layout' function which renders views
// For example, you may want a view's line to be focused only after that view is
// resized, if in accordion mode.
@ -131,11 +131,8 @@ type IModeMgr interface {
}
type IPopupHandler interface {
// Shows a popup with a (localized) "Error" caption and the given error message (in red).
//
// This is a convenience wrapper around Alert().
ErrorMsg(message string) error
Error(err error) error
// The global error handler for gocui. Not to be used by application code.
ErrorHandler(err error) error
// Shows a notification popup with the given title and message to the user.
//
// This is a convenience wrapper around Confirm(), thus the popup can be closed using both 'Enter' and 'ESC'.

View file

@ -33,7 +33,7 @@ const (
)
type RefreshOptions struct {
Then func()
Then func() error
Scope []RefreshableView // e.g. []RefreshableView{COMMITS, BRANCHES}. Leave empty to refresh everything
Mode RefreshMode // one of SYNC (default), ASYNC, and BLOCK_UI

View file

@ -18,10 +18,10 @@ type AsyncHandler struct {
lastId int
mutex deadlock.Mutex
onReject func()
onWorker func(func(gocui.Task))
onWorker func(func(gocui.Task) error)
}
func NewAsyncHandler(onWorker func(func(gocui.Task))) *AsyncHandler {
func NewAsyncHandler(onWorker func(func(gocui.Task) error)) *AsyncHandler {
return &AsyncHandler{
mutex: deadlock.Mutex{},
onWorker: onWorker,
@ -34,9 +34,10 @@ func (self *AsyncHandler) Do(f func() func()) {
id := self.currentId
self.mutex.Unlock()
self.onWorker(func(gocui.Task) {
self.onWorker(func(gocui.Task) error {
after := f()
self.handle(after, id)
return nil
})
}

View file

@ -13,8 +13,8 @@ func TestAsyncHandler(t *testing.T) {
wg := sync.WaitGroup{}
wg.Add(2)
onWorker := func(f func(gocui.Task)) {
go f(gocui.NewFakeTask())
onWorker := func(f func(gocui.Task) error) {
go func() { _ = f(gocui.NewFakeTask()) }()
}
handler := NewAsyncHandler(onWorker)
handler.onReject = func() {

73
vendor/github.com/gdamore/encoding/CODE_OF_CONDUCT.md generated vendored Normal file
View file

@ -0,0 +1,73 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at garrett@damore.org. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org

View file

@ -1,10 +1,11 @@
## encoding
[![Linux Status](https://img.shields.io/travis/gdamore/encoding.svg?label=linux)](https://travis-ci.org/gdamore/encoding)
[![Windows Status](https://img.shields.io/appveyor/ci/gdamore/encoding.svg?label=windows)](https://ci.appveyor.com/project/gdamore/encoding)
[![Apache License](https://img.shields.io/badge/license-APACHE2-blue.svg)](https://github.com/gdamore/encoding/blob/master/LICENSE)
[![Linux](https://img.shields.io/github/actions/workflow/status/gdamore/encoding/linux.yml?branch=main&logoColor=grey&logo=linux&label=)](https://github.com/gdamore/encoding/actions/workflows/linux.yml)
[![Windows](https://img.shields.io/github/actions/workflow/status/gdamore/encoding/windows.yml?branch=main&logoColor=grey&logo=windows&label=)](https://github.com/gdamore/encoding/actions/workflows/windows.yml)
[![Apache License](https://img.shields.io/github/license/gdamore/encoding.svg?logoColor=silver&logo=opensourceinitiative&color=blue&label=)](https://github.com/gdamore/encoding/blob/master/LICENSE)
[![Coverage](https://img.shields.io/codecov/c/github/gdamore/encoding?logoColor=grey&logo=codecov&label=)](https://codecov.io/gh/gdamore/encoding)
[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://godoc.org/github.com/gdamore/encoding)
[![Go Report Card](http://goreportcard.com/badge/gdamore/encoding)](http://goreportcard.com/report/gdamore/encoding)
Package encoding provides a number of encodings that are missing from the
standard Go [encoding]("https://godoc.org/golang.org/x/text/encoding") package.

12
vendor/github.com/gdamore/encoding/SECURITY.md generated vendored Normal file
View file

@ -0,0 +1,12 @@
# Security Policy
We take security very seriously in mangos, since you may be using it in
Internet-facing applications.
## Reporting a Vulnerability
To report a vulnerability, please contact us on our discord.
You may also send an email to garrett@damore.org, or info@staysail.tech.
We will keep the reporter updated on any status updates on a regular basis,
and will respond within two business days for any reported security issue.

View file

@ -1,4 +1,4 @@
// Copyright 2015 Garrett D'Amore
// Copyright 2024 Garrett D'Amore
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use file except in compliance with the License.
@ -52,7 +52,6 @@ const (
// direction takes about 100 nsec/op. (The larger cost for conversion
// from UTF-8 is most likely due to the need to convert the UTF-8 byte stream
// to a rune before conversion.
//
type Charmap struct {
transform.NopResetter
bytes map[rune]byte
@ -177,7 +176,7 @@ func (d *cmapEncoder) Transform(dst, src []byte, atEOF bool) (int, int, error) {
if r == utf8.RuneError && sz == 1 {
// If its inconclusive due to insufficient data in
// in the source, report it
if !atEOF && !utf8.FullRune(src[nsrc:]) {
if atEOF && !utf8.FullRune(src[nsrc:]) {
e = transform.ErrShortSrc
break
}

View file

@ -322,27 +322,6 @@ func (ei *escapeInterpreter) csiColor(param []string) (color Attribute, skip int
}
}
// splitFgBg splits foreground and background color according to ANSI sequence.
//
// num (number of segments in ansi) is used to determine if it's 256 mode or rgb mode (3 - 256-color, 5 - rgb-color)
func splitFgBg(params []string, num int) [][]string {
var out [][]string
var current []string
for _, p := range params {
if len(current) == num && (p == "48" || p == "38") {
out = append(out, current)
current = []string{}
}
current = append(current, p)
}
if len(current) > 0 {
out = append(out, current)
}
return out
}
func getFontEffect(f int) Attribute {
switch fontEffect(f) {
case bold:

View file

@ -172,6 +172,8 @@ type Gui struct {
NextSearchMatchKey interface{}
PrevSearchMatchKey interface{}
ErrorHandler func(error) error
screen tcell.Screen
suspendedMutex sync.Mutex
suspended bool
@ -661,7 +663,7 @@ func (g *Gui) updateAsyncAux(f func(*Gui) error, task Task) {
// consider itself 'busy` as it runs the code. Don't use for long-running
// background goroutines where you wouldn't want lazygit to be considered busy
// (i.e. when you wouldn't want a loader to be shown to the user)
func (g *Gui) OnWorker(f func(Task)) {
func (g *Gui) OnWorker(f func(Task) error) {
task := g.NewTask()
go func() {
g.onWorkerAux(f, task)
@ -669,7 +671,7 @@ func (g *Gui) OnWorker(f func(Task)) {
}()
}
func (g *Gui) onWorkerAux(f func(Task), task Task) {
func (g *Gui) onWorkerAux(f func(Task) error, task Task) {
panicking := true
defer func() {
if panicking && Screen != nil {
@ -677,9 +679,15 @@ func (g *Gui) onWorkerAux(f func(Task), task Task) {
}
}()
f(task)
err := f(task)
panicking = false
if err != nil {
g.Update(func(g *Gui) error {
return err
})
}
}
// A Manager is in charge of GUI's layout and can be used to build widgets.
@ -745,19 +753,27 @@ func (g *Gui) MainLoop() error {
}
}
func (g *Gui) handleError(err error) error {
if err != nil && !IsQuit(err) && g.ErrorHandler != nil {
return g.ErrorHandler(err)
}
return err
}
func (g *Gui) processEvent() error {
select {
case ev := <-g.gEvents:
task := g.NewTask()
defer func() { task.Done() }()
if err := g.handleEvent(&ev); err != nil {
if err := g.handleError(g.handleEvent(&ev)); err != nil {
return err
}
case ev := <-g.userEvents:
defer func() { ev.task.Done() }()
if err := ev.f(g); err != nil {
if err := g.handleError(ev.f(g)); err != nil {
return err
}
}
@ -777,11 +793,11 @@ func (g *Gui) processRemainingEvents() error {
for {
select {
case ev := <-g.gEvents:
if err := g.handleEvent(&ev); err != nil {
if err := g.handleError(g.handleEvent(&ev)); err != nil {
return err
}
case ev := <-g.userEvents:
err := ev.f(g)
err := g.handleError(ev.f(g))
ev.task.Done()
if err != nil {
return err
@ -815,17 +831,6 @@ func (g *Gui) onResize() {
// g.screen.Sync()
}
func (g *Gui) clear(fg, bg Attribute) (int, int) {
st := getTcellStyle(oldStyle{fg: fg, bg: bg, outputMode: g.outputMode})
w, h := Screen.Size()
for row := 0; row < h; row++ {
for col := 0; col < w; col++ {
Screen.SetContent(col, row, ' ', nil, st)
}
}
return w, h
}
// drawFrameEdges draws the horizontal and vertical edges of a view.
func (g *Gui) drawFrameEdges(v *View, fgColor, bgColor Attribute) error {
runeH, runeV := '─', '│'
@ -1397,7 +1402,7 @@ func (g *Gui) execKeybindings(v *View, ev *GocuiEvent) (matched bool, err error)
var matchingParentViewKb *keybinding
// if we're searching, and we've hit n/N/Esc, we ignore the default keybinding
if v != nil && v.IsSearching() && Modifier(ev.Mod) == ModNone {
if v != nil && v.IsSearching() && ev.Mod == ModNone {
if eventMatchesKey(ev, g.NextSearchMatchKey) {
return true, v.gotoNextMatch()
} else if eventMatchesKey(ev, g.PrevSearchMatchKey) {
@ -1417,7 +1422,7 @@ func (g *Gui) execKeybindings(v *View, ev *GocuiEvent) (matched bool, err error)
if kb.handler == nil {
continue
}
if !kb.matchKeypress(Key(ev.Key), ev.Ch, Modifier(ev.Mod)) {
if !kb.matchKeypress(ev.Key, ev.Ch, ev.Mod) {
continue
}
if g.matchView(v, kb) {
@ -1435,7 +1440,7 @@ func (g *Gui) execKeybindings(v *View, ev *GocuiEvent) (matched bool, err error)
}
if g.currentView != nil && g.currentView.Editable && g.currentView.Editor != nil {
matched := g.currentView.Editor.Edit(g.currentView, Key(ev.Key), ev.Ch, Modifier(ev.Mod))
matched := g.currentView.Editor.Edit(g.currentView, ev.Key, ev.Ch, ev.Mod)
if matched {
return true, nil
}
@ -1550,7 +1555,7 @@ func (g *Gui) matchView(v *View, kb *keybinding) bool {
if v == nil {
return false
}
if v.Editable == true && kb.ch != 0 {
if v.Editable && kb.ch != 0 {
return false
}
if kb.viewName != v.name {

View file

@ -46,16 +46,14 @@ func (g *Gui) getTermWindowSize() (int, int, error) {
return termw, termh, nil
}
select {
case signal := <-signalCh:
switch signal {
// when the terminal window size is changed
case syscall.SIGWINCH:
continue
// ctrl + c to cancel
case syscall.SIGINT:
return 0, 0, errors.New("stop to get term window size")
}
signal := <-signalCh
switch signal {
// when the terminal window size is changed
case syscall.SIGWINCH:
continue
// ctrl + c to cancel
case syscall.SIGINT:
return 0, 0, errors.New("stop to get term window size")
}
}
}

View file

@ -13,10 +13,12 @@ import (
"unsafe"
)
type wchar uint16
type short int16
type dword uint32
type word uint16
type (
wchar uint16
short int16
dword uint32
word uint16
)
type coord struct {
x short

View file

@ -105,7 +105,7 @@ func newKeybinding(viewname string, key Key, ch rune, mod Modifier, handler func
func eventMatchesKey(ev *GocuiEvent, key interface{}) bool {
// assuming ModNone for now
if Modifier(ev.Mod) != ModNone {
if ev.Mod != ModNone {
return false
}
@ -114,7 +114,7 @@ func eventMatchesKey(ev *GocuiEvent, key interface{}) bool {
return false
}
return k == Key(ev.Key) && ch == ev.Ch
return k == ev.Key && ch == ev.Ch
}
// matchKeypress returns if the keybinding matches the keypress.

View file

@ -767,7 +767,7 @@ func (v *View) writeString(s string) {
// parseInput parses char by char the input written to the View. It returns nil
// while processing ESC sequences. Otherwise, it returns a cell slice that
// contains the processed data.
func (v *View) parseInput(ch rune, x int, y int) (bool, []cell) {
func (v *View) parseInput(ch rune, x int, _ int) (bool, []cell) {
cells := []cell{}
moveCursor := true
@ -1283,7 +1283,7 @@ func (v *View) Word(x, y int) (string, error) {
} else {
nr = nr + x
}
return string(str[nl:nr]), nil
return str[nl:nr], nil
}
// indexFunc allows to split lines by words taking into account spaces

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build aix || darwin || dragonfly || freebsd || openbsd || solaris
//go:build aix || darwin || dragonfly || freebsd || openbsd || solaris || zos
package unix

View file

@ -1520,6 +1520,14 @@ func (m *mmapper) Munmap(data []byte) (err error) {
return nil
}
func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
return mapper.Mmap(fd, offset, length, prot, flags)
}
func Munmap(b []byte) (err error) {
return mapper.Munmap(b)
}
func Read(fd int, p []byte) (n int, err error) {
n, err = read(fd, p)
if raceenabled {

View file

@ -165,6 +165,7 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile Handle) (handle Handle, err error) [failretval==InvalidHandle] = CreateFileW
//sys CreateNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *SecurityAttributes) (handle Handle, err error) [failretval==InvalidHandle] = CreateNamedPipeW
//sys ConnectNamedPipe(pipe Handle, overlapped *Overlapped) (err error)
//sys DisconnectNamedPipe(pipe Handle) (err error)
//sys GetNamedPipeInfo(pipe Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error)
//sys GetNamedPipeHandleState(pipe Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW
//sys SetNamedPipeHandleState(pipe Handle, state *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32) (err error) = SetNamedPipeHandleState
@ -348,8 +349,19 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys SetProcessPriorityBoost(process Handle, disable bool) (err error) = kernel32.SetProcessPriorityBoost
//sys GetProcessWorkingSetSizeEx(hProcess Handle, lpMinimumWorkingSetSize *uintptr, lpMaximumWorkingSetSize *uintptr, flags *uint32)
//sys SetProcessWorkingSetSizeEx(hProcess Handle, dwMinimumWorkingSetSize uintptr, dwMaximumWorkingSetSize uintptr, flags uint32) (err error)
//sys ClearCommBreak(handle Handle) (err error)
//sys ClearCommError(handle Handle, lpErrors *uint32, lpStat *ComStat) (err error)
//sys EscapeCommFunction(handle Handle, dwFunc uint32) (err error)
//sys GetCommState(handle Handle, lpDCB *DCB) (err error)
//sys GetCommModemStatus(handle Handle, lpModemStat *uint32) (err error)
//sys GetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error)
//sys PurgeComm(handle Handle, dwFlags uint32) (err error)
//sys SetCommBreak(handle Handle) (err error)
//sys SetCommMask(handle Handle, dwEvtMask uint32) (err error)
//sys SetCommState(handle Handle, lpDCB *DCB) (err error)
//sys SetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error)
//sys SetupComm(handle Handle, dwInQueue uint32, dwOutQueue uint32) (err error)
//sys WaitCommEvent(handle Handle, lpEvtMask *uint32, lpOverlapped *Overlapped) (err error)
//sys GetActiveProcessorCount(groupNumber uint16) (ret uint32)
//sys GetMaximumProcessorCount(groupNumber uint16) (ret uint32)
//sys EnumWindows(enumFunc uintptr, param unsafe.Pointer) (err error) = user32.EnumWindows
@ -1834,3 +1846,73 @@ func ResizePseudoConsole(pconsole Handle, size Coord) error {
// accept arguments that can be casted to uintptr, and Coord can't.
return resizePseudoConsole(pconsole, *((*uint32)(unsafe.Pointer(&size))))
}
// DCB constants. See https://learn.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-dcb.
const (
CBR_110 = 110
CBR_300 = 300
CBR_600 = 600
CBR_1200 = 1200
CBR_2400 = 2400
CBR_4800 = 4800
CBR_9600 = 9600
CBR_14400 = 14400
CBR_19200 = 19200
CBR_38400 = 38400
CBR_57600 = 57600
CBR_115200 = 115200
CBR_128000 = 128000
CBR_256000 = 256000
DTR_CONTROL_DISABLE = 0x00000000
DTR_CONTROL_ENABLE = 0x00000010
DTR_CONTROL_HANDSHAKE = 0x00000020
RTS_CONTROL_DISABLE = 0x00000000
RTS_CONTROL_ENABLE = 0x00001000
RTS_CONTROL_HANDSHAKE = 0x00002000
RTS_CONTROL_TOGGLE = 0x00003000
NOPARITY = 0
ODDPARITY = 1
EVENPARITY = 2
MARKPARITY = 3
SPACEPARITY = 4
ONESTOPBIT = 0
ONE5STOPBITS = 1
TWOSTOPBITS = 2
)
// EscapeCommFunction constants. See https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-escapecommfunction.
const (
SETXOFF = 1
SETXON = 2
SETRTS = 3
CLRRTS = 4
SETDTR = 5
CLRDTR = 6
SETBREAK = 8
CLRBREAK = 9
)
// PurgeComm constants. See https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-purgecomm.
const (
PURGE_TXABORT = 0x0001
PURGE_RXABORT = 0x0002
PURGE_TXCLEAR = 0x0004
PURGE_RXCLEAR = 0x0008
)
// SetCommMask constants. See https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setcommmask.
const (
EV_RXCHAR = 0x0001
EV_RXFLAG = 0x0002
EV_TXEMPTY = 0x0004
EV_CTS = 0x0008
EV_DSR = 0x0010
EV_RLSD = 0x0020
EV_BREAK = 0x0040
EV_ERR = 0x0080
EV_RING = 0x0100
)

View file

@ -3380,3 +3380,27 @@ type BLOB struct {
Size uint32
BlobData *byte
}
type ComStat struct {
Flags uint32
CBInQue uint32
CBOutQue uint32
}
type DCB struct {
DCBlength uint32
BaudRate uint32
Flags uint32
wReserved uint16
XonLim uint16
XoffLim uint16
ByteSize uint8
Parity uint8
StopBits uint8
XonChar byte
XoffChar byte
ErrorChar byte
EofChar byte
EvtChar byte
wReserved1 uint16
}

View file

@ -188,6 +188,8 @@ var (
procAssignProcessToJobObject = modkernel32.NewProc("AssignProcessToJobObject")
procCancelIo = modkernel32.NewProc("CancelIo")
procCancelIoEx = modkernel32.NewProc("CancelIoEx")
procClearCommBreak = modkernel32.NewProc("ClearCommBreak")
procClearCommError = modkernel32.NewProc("ClearCommError")
procCloseHandle = modkernel32.NewProc("CloseHandle")
procClosePseudoConsole = modkernel32.NewProc("ClosePseudoConsole")
procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe")
@ -212,7 +214,9 @@ var (
procDeleteProcThreadAttributeList = modkernel32.NewProc("DeleteProcThreadAttributeList")
procDeleteVolumeMountPointW = modkernel32.NewProc("DeleteVolumeMountPointW")
procDeviceIoControl = modkernel32.NewProc("DeviceIoControl")
procDisconnectNamedPipe = modkernel32.NewProc("DisconnectNamedPipe")
procDuplicateHandle = modkernel32.NewProc("DuplicateHandle")
procEscapeCommFunction = modkernel32.NewProc("EscapeCommFunction")
procExitProcess = modkernel32.NewProc("ExitProcess")
procExpandEnvironmentStringsW = modkernel32.NewProc("ExpandEnvironmentStringsW")
procFindClose = modkernel32.NewProc("FindClose")
@ -236,6 +240,8 @@ var (
procGenerateConsoleCtrlEvent = modkernel32.NewProc("GenerateConsoleCtrlEvent")
procGetACP = modkernel32.NewProc("GetACP")
procGetActiveProcessorCount = modkernel32.NewProc("GetActiveProcessorCount")
procGetCommModemStatus = modkernel32.NewProc("GetCommModemStatus")
procGetCommState = modkernel32.NewProc("GetCommState")
procGetCommTimeouts = modkernel32.NewProc("GetCommTimeouts")
procGetCommandLineW = modkernel32.NewProc("GetCommandLineW")
procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW")
@ -322,6 +328,7 @@ var (
procProcess32NextW = modkernel32.NewProc("Process32NextW")
procProcessIdToSessionId = modkernel32.NewProc("ProcessIdToSessionId")
procPulseEvent = modkernel32.NewProc("PulseEvent")
procPurgeComm = modkernel32.NewProc("PurgeComm")
procQueryDosDeviceW = modkernel32.NewProc("QueryDosDeviceW")
procQueryFullProcessImageNameW = modkernel32.NewProc("QueryFullProcessImageNameW")
procQueryInformationJobObject = modkernel32.NewProc("QueryInformationJobObject")
@ -335,6 +342,9 @@ var (
procResetEvent = modkernel32.NewProc("ResetEvent")
procResizePseudoConsole = modkernel32.NewProc("ResizePseudoConsole")
procResumeThread = modkernel32.NewProc("ResumeThread")
procSetCommBreak = modkernel32.NewProc("SetCommBreak")
procSetCommMask = modkernel32.NewProc("SetCommMask")
procSetCommState = modkernel32.NewProc("SetCommState")
procSetCommTimeouts = modkernel32.NewProc("SetCommTimeouts")
procSetConsoleCursorPosition = modkernel32.NewProc("SetConsoleCursorPosition")
procSetConsoleMode = modkernel32.NewProc("SetConsoleMode")
@ -342,7 +352,6 @@ var (
procSetDefaultDllDirectories = modkernel32.NewProc("SetDefaultDllDirectories")
procSetDllDirectoryW = modkernel32.NewProc("SetDllDirectoryW")
procSetEndOfFile = modkernel32.NewProc("SetEndOfFile")
procSetFileValidData = modkernel32.NewProc("SetFileValidData")
procSetEnvironmentVariableW = modkernel32.NewProc("SetEnvironmentVariableW")
procSetErrorMode = modkernel32.NewProc("SetErrorMode")
procSetEvent = modkernel32.NewProc("SetEvent")
@ -351,6 +360,7 @@ var (
procSetFileInformationByHandle = modkernel32.NewProc("SetFileInformationByHandle")
procSetFilePointer = modkernel32.NewProc("SetFilePointer")
procSetFileTime = modkernel32.NewProc("SetFileTime")
procSetFileValidData = modkernel32.NewProc("SetFileValidData")
procSetHandleInformation = modkernel32.NewProc("SetHandleInformation")
procSetInformationJobObject = modkernel32.NewProc("SetInformationJobObject")
procSetNamedPipeHandleState = modkernel32.NewProc("SetNamedPipeHandleState")
@ -361,6 +371,7 @@ var (
procSetStdHandle = modkernel32.NewProc("SetStdHandle")
procSetVolumeLabelW = modkernel32.NewProc("SetVolumeLabelW")
procSetVolumeMountPointW = modkernel32.NewProc("SetVolumeMountPointW")
procSetupComm = modkernel32.NewProc("SetupComm")
procSizeofResource = modkernel32.NewProc("SizeofResource")
procSleepEx = modkernel32.NewProc("SleepEx")
procTerminateJobObject = modkernel32.NewProc("TerminateJobObject")
@ -379,6 +390,7 @@ var (
procVirtualQueryEx = modkernel32.NewProc("VirtualQueryEx")
procVirtualUnlock = modkernel32.NewProc("VirtualUnlock")
procWTSGetActiveConsoleSessionId = modkernel32.NewProc("WTSGetActiveConsoleSessionId")
procWaitCommEvent = modkernel32.NewProc("WaitCommEvent")
procWaitForMultipleObjects = modkernel32.NewProc("WaitForMultipleObjects")
procWaitForSingleObject = modkernel32.NewProc("WaitForSingleObject")
procWriteConsoleW = modkernel32.NewProc("WriteConsoleW")
@ -1641,6 +1653,22 @@ func CancelIoEx(s Handle, o *Overlapped) (err error) {
return
}
func ClearCommBreak(handle Handle) (err error) {
r1, _, e1 := syscall.Syscall(procClearCommBreak.Addr(), 1, uintptr(handle), 0, 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func ClearCommError(handle Handle, lpErrors *uint32, lpStat *ComStat) (err error) {
r1, _, e1 := syscall.Syscall(procClearCommError.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(lpErrors)), uintptr(unsafe.Pointer(lpStat)))
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func CloseHandle(handle Handle) (err error) {
r1, _, e1 := syscall.Syscall(procCloseHandle.Addr(), 1, uintptr(handle), 0, 0)
if r1 == 0 {
@ -1845,6 +1873,14 @@ func DeviceIoControl(handle Handle, ioControlCode uint32, inBuffer *byte, inBuff
return
}
func DisconnectNamedPipe(pipe Handle) (err error) {
r1, _, e1 := syscall.Syscall(procDisconnectNamedPipe.Addr(), 1, uintptr(pipe), 0, 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error) {
var _p0 uint32
if bInheritHandle {
@ -1857,6 +1893,14 @@ func DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetP
return
}
func EscapeCommFunction(handle Handle, dwFunc uint32) (err error) {
r1, _, e1 := syscall.Syscall(procEscapeCommFunction.Addr(), 2, uintptr(handle), uintptr(dwFunc), 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func ExitProcess(exitcode uint32) {
syscall.Syscall(procExitProcess.Addr(), 1, uintptr(exitcode), 0, 0)
return
@ -2058,6 +2102,22 @@ func GetActiveProcessorCount(groupNumber uint16) (ret uint32) {
return
}
func GetCommModemStatus(handle Handle, lpModemStat *uint32) (err error) {
r1, _, e1 := syscall.Syscall(procGetCommModemStatus.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(lpModemStat)), 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func GetCommState(handle Handle, lpDCB *DCB) (err error) {
r1, _, e1 := syscall.Syscall(procGetCommState.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(lpDCB)), 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func GetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error) {
r1, _, e1 := syscall.Syscall(procGetCommTimeouts.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(timeouts)), 0)
if r1 == 0 {
@ -2810,6 +2870,14 @@ func PulseEvent(event Handle) (err error) {
return
}
func PurgeComm(handle Handle, dwFlags uint32) (err error) {
r1, _, e1 := syscall.Syscall(procPurgeComm.Addr(), 2, uintptr(handle), uintptr(dwFlags), 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func QueryDosDevice(deviceName *uint16, targetPath *uint16, max uint32) (n uint32, err error) {
r0, _, e1 := syscall.Syscall(procQueryDosDeviceW.Addr(), 3, uintptr(unsafe.Pointer(deviceName)), uintptr(unsafe.Pointer(targetPath)), uintptr(max))
n = uint32(r0)
@ -2924,6 +2992,30 @@ func ResumeThread(thread Handle) (ret uint32, err error) {
return
}
func SetCommBreak(handle Handle) (err error) {
r1, _, e1 := syscall.Syscall(procSetCommBreak.Addr(), 1, uintptr(handle), 0, 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func SetCommMask(handle Handle, dwEvtMask uint32) (err error) {
r1, _, e1 := syscall.Syscall(procSetCommMask.Addr(), 2, uintptr(handle), uintptr(dwEvtMask), 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func SetCommState(handle Handle, lpDCB *DCB) (err error) {
r1, _, e1 := syscall.Syscall(procSetCommState.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(lpDCB)), 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func SetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error) {
r1, _, e1 := syscall.Syscall(procSetCommTimeouts.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(timeouts)), 0)
if r1 == 0 {
@ -2989,14 +3081,6 @@ func SetEndOfFile(handle Handle) (err error) {
return
}
func SetFileValidData(handle Handle, validDataLength int64) (err error) {
r1, _, e1 := syscall.Syscall(procSetFileValidData.Addr(), 2, uintptr(handle), uintptr(validDataLength), 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func SetEnvironmentVariable(name *uint16, value *uint16) (err error) {
r1, _, e1 := syscall.Syscall(procSetEnvironmentVariableW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value)), 0)
if r1 == 0 {
@ -3060,6 +3144,14 @@ func SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetim
return
}
func SetFileValidData(handle Handle, validDataLength int64) (err error) {
r1, _, e1 := syscall.Syscall(procSetFileValidData.Addr(), 2, uintptr(handle), uintptr(validDataLength), 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error) {
r1, _, e1 := syscall.Syscall(procSetHandleInformation.Addr(), 3, uintptr(handle), uintptr(mask), uintptr(flags))
if r1 == 0 {
@ -3145,6 +3237,14 @@ func SetVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16) (err erro
return
}
func SetupComm(handle Handle, dwInQueue uint32, dwOutQueue uint32) (err error) {
r1, _, e1 := syscall.Syscall(procSetupComm.Addr(), 3, uintptr(handle), uintptr(dwInQueue), uintptr(dwOutQueue))
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func SizeofResource(module Handle, resInfo Handle) (size uint32, err error) {
r0, _, e1 := syscall.Syscall(procSizeofResource.Addr(), 2, uintptr(module), uintptr(resInfo), 0)
size = uint32(r0)
@ -3291,6 +3391,14 @@ func WTSGetActiveConsoleSessionId() (sessionID uint32) {
return
}
func WaitCommEvent(handle Handle, lpEvtMask *uint32, lpOverlapped *Overlapped) (err error) {
r1, _, e1 := syscall.Syscall(procWaitCommEvent.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(lpEvtMask)), uintptr(unsafe.Pointer(lpOverlapped)))
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func waitForMultipleObjects(count uint32, handles uintptr, waitAll bool, waitMilliseconds uint32) (event uint32, err error) {
var _p0 uint32
if waitAll {

8
vendor/modules.txt vendored
View file

@ -37,7 +37,7 @@ github.com/fatih/color
# github.com/fsmiamoto/git-todo-parser v0.0.5
## explicit; go 1.13
github.com/fsmiamoto/git-todo-parser/todo
# github.com/gdamore/encoding v1.0.0
# github.com/gdamore/encoding v1.0.1
## explicit; go 1.9
github.com/gdamore/encoding
# github.com/gdamore/tcell/v2 v2.7.4
@ -172,7 +172,7 @@ github.com/jesseduffield/go-git/v5/utils/merkletrie/filesystem
github.com/jesseduffield/go-git/v5/utils/merkletrie/index
github.com/jesseduffield/go-git/v5/utils/merkletrie/internal/frame
github.com/jesseduffield/go-git/v5/utils/merkletrie/noder
# github.com/jesseduffield/gocui v0.3.1-0.20240309085756-86e0d5a312de
# github.com/jesseduffield/gocui v0.3.1-0.20240418080333-8cd33929c513
## explicit; go 1.12
github.com/jesseduffield/gocui
# github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10
@ -310,13 +310,13 @@ golang.org/x/exp/slices
golang.org/x/net/context
golang.org/x/net/internal/socks
golang.org/x/net/proxy
# golang.org/x/sys v0.18.0
# golang.org/x/sys v0.19.0
## explicit; go 1.18
golang.org/x/sys/cpu
golang.org/x/sys/plan9
golang.org/x/sys/unix
golang.org/x/sys/windows
# golang.org/x/term v0.18.0
# golang.org/x/term v0.19.0
## explicit; go 1.18
golang.org/x/term
# golang.org/x/text v0.14.0