From 7ebf5fff0f637d375a6ccb27f5f3e73ce291aa75 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Mon, 30 Jun 2025 14:13:03 +0200 Subject: [PATCH 01/13] Provide a script to lint the whole working copy, and update make lint to use it The script expects a golangci-lint binary in .bin; this makes it possible to install the exact same version that also runs on CI. --- Makefile | 2 +- scripts/lint.sh | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100755 scripts/lint.sh diff --git a/Makefile b/Makefile index ca490a94a..f972100a1 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,7 @@ format: .PHONY: lint lint: - golangci-lint run + ./scripts/lint.sh # For more details about integration test, see https://github.com/jesseduffield/lazygit/blob/master/pkg/integration/README.md. .PHONY: integration-test-tui diff --git a/scripts/lint.sh b/scripts/lint.sh new file mode 100755 index 000000000..98d697bc1 --- /dev/null +++ b/scripts/lint.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +set -e + +if [ ! -x ./.bin/golangci-lint ]; then + echo 'You need to install golangci-lint into .bin' + echo 'One way to do this is to run' + echo ' GOBIN=$(pwd)/.bin go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.2.1' + exit 1 +fi + +./.bin/golangci-lint run From 8c574f888c01fee48958557bd51373e3b2ee1c7c Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Fri, 20 Jun 2025 19:49:46 +0200 Subject: [PATCH 02/13] Fix warning ST1016: methods on the same type should have the same receiver name Most methods use gui as a receiver name (120 of them), so switch the few that use self over to that too. --- pkg/gui/gui.go | 4 +- pkg/gui/keybindings.go | 198 ++++++++++++++++++++--------------------- 2 files changed, 101 insertions(+), 101 deletions(-) diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index ac1be6601..3f79622b8 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -586,8 +586,8 @@ func (gui *Gui) resetState(startArgs appTypes.StartArgs) types.Context { return initialContext(contextTree, startArgs) } -func (self *Gui) getViewBufferManagerForView(view *gocui.View) *tasks.ViewBufferManager { - manager, ok := self.viewBufferManagerMap[view.Name()] +func (gui *Gui) getViewBufferManagerForView(view *gocui.View) *tasks.ViewBufferManager { + manager, ok := gui.viewBufferManagerMap[view.Name()] if !ok { return nil } diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go index 63d25b622..4b41ebe1d 100644 --- a/pkg/gui/keybindings.go +++ b/pkg/gui/keybindings.go @@ -45,27 +45,27 @@ func (gui *Gui) validateNotInFilterMode() bool { } // only to be called from the cheatsheet generate script. This mutates the Gui struct. -func (self *Gui) GetCheatsheetKeybindings() []*types.Binding { - self.g = &gocui.Gui{} - if err := self.createAllViews(); err != nil { +func (gui *Gui) GetCheatsheetKeybindings() []*types.Binding { + gui.g = &gocui.Gui{} + if err := gui.createAllViews(); err != nil { panic(err) } // need to instantiate views - self.helpers = helpers.NewStubHelpers() - self.State = &GuiRepoState{} - self.State.Contexts = self.contextTree() - self.State.ContextMgr = NewContextMgr(self, self.State.Contexts) - self.resetHelpersAndControllers() - bindings, _ := self.GetInitialKeybindings() + gui.helpers = helpers.NewStubHelpers() + gui.State = &GuiRepoState{} + gui.State.Contexts = gui.contextTree() + gui.State.ContextMgr = NewContextMgr(gui, gui.State.Contexts) + gui.resetHelpersAndControllers() + bindings, _ := gui.GetInitialKeybindings() return bindings } -func (self *Gui) keybindingOpts() types.KeybindingsOpts { - config := self.c.UserConfig().Keybinding +func (gui *Gui) keybindingOpts() types.KeybindingsOpts { + config := gui.c.UserConfig().Keybinding guards := types.KeybindingGuards{ - OutsideFilterMode: self.outsideFilterMode, - NoPopupPanel: self.noPopupPanel, + OutsideFilterMode: gui.outsideFilterMode, + NoPopupPanel: gui.noPopupPanel, } return types.KeybindingsOpts{ @@ -76,318 +76,318 @@ func (self *Gui) keybindingOpts() types.KeybindingsOpts { } // renaming receiver to 'self' to aid refactoring. Will probably end up moving all Gui handlers to this pattern eventually. -func (self *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBinding) { - opts := self.c.KeybindingsOpts() +func (gui *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBinding) { + opts := gui.c.KeybindingsOpts() bindings := []*types.Binding{ { ViewName: "", Key: opts.GetKey(opts.Config.Universal.OpenRecentRepos), - Handler: opts.Guards.NoPopupPanel(self.helpers.Repos.CreateRecentReposMenu), - Description: self.c.Tr.SwitchRepo, + Handler: opts.Guards.NoPopupPanel(gui.helpers.Repos.CreateRecentReposMenu), + Description: gui.c.Tr.SwitchRepo, }, { ViewName: "", Key: opts.GetKey(opts.Config.Universal.ScrollUpMain), - Handler: self.scrollUpMain, + Handler: gui.scrollUpMain, Alternative: "fn+up/shift+k", - Description: self.c.Tr.ScrollUpMainWindow, + Description: gui.c.Tr.ScrollUpMainWindow, }, { ViewName: "", Key: opts.GetKey(opts.Config.Universal.ScrollDownMain), - Handler: self.scrollDownMain, + Handler: gui.scrollDownMain, Alternative: "fn+down/shift+j", - Description: self.c.Tr.ScrollDownMainWindow, + Description: gui.c.Tr.ScrollDownMainWindow, }, { ViewName: "", Key: opts.GetKey(opts.Config.Universal.ScrollUpMainAlt1), Modifier: gocui.ModNone, - Handler: self.scrollUpMain, + Handler: gui.scrollUpMain, }, { ViewName: "", Key: opts.GetKey(opts.Config.Universal.ScrollDownMainAlt1), Modifier: gocui.ModNone, - Handler: self.scrollDownMain, + Handler: gui.scrollDownMain, }, { ViewName: "", Key: opts.GetKey(opts.Config.Universal.ScrollUpMainAlt2), Modifier: gocui.ModNone, - Handler: self.scrollUpMain, + Handler: gui.scrollUpMain, }, { ViewName: "", Key: opts.GetKey(opts.Config.Universal.ScrollDownMainAlt2), Modifier: gocui.ModNone, - Handler: self.scrollDownMain, + Handler: gui.scrollDownMain, }, { ViewName: "files", Key: opts.GetKey(opts.Config.Universal.CopyToClipboard), - Handler: self.handleCopySelectedSideContextItemToClipboard, - GetDisabledReason: self.getCopySelectedSideContextItemToClipboardDisabledReason, - Description: self.c.Tr.CopyPathToClipboard, + Handler: gui.handleCopySelectedSideContextItemToClipboard, + GetDisabledReason: gui.getCopySelectedSideContextItemToClipboardDisabledReason, + Description: gui.c.Tr.CopyPathToClipboard, }, { ViewName: "localBranches", Key: opts.GetKey(opts.Config.Universal.CopyToClipboard), - Handler: self.handleCopySelectedSideContextItemToClipboard, - GetDisabledReason: self.getCopySelectedSideContextItemToClipboardDisabledReason, - Description: self.c.Tr.CopyBranchNameToClipboard, + Handler: gui.handleCopySelectedSideContextItemToClipboard, + GetDisabledReason: gui.getCopySelectedSideContextItemToClipboardDisabledReason, + Description: gui.c.Tr.CopyBranchNameToClipboard, }, { ViewName: "remoteBranches", Key: opts.GetKey(opts.Config.Universal.CopyToClipboard), - Handler: self.handleCopySelectedSideContextItemToClipboard, - GetDisabledReason: self.getCopySelectedSideContextItemToClipboardDisabledReason, - Description: self.c.Tr.CopyBranchNameToClipboard, + Handler: gui.handleCopySelectedSideContextItemToClipboard, + GetDisabledReason: gui.getCopySelectedSideContextItemToClipboardDisabledReason, + Description: gui.c.Tr.CopyBranchNameToClipboard, }, { ViewName: "tags", Key: opts.GetKey(opts.Config.Universal.CopyToClipboard), - Handler: self.handleCopySelectedSideContextItemToClipboard, - GetDisabledReason: self.getCopySelectedSideContextItemToClipboardDisabledReason, - Description: self.c.Tr.CopyTagToClipboard, + Handler: gui.handleCopySelectedSideContextItemToClipboard, + GetDisabledReason: gui.getCopySelectedSideContextItemToClipboardDisabledReason, + Description: gui.c.Tr.CopyTagToClipboard, }, { ViewName: "commits", Key: opts.GetKey(opts.Config.Universal.CopyToClipboard), - Handler: self.handleCopySelectedSideContextItemCommitHashToClipboard, - GetDisabledReason: self.getCopySelectedSideContextItemToClipboardDisabledReason, - Description: self.c.Tr.CopyCommitHashToClipboard, + Handler: gui.handleCopySelectedSideContextItemCommitHashToClipboard, + GetDisabledReason: gui.getCopySelectedSideContextItemToClipboardDisabledReason, + Description: gui.c.Tr.CopyCommitHashToClipboard, }, { ViewName: "commits", Key: opts.GetKey(opts.Config.Commits.ResetCherryPick), - Handler: self.helpers.CherryPick.Reset, - Description: self.c.Tr.ResetCherryPick, + Handler: gui.helpers.CherryPick.Reset, + Description: gui.c.Tr.ResetCherryPick, }, { ViewName: "reflogCommits", Key: opts.GetKey(opts.Config.Universal.CopyToClipboard), - Handler: self.handleCopySelectedSideContextItemToClipboard, - GetDisabledReason: self.getCopySelectedSideContextItemToClipboardDisabledReason, - Description: self.c.Tr.CopyCommitHashToClipboard, + Handler: gui.handleCopySelectedSideContextItemToClipboard, + GetDisabledReason: gui.getCopySelectedSideContextItemToClipboardDisabledReason, + Description: gui.c.Tr.CopyCommitHashToClipboard, }, { ViewName: "subCommits", Key: opts.GetKey(opts.Config.Universal.CopyToClipboard), - Handler: self.handleCopySelectedSideContextItemCommitHashToClipboard, - GetDisabledReason: self.getCopySelectedSideContextItemToClipboardDisabledReason, - Description: self.c.Tr.CopyCommitHashToClipboard, + Handler: gui.handleCopySelectedSideContextItemCommitHashToClipboard, + GetDisabledReason: gui.getCopySelectedSideContextItemToClipboardDisabledReason, + Description: gui.c.Tr.CopyCommitHashToClipboard, }, { ViewName: "information", Key: gocui.MouseLeft, Modifier: gocui.ModNone, - Handler: self.handleInfoClick, + Handler: gui.handleInfoClick, }, { ViewName: "commitFiles", Key: opts.GetKey(opts.Config.Universal.CopyToClipboard), - Handler: self.handleCopySelectedSideContextItemToClipboard, - GetDisabledReason: self.getCopySelectedSideContextItemToClipboardDisabledReason, - Description: self.c.Tr.CopyPathToClipboard, + Handler: gui.handleCopySelectedSideContextItemToClipboard, + GetDisabledReason: gui.getCopySelectedSideContextItemToClipboardDisabledReason, + Description: gui.c.Tr.CopyPathToClipboard, }, { ViewName: "", Key: opts.GetKey(opts.Config.Universal.ExtrasMenu), - Handler: opts.Guards.NoPopupPanel(self.handleCreateExtrasMenuPanel), - Description: self.c.Tr.OpenCommandLogMenu, - Tooltip: self.c.Tr.OpenCommandLogMenuTooltip, + Handler: opts.Guards.NoPopupPanel(gui.handleCreateExtrasMenuPanel), + Description: gui.c.Tr.OpenCommandLogMenu, + Tooltip: gui.c.Tr.OpenCommandLogMenuTooltip, OpensMenu: true, }, { ViewName: "main", Key: gocui.MouseWheelDown, - Handler: self.scrollDownMain, - Description: self.c.Tr.ScrollDown, + Handler: gui.scrollDownMain, + Description: gui.c.Tr.ScrollDown, Alternative: "fn+up", }, { ViewName: "main", Key: gocui.MouseWheelUp, - Handler: self.scrollUpMain, - Description: self.c.Tr.ScrollUp, + Handler: gui.scrollUpMain, + Description: gui.c.Tr.ScrollUp, Alternative: "fn+down", }, { ViewName: "secondary", Key: gocui.MouseWheelDown, Modifier: gocui.ModNone, - Handler: self.scrollDownSecondary, + Handler: gui.scrollDownSecondary, }, { ViewName: "secondary", Key: gocui.MouseWheelUp, Modifier: gocui.ModNone, - Handler: self.scrollUpSecondary, + Handler: gui.scrollUpSecondary, }, { ViewName: "confirmation", Key: opts.GetKey(opts.Config.Universal.PrevItem), Modifier: gocui.ModNone, - Handler: self.scrollUpConfirmationPanel, + Handler: gui.scrollUpConfirmationPanel, }, { ViewName: "confirmation", Key: opts.GetKey(opts.Config.Universal.NextItem), Modifier: gocui.ModNone, - Handler: self.scrollDownConfirmationPanel, + Handler: gui.scrollDownConfirmationPanel, }, { ViewName: "confirmation", Key: opts.GetKey(opts.Config.Universal.PrevItemAlt), Modifier: gocui.ModNone, - Handler: self.scrollUpConfirmationPanel, + Handler: gui.scrollUpConfirmationPanel, }, { ViewName: "confirmation", Key: opts.GetKey(opts.Config.Universal.NextItemAlt), Modifier: gocui.ModNone, - Handler: self.scrollDownConfirmationPanel, + Handler: gui.scrollDownConfirmationPanel, }, { ViewName: "confirmation", Key: gocui.MouseWheelUp, - Handler: self.scrollUpConfirmationPanel, + Handler: gui.scrollUpConfirmationPanel, }, { ViewName: "confirmation", Key: gocui.MouseWheelDown, - Handler: self.scrollDownConfirmationPanel, + Handler: gui.scrollDownConfirmationPanel, }, { ViewName: "confirmation", Key: opts.GetKey(opts.Config.Universal.NextPage), Modifier: gocui.ModNone, - Handler: self.pageDownConfirmationPanel, + Handler: gui.pageDownConfirmationPanel, }, { ViewName: "confirmation", Key: opts.GetKey(opts.Config.Universal.PrevPage), Modifier: gocui.ModNone, - Handler: self.pageUpConfirmationPanel, + Handler: gui.pageUpConfirmationPanel, }, { ViewName: "confirmation", Key: opts.GetKey(opts.Config.Universal.GotoTop), Modifier: gocui.ModNone, - Handler: self.goToConfirmationPanelTop, + Handler: gui.goToConfirmationPanelTop, }, { ViewName: "confirmation", Key: opts.GetKey(opts.Config.Universal.GotoTopAlt), Modifier: gocui.ModNone, - Handler: self.goToConfirmationPanelTop, + Handler: gui.goToConfirmationPanelTop, }, { ViewName: "confirmation", Key: opts.GetKey(opts.Config.Universal.GotoBottom), Modifier: gocui.ModNone, - Handler: self.goToConfirmationPanelBottom, + Handler: gui.goToConfirmationPanelBottom, }, { ViewName: "confirmation", Key: opts.GetKey(opts.Config.Universal.GotoBottomAlt), Modifier: gocui.ModNone, - Handler: self.goToConfirmationPanelBottom, + Handler: gui.goToConfirmationPanelBottom, }, { ViewName: "submodules", Key: opts.GetKey(opts.Config.Universal.CopyToClipboard), - Handler: self.handleCopySelectedSideContextItemToClipboard, - GetDisabledReason: self.getCopySelectedSideContextItemToClipboardDisabledReason, - Description: self.c.Tr.CopySubmoduleNameToClipboard, + Handler: gui.handleCopySelectedSideContextItemToClipboard, + GetDisabledReason: gui.getCopySelectedSideContextItemToClipboardDisabledReason, + Description: gui.c.Tr.CopySubmoduleNameToClipboard, }, { ViewName: "extras", Key: gocui.MouseWheelUp, - Handler: self.scrollUpExtra, + Handler: gui.scrollUpExtra, }, { ViewName: "extras", Key: gocui.MouseWheelDown, - Handler: self.scrollDownExtra, + Handler: gui.scrollDownExtra, }, { ViewName: "extras", Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.PrevItemAlt), Modifier: gocui.ModNone, - Handler: self.scrollUpExtra, + Handler: gui.scrollUpExtra, }, { ViewName: "extras", Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.PrevItem), Modifier: gocui.ModNone, - Handler: self.scrollUpExtra, + Handler: gui.scrollUpExtra, }, { ViewName: "extras", Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.NextItem), Modifier: gocui.ModNone, - Handler: self.scrollDownExtra, + Handler: gui.scrollDownExtra, }, { ViewName: "extras", Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.NextItemAlt), Modifier: gocui.ModNone, - Handler: self.scrollDownExtra, + Handler: gui.scrollDownExtra, }, { ViewName: "extras", Key: opts.GetKey(opts.Config.Universal.NextPage), Modifier: gocui.ModNone, - Handler: self.pageDownExtrasPanel, + Handler: gui.pageDownExtrasPanel, }, { ViewName: "extras", Key: opts.GetKey(opts.Config.Universal.PrevPage), Modifier: gocui.ModNone, - Handler: self.pageUpExtrasPanel, + Handler: gui.pageUpExtrasPanel, }, { ViewName: "extras", Key: opts.GetKey(opts.Config.Universal.GotoTop), Modifier: gocui.ModNone, - Handler: self.goToExtrasPanelTop, + Handler: gui.goToExtrasPanelTop, }, { ViewName: "extras", Key: opts.GetKey(opts.Config.Universal.GotoTopAlt), Modifier: gocui.ModNone, - Handler: self.goToExtrasPanelTop, + Handler: gui.goToExtrasPanelTop, }, { ViewName: "extras", Key: opts.GetKey(opts.Config.Universal.GotoBottom), Modifier: gocui.ModNone, - Handler: self.goToExtrasPanelBottom, + Handler: gui.goToExtrasPanelBottom, }, { ViewName: "extras", Key: opts.GetKey(opts.Config.Universal.GotoBottomAlt), Modifier: gocui.ModNone, - Handler: self.goToExtrasPanelBottom, + Handler: gui.goToExtrasPanelBottom, }, { ViewName: "extras", Tag: "navigation", Key: gocui.MouseLeft, Modifier: gocui.ModNone, - Handler: self.handleFocusCommandLog, + Handler: gui.handleFocusCommandLog, }, } mouseKeybindings := []*gocui.ViewMouseBinding{} - for _, c := range self.State.Contexts.Flatten() { + for _, c := range gui.State.Contexts.Flatten() { viewName := c.GetViewName() for _, binding := range c.GetKeybindings(opts) { // TODO: move all mouse keybindings into the mouse keybindings approach below @@ -402,15 +402,15 @@ func (self *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBi { ViewName: "", Key: opts.GetKey(opts.Config.Universal.NextTab), - Handler: opts.Guards.NoPopupPanel(self.handleNextTab), - Description: self.c.Tr.NextTab, + Handler: opts.Guards.NoPopupPanel(gui.handleNextTab), + Description: gui.c.Tr.NextTab, Tag: "navigation", }, { ViewName: "", Key: opts.GetKey(opts.Config.Universal.PrevTab), - Handler: opts.Guards.NoPopupPanel(self.handlePrevTab), - Description: self.c.Tr.PrevTab, + Handler: opts.Guards.NoPopupPanel(gui.handlePrevTab), + Description: gui.c.Tr.PrevTab, Tag: "navigation", }, }...) @@ -418,12 +418,12 @@ func (self *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBi return bindings, mouseKeybindings } -func (self *Gui) GetInitialKeybindingsWithCustomCommands() ([]*types.Binding, []*gocui.ViewMouseBinding) { +func (gui *Gui) GetInitialKeybindingsWithCustomCommands() ([]*types.Binding, []*gocui.ViewMouseBinding) { // if the search or filter prompt is open, we only want the keybindings for // that context. It shouldn't be possible, for example, to open a menu while // the prompt is showing; you first need to confirm or cancel the search/filter. - if currentContext := self.State.ContextMgr.Current(); currentContext.GetKey() == context.SEARCH_CONTEXT_KEY { - bindings := currentContext.GetKeybindings(self.c.KeybindingsOpts()) + if currentContext := gui.State.ContextMgr.Current(); currentContext.GetKey() == context.SEARCH_CONTEXT_KEY { + bindings := currentContext.GetKeybindings(gui.c.KeybindingsOpts()) viewName := currentContext.GetViewName() for _, binding := range bindings { binding.ViewName = viewName @@ -431,8 +431,8 @@ func (self *Gui) GetInitialKeybindingsWithCustomCommands() ([]*types.Binding, [] return bindings, nil } - bindings, mouseBindings := self.GetInitialKeybindings() - customBindings, err := self.CustomCommandsClient.GetCustomCommandKeybindings() + bindings, mouseBindings := gui.GetInitialKeybindings() + customBindings, err := gui.CustomCommandsClient.GetCustomCommandKeybindings() if err != nil { log.Fatal(err) } From b7aecf5f17832b776101201ade645e9916324577 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Fri, 20 Jun 2025 19:55:45 +0200 Subject: [PATCH 03/13] Fix warning ST1016: methods on the same type should have the same receiver name --- pkg/commands/git_commands/file_loader.go | 8 ++++---- pkg/tasks/tasks.go | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/commands/git_commands/file_loader.go b/pkg/commands/git_commands/file_loader.go index bb898d06a..92a011f63 100644 --- a/pkg/commands/git_commands/file_loader.go +++ b/pkg/commands/git_commands/file_loader.go @@ -110,8 +110,8 @@ type FileDiff struct { LinesDeleted int } -func (fileLoader *FileLoader) getFileDiffs() (map[string]FileDiff, error) { - diffs, err := fileLoader.gitDiffNumStat() +func (self *FileLoader) getFileDiffs() (map[string]FileDiff, error) { + diffs, err := self.gitDiffNumStat() if err != nil { return nil, err } @@ -157,8 +157,8 @@ type FileStatus struct { PreviousPath string } -func (fileLoader *FileLoader) gitDiffNumStat() (string, error) { - return fileLoader.cmd.New( +func (self *FileLoader) gitDiffNumStat() (string, error) { + return self.cmd.New( NewGitCmd("diff"). Arg("--numstat"). Arg("-z"). diff --git a/pkg/tasks/tasks.go b/pkg/tasks/tasks.go index bc56c5110..8de96b249 100644 --- a/pkg/tasks/tasks.go +++ b/pkg/tasks/tasks.go @@ -75,8 +75,8 @@ type LinesToRead struct { Then func() } -func (m *ViewBufferManager) GetTaskKey() string { - return m.taskKey +func (self *ViewBufferManager) GetTaskKey() string { + return self.taskKey } func NewViewBufferManager( From 4604227238144665a359278106383fd934058eea Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Fri, 20 Jun 2025 19:55:25 +0200 Subject: [PATCH 04/13] Make stashEntryFromLine a free-standing function It doesn't use the receiver at all, so doesn't have to be a method. This fixes ST1016: methods on the same type should have the same receiver name. --- pkg/commands/git_commands/stash_loader.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/commands/git_commands/stash_loader.go b/pkg/commands/git_commands/stash_loader.go index f97cc718a..d0a290507 100644 --- a/pkg/commands/git_commands/stash_loader.go +++ b/pkg/commands/git_commands/stash_loader.go @@ -53,7 +53,7 @@ outer: if err != nil { return self.getUnfilteredStashEntries() } - currentStashEntry = self.stashEntryFromLine(lines[i], idx) + currentStashEntry = stashEntryFromLine(lines[i], idx) for i+1 < len(lines) && !isAStash(lines[i+1]) { i++ if lines[i] == filterPath { @@ -70,11 +70,11 @@ func (self *StashLoader) getUnfilteredStashEntries() []*models.StashEntry { rawString, _ := self.cmd.New(cmdArgs).DontLog().RunWithOutput() return lo.Map(utils.SplitNul(rawString), func(line string, index int) *models.StashEntry { - return self.stashEntryFromLine(line, index) + return stashEntryFromLine(line, index) }) } -func (c *StashLoader) stashEntryFromLine(line string, index int) *models.StashEntry { +func stashEntryFromLine(line string, index int) *models.StashEntry { model := &models.StashEntry{ Name: line, Index: index, From c7d0aaa786fc3f84d44d063a438cad567bc30ef3 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Fri, 20 Jun 2025 19:57:03 +0200 Subject: [PATCH 05/13] Fix warning QF1004: could use strings.ReplaceAll instead --- pkg/commands/git_commands/commit_loader_test.go | 6 +++--- pkg/commands/git_commands/reflog_commit_loader_test.go | 4 ++-- pkg/commands/oscommands/os.go | 2 +- pkg/gui/command_log_panel.go | 2 +- pkg/gui/controllers/helpers/refs_helper.go | 2 +- pkg/gui/global_handlers.go | 2 +- pkg/utils/lines.go | 6 +++--- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/pkg/commands/git_commands/commit_loader_test.go b/pkg/commands/git_commands/commit_loader_test.go index cc959b4ea..fcbc825d9 100644 --- a/pkg/commands/git_commands/commit_loader_test.go +++ b/pkg/commands/git_commands/commit_loader_test.go @@ -16,16 +16,16 @@ import ( "github.com/stretchr/testify/assert" ) -var commitsOutput = strings.Replace(`0eea75e8c631fba6b58135697835d58ba4c18dbc|1640826609|Jesse Duffield|jessedduffield@gmail.com|HEAD -> better-tests|b21997d6b4cbdf84b149|>|better typing for rebase mode +var commitsOutput = strings.ReplaceAll(`0eea75e8c631fba6b58135697835d58ba4c18dbc|1640826609|Jesse Duffield|jessedduffield@gmail.com|HEAD -> better-tests|b21997d6b4cbdf84b149|>|better typing for rebase mode b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164|1640824515|Jesse Duffield|jessedduffield@gmail.com|origin/better-tests|e94e8fc5b6fab4cb755f|>|fix logging e94e8fc5b6fab4cb755f29f1bdb3ee5e001df35c|1640823749|Jesse Duffield|jessedduffield@gmail.com|tag: 123, tag: 456|d8084cd558925eb7c9c3|>|refactor d8084cd558925eb7c9c38afeed5725c21653ab90|1640821426|Jesse Duffield|jessedduffield@gmail.com||65f910ebd85283b5cce9|>|WIP 65f910ebd85283b5cce9bf67d03d3f1a9ea3813a|1640821275|Jesse Duffield|jessedduffield@gmail.com||26c07b1ab33860a1a759|>|WIP 26c07b1ab33860a1a7591a0638f9925ccf497ffa|1640750752|Jesse Duffield|jessedduffield@gmail.com||3d4470a6c072208722e5|>|WIP 3d4470a6c072208722e5ae9a54bcb9634959a1c5|1640748818|Jesse Duffield|jessedduffield@gmail.com||053a66a7be3da43aacdc|>|WIP -053a66a7be3da43aacdc7aa78e1fe757b82c4dd2|1640739815|Jesse Duffield|jessedduffield@gmail.com||985fe482e806b172aea4|>|refactoring the config struct`, "|", "\x00", -1) +053a66a7be3da43aacdc7aa78e1fe757b82c4dd2|1640739815|Jesse Duffield|jessedduffield@gmail.com||985fe482e806b172aea4|>|refactoring the config struct`, "|", "\x00") -var singleCommitOutput = strings.Replace(`0eea75e8c631fba6b58135697835d58ba4c18dbc|1640826609|Jesse Duffield|jessedduffield@gmail.com|HEAD -> better-tests|b21997d6b4cbdf84b149|>|better typing for rebase mode`, "|", "\x00", -1) +var singleCommitOutput = strings.ReplaceAll(`0eea75e8c631fba6b58135697835d58ba4c18dbc|1640826609|Jesse Duffield|jessedduffield@gmail.com|HEAD -> better-tests|b21997d6b4cbdf84b149|>|better typing for rebase mode`, "|", "\x00") func TestGetCommits(t *testing.T) { type scenario struct { diff --git a/pkg/commands/git_commands/reflog_commit_loader_test.go b/pkg/commands/git_commands/reflog_commit_loader_test.go index 5cc7395c0..01e479e5c 100644 --- a/pkg/commands/git_commands/reflog_commit_loader_test.go +++ b/pkg/commands/git_commands/reflog_commit_loader_test.go @@ -14,12 +14,12 @@ import ( "github.com/stretchr/testify/assert" ) -var reflogOutput = strings.Replace(`c3c4b66b64c97ffeecde|1643150483|checkout: moving from A to B|51baa8c1 +var reflogOutput = strings.ReplaceAll(`c3c4b66b64c97ffeecde|1643150483|checkout: moving from A to B|51baa8c1 c3c4b66b64c97ffeecde|1643150483|checkout: moving from B to A|51baa8c1 c3c4b66b64c97ffeecde|1643150483|checkout: moving from A to B|51baa8c1 c3c4b66b64c97ffeecde|1643150483|checkout: moving from master to A|51baa8c1 f4ddf2f0d4be4ccc7efa|1643149435|checkout: moving from A to master|51baa8c1 -`, "|", "\x00", -1) +`, "|", "\x00") func TestGetReflogCommits(t *testing.T) { type scenario struct { diff --git a/pkg/commands/oscommands/os.go b/pkg/commands/oscommands/os.go index 042af3f92..2443e8c35 100644 --- a/pkg/commands/oscommands/os.go +++ b/pkg/commands/oscommands/os.go @@ -283,7 +283,7 @@ func PrepareForChildren(cmd *exec.Cmd) { } func (c *OSCommand) CopyToClipboard(str string) error { - escaped := strings.Replace(str, "\n", "\\n", -1) + escaped := strings.ReplaceAll(str, "\n", "\\n") truncated := utils.TruncateWithEllipsis(escaped, 40) msg := utils.ResolvePlaceholderString( diff --git a/pkg/gui/command_log_panel.go b/pkg/gui/command_log_panel.go index 8c1daa4c7..c0319f5c0 100644 --- a/pkg/gui/command_log_panel.go +++ b/pkg/gui/command_log_panel.go @@ -48,7 +48,7 @@ func (gui *Gui) LogCommand(cmdStr string, commandLine bool) { textStyle = style.FgMagenta } gui.GuiLog = append(gui.GuiLog, cmdStr) - indentedCmdStr := " " + strings.Replace(cmdStr, "\n", "\n ", -1) + indentedCmdStr := " " + strings.ReplaceAll(cmdStr, "\n", "\n ") fmt.Fprint(gui.Views.Extras, "\n"+textStyle.Sprint(indentedCmdStr)) } diff --git a/pkg/gui/controllers/helpers/refs_helper.go b/pkg/gui/controllers/helpers/refs_helper.go index 8936a1d61..7a7f29d8e 100644 --- a/pkg/gui/controllers/helpers/refs_helper.go +++ b/pkg/gui/controllers/helpers/refs_helper.go @@ -563,7 +563,7 @@ func (self *RefsHelper) CanMoveCommitsToNewBranch() *types.DisabledReason { // SanitizedBranchName will remove all spaces in favor of a dash "-" to meet // git's branch naming requirement. func SanitizedBranchName(input string) string { - return strings.Replace(input, " ", "-", -1) + return strings.ReplaceAll(input, " ", "-") } // Checks if the given branch name is a remote branch, and returns the name of diff --git a/pkg/gui/global_handlers.go b/pkg/gui/global_handlers.go index 62f9311ea..9abadf4e0 100644 --- a/pkg/gui/global_handlers.go +++ b/pkg/gui/global_handlers.go @@ -185,7 +185,7 @@ func (gui *Gui) handleCopySelectedSideContextItemToClipboardWithTruncation(maxWi return err } - truncatedItemId := utils.TruncateWithEllipsis(strings.Replace(itemId, "\n", " ", -1), 50) + truncatedItemId := utils.TruncateWithEllipsis(strings.ReplaceAll(itemId, "\n", " "), 50) gui.c.Toast(fmt.Sprintf("'%s' %s", truncatedItemId, gui.c.Tr.CopiedToClipboard)) diff --git a/pkg/utils/lines.go b/pkg/utils/lines.go index c601bb806..576f48371 100644 --- a/pkg/utils/lines.go +++ b/pkg/utils/lines.go @@ -11,7 +11,7 @@ import ( // currently we are also stripping \r's which may have adverse effects for // windows users (but no issues have been raised yet) func SplitLines(multilineString string) []string { - multilineString = strings.Replace(multilineString, "\r", "", -1) + multilineString = strings.ReplaceAll(multilineString, "\r", "") if multilineString == "" || multilineString == "\n" { return make([]string, 0) } @@ -32,8 +32,8 @@ func SplitNul(str string) []string { // NormalizeLinefeeds - Removes all Windows and Mac style line feeds func NormalizeLinefeeds(str string) string { - str = strings.Replace(str, "\r\n", "\n", -1) - str = strings.Replace(str, "\r", "", -1) + str = strings.ReplaceAll(str, "\r\n", "\n") + str = strings.ReplaceAll(str, "\r", "") return str } From 92093ce56a40c2d0cc893db122c414d7cee7da22 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Sun, 29 Jun 2025 10:39:21 +0200 Subject: [PATCH 06/13] Fix warning QF1003: could use tagged switch --- pkg/gui/controllers/list_controller.go | 5 +++-- pkg/gui/presentation/files.go | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/pkg/gui/controllers/list_controller.go b/pkg/gui/controllers/list_controller.go index 36ac1ba91..2fbadd2fe 100644 --- a/pkg/gui/controllers/list_controller.go +++ b/pkg/gui/controllers/list_controller.go @@ -109,10 +109,11 @@ func (self *ListController) handleLineChangeAux(f func(int), change int) error { // we're not constantly re-rendering the main view. cursorMoved := before != after if cursorMoved { - if change == -1 { + switch change { + case -1: checkScrollUp(self.context.GetViewTrait(), self.c.UserConfig(), self.context.ModelIndexToViewIndex(before), self.context.ModelIndexToViewIndex(after)) - } else if change == 1 { + case 1: checkScrollDown(self.context.GetViewTrait(), self.c.UserConfig(), self.context.ModelIndexToViewIndex(before), self.context.ModelIndexToViewIndex(after)) } diff --git a/pkg/gui/presentation/files.go b/pkg/gui/presentation/files.go index 64296aa8c..4222fb68d 100644 --- a/pkg/gui/presentation/files.go +++ b/pkg/gui/presentation/files.go @@ -185,9 +185,10 @@ func getFileLine( func formatFileStatus(file *models.File, restColor style.TextStyle) string { firstChar := file.ShortStatus[0:1] firstCharCl := style.FgGreen - if firstChar == "?" { + switch firstChar { + case "?": firstCharCl = theme.UnstagedChangesColor - } else if firstChar == " " { + case " ": firstCharCl = restColor } From c4de94cff04be814a74cde45adb9521861ed5dd8 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Sun, 22 Jun 2025 11:14:45 +0200 Subject: [PATCH 07/13] Update .golangci.yml to use version 2 The config file was migrated using `golangci-lint migrate`, and then edited by hand to disable a few checks that we don't want. --- .github/workflows/ci.yml | 4 +- .golangci.yml | 118 +++++++++++++++++++++++++++++---------- 2 files changed, 91 insertions(+), 31 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fb3fe8f50..99ea11280 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -169,9 +169,9 @@ jobs: with: go-version: 1.24.x - name: Lint - uses: golangci/golangci-lint-action@v6.5.0 + uses: golangci/golangci-lint-action@v8 with: - version: v1.64.6 + version: v2.2.1 - name: errors run: golangci-lint run if: ${{ failure() }} diff --git a/.golangci.yml b/.golangci.yml index 209e79c5c..1aa648246 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,36 +1,96 @@ +version: "2" +run: + go: "1.24" linters: enable: - - gofumpt - - thelper - - goimports - - tparallel - - wastedassign - - unparam - - prealloc - - unconvert + - copyloopvar - exhaustive - makezero - nakedret - - copyloopvar - fast: false + - prealloc + - thelper + - tparallel + - unconvert + - unparam + - wastedassign + settings: + copyloopvar: + check-alias: true + exhaustive: + default-signifies-exhaustive: true + nakedret: + # the gods will judge me but I just don't like naked returns at all + max-func-lines: 0 + staticcheck: + checks: + - all -linters-settings: - copyloopvar: - # Check all assigning the loop variable to another variable. - # Default: false - # If true, an assignment like `a := x` will be detected as an error. - check-alias: true - exhaustive: - default-signifies-exhaustive: true - staticcheck: - # SA1019 is for checking that we're not using fields marked as deprecated - # in a comment. It decides this in a loose way so I'm silencing it. Also because - # it's tripping on our own structs. - checks: ["all", "-SA1019"] - nakedret: - # the gods will judge me but I just don't like naked returns at all - max-func-lines: 0 + # SA1019 is for checking that we're not using fields marked as + # deprecated in a comment. It decides this in a loose way so I'm + # silencing it. Also because it's tripping on our own structs. + - -SA1019 -run: - go: "1.24" - timeout: 10m + # ST1003 complains about names like remoteUrl or itemId (should be + # remoteURL and itemID). While I like these suggestions, it also + # complains about enum constants that are all caps, and we use these and + # I like them, and also about camelCase identifiers that contain an + # underscore, which we also use in a few places. Since it can't be + # configured to ignore specific cases, and I don't want to use nolint + # comments in the code, we have to disable it altogether. + - -ST1003 # Poorly chosen identifier + + # Probably a good idea, but we first have to review our error reporting + # strategy to be able to use it everywhere. + - -ST1005 # Error strings should not be capitalized + + # Many of our classes use self as a receiver name, and we think that's fine. + - -ST1006 # Use of self or this as receiver name + + # De Morgan's law suggests to replace `!(a && b)` with `!a || !b`; but + # sometimes I find one more readable than the other, so I want to decide + # that myself. + - -QF1001 # De Morgan's law + + # QF1003 is about using a tagged switch instead of an if-else chain. In + # many cases this is a useful suggestion; however, sometimes the change + # is only possible by adding a default case to the switch (when there + # was no `else` block in the original code), in which case I don't find + # it to be an improvement. + - -QF1003 # Could replace with tagged switch + + # We need to review our use of embedded fields. I suspect that in some + # cases the fix is not to remove the selector for the embedded field, + # but to turn the embedded field into a named field. + - -QF1008 # Could remove embedded field from selector + + # The following checks are all disabled by default in golangci-lint, but + # we disable them again explicitly here to make it easier to keep this + # list in sync with the gopls config in .vscode/settings.json. + - -ST1000, # At least one file in a package should have a package comment + - -ST1020, # The documentation of an exported function should start with the function's name + - -ST1021, # The documentation of an exported type should start with type's name + - -ST1022, # The documentation of an exported variable or constant should start with variable's name + + dot-import-whitelist: + - github.com/jesseduffield/lazygit/pkg/integration/components + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + paths: + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - gofumpt + - goimports + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ From 9b54dc0b28992cfdd161ce5f5365d7b21c5d1eb9 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Mon, 30 Jun 2025 15:38:14 +0200 Subject: [PATCH 08/13] Update VS Code settings to use golangci-lint v2 We configure it to call the same binary that the new lint script also uses (see beginning of the branch). --- .vscode/settings.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.vscode/settings.json b/.vscode/settings.json index 219c87aea..f1a17a3c9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,4 +2,8 @@ "gopls": { "formatting.gofumpt": true, }, + "go.alternateTools": { + "golangci-lint-v2": "${workspaceFolder}/.bin/golangci-lint", + }, + "go.lintTool": "golangci-lint-v2", } From d9e299c1dfb654caee04d59091489262dcd431aa Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Mon, 30 Jun 2025 10:12:18 +0200 Subject: [PATCH 09/13] Update VS Code settings to enable staticcheck linter ... and configure it to run the same checks as golangci-lint. It may seem redundant to have two linter checks enabled; however, there are reasons to have both. golangci-lint is what we are running on CI, and it has a lot more linters than gopls, so we want to run it locally too to get the same coverage. The linter that is built into gopls is only staticcheck, so that's redundant; but it has the advantage that the warnings appear a bit faster (golangci-lint runs only on save, and with a bit of delay), and in particular it provides quick fixes for some of the checks, which is quite convenient. --- .vscode/settings.json | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.vscode/settings.json b/.vscode/settings.json index f1a17a3c9..23a0e524b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,26 @@ { "gopls": { "formatting.gofumpt": true, + "ui.diagnostic.staticcheck": true, + "ui.diagnostic.analyses": { + // This list must match the one in .golangci.yml + "SA1019": false, + "ST1003": false, + "ST1005": false, + "ST1006": false, + "QF1001": false, + "QF1003": false, + "QF1008": false, + "ST1000": false, + "ST1020": false, + "ST1021": false, + "ST1022": false, + // Dot imports; this warning is enabled in .golangci.yml, but with an + // extra dot-import-whitelist config. Because I couldn't figure out how to + // specify that extra config for gopls, I'm disabling the check altogether + // here. + "ST1001": false, + }, }, "go.alternateTools": { "golangci-lint-v2": "${workspaceFolder}/.bin/golangci-lint", From 1e92d8b7f317fa5272310fc9e92863f5bdfa02d9 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Mon, 30 Jun 2025 10:40:02 +0200 Subject: [PATCH 10/13] Enable nolintlint linter, and fix warnings --- .golangci.yml | 1 + pkg/gui/controllers/files_controller.go | 2 +- pkg/gui/controllers/list_controller_trait.go | 2 +- pkg/gui/gui.go | 2 +- pkg/integration/components/runner.go | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 1aa648246..cbd7de85d 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -7,6 +7,7 @@ linters: - exhaustive - makezero - nakedret + - nolintlint - prealloc - thelper - tparallel diff --git a/pkg/gui/controllers/files_controller.go b/pkg/gui/controllers/files_controller.go index d10d4726a..0c8db786f 100644 --- a/pkg/gui/controllers/files_controller.go +++ b/pkg/gui/controllers/files_controller.go @@ -18,7 +18,7 @@ import ( ) type FilesController struct { - baseController // nolint: unused + baseController *ListControllerTrait[*filetree.FileNode] c *ControllerCommon } diff --git a/pkg/gui/controllers/list_controller_trait.go b/pkg/gui/controllers/list_controller_trait.go index fa5fc1492..4f05a3d2a 100644 --- a/pkg/gui/controllers/list_controller_trait.go +++ b/pkg/gui/controllers/list_controller_trait.go @@ -87,7 +87,7 @@ func (self *ListControllerTrait[T]) itemRangeSelected(callbacks ...func([]T, int } } -func (self *ListControllerTrait[T]) itemsSelected(callbacks ...func([]T) *types.DisabledReason) func() *types.DisabledReason { //nolint:unused +func (self *ListControllerTrait[T]) itemsSelected(callbacks ...func([]T) *types.DisabledReason) func() *types.DisabledReason { return func() *types.DisabledReason { items, _, _ := self.getSelectedItems() if len(items) == 0 { diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index 3f79622b8..84ab86a62 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -965,7 +965,7 @@ func (gui *Gui) runSubprocessWithSuspense(subprocess *oscommands.CmdObj) (bool, return true, nil } -func (gui *Gui) runSubprocess(cmdObj *oscommands.CmdObj) error { //nolint:unparam +func (gui *Gui) runSubprocess(cmdObj *oscommands.CmdObj) error { gui.LogCommand(cmdObj.ToString(), true) subprocess := cmdObj.GetCmd() diff --git a/pkg/integration/components/runner.go b/pkg/integration/components/runner.go index f123182cf..7952b462c 100644 --- a/pkg/integration/components/runner.go +++ b/pkg/integration/components/runner.go @@ -48,7 +48,7 @@ func RunTests(args RunTestArgs) error { } for _, test := range args.Tests { - args.TestWrapper(test, func() error { //nolint: thelper + args.TestWrapper(test, func() error { paths := NewPaths( filepath.Join(testDir, test.Name()), ) From 0471dbaa84604691f65d3e8c5ad527f83b5150b1 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Mon, 30 Jun 2025 11:03:00 +0200 Subject: [PATCH 11/13] Enable intrange linter, and fix warnings --- .golangci.yml | 1 + pkg/commands/git_cmd_obj_runner.go | 4 ++-- pkg/commands/oscommands/os.go | 2 +- pkg/commands/patch/patch.go | 2 +- pkg/commands/patch/patch_builder.go | 2 +- pkg/config/user_config_validation.go | 2 +- pkg/gui/context/list_renderer_test.go | 4 ++-- pkg/gui/controllers/workspace_reset_controller.go | 6 +++--- pkg/gui/presentation/graph/graph.go | 2 +- pkg/gui/presentation/graph/graph_test.go | 2 +- .../components/commit_description_panel_driver.go | 2 +- pkg/integration/components/runner.go | 2 +- pkg/integration/components/shell.go | 8 ++++---- pkg/integration/components/view_driver.go | 10 +++++----- pkg/integration/tests/filter_by_author/shared.go | 2 +- pkg/jsonschema/generate.go | 4 ++-- pkg/snake/snake.go | 4 ++-- pkg/utils/formatting.go | 2 +- pkg/utils/search.go | 2 +- pkg/utils/thread_safe_map_test.go | 4 ++-- pkg/utils/yaml_utils/yaml_utils.go | 2 +- 21 files changed, 35 insertions(+), 34 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index cbd7de85d..ecc8193e2 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -5,6 +5,7 @@ linters: enable: - copyloopvar - exhaustive + - intrange - makezero - nakedret - nolintlint diff --git a/pkg/commands/git_cmd_obj_runner.go b/pkg/commands/git_cmd_obj_runner.go index 302547d41..fd98bc84f 100644 --- a/pkg/commands/git_cmd_obj_runner.go +++ b/pkg/commands/git_cmd_obj_runner.go @@ -28,7 +28,7 @@ func (self *gitCmdObjRunner) Run(cmdObj *oscommands.CmdObj) error { func (self *gitCmdObjRunner) RunWithOutput(cmdObj *oscommands.CmdObj) (string, error) { var output string var err error - for i := 0; i < RetryCount; i++ { + for range RetryCount { newCmdObj := cmdObj.Clone() output, err = self.innerRunner.RunWithOutput(newCmdObj) @@ -47,7 +47,7 @@ func (self *gitCmdObjRunner) RunWithOutput(cmdObj *oscommands.CmdObj) (string, e func (self *gitCmdObjRunner) RunWithOutputs(cmdObj *oscommands.CmdObj) (string, string, error) { var stdout, stderr string var err error - for i := 0; i < RetryCount; i++ { + for range RetryCount { newCmdObj := cmdObj.Clone() stdout, stderr, err = self.innerRunner.RunWithOutputs(newCmdObj) diff --git a/pkg/commands/oscommands/os.go b/pkg/commands/oscommands/os.go index 2443e8c35..53e4f3c3d 100644 --- a/pkg/commands/oscommands/os.go +++ b/pkg/commands/oscommands/os.go @@ -222,7 +222,7 @@ func (c *OSCommand) PipeCommands(cmdObjs ...*CmdObj) error { c.LogCommand(logCmdStr, true) - for i := 0; i < len(cmds)-1; i++ { + for i := range len(cmds) - 1 { stdout, err := cmds[i].StdoutPipe() if err != nil { return err diff --git a/pkg/commands/patch/patch.go b/pkg/commands/patch/patch.go index 5e4f9a846..f5efe95da 100644 --- a/pkg/commands/patch/patch.go +++ b/pkg/commands/patch/patch.go @@ -56,7 +56,7 @@ func (self *Patch) HunkStartIdx(hunkIndex int) int { hunkIndex = lo.Clamp(hunkIndex, 0, len(self.hunks)-1) result := len(self.header) - for i := 0; i < hunkIndex; i++ { + for i := range hunkIndex { result += self.hunks[i].lineCount() } return result diff --git a/pkg/commands/patch/patch_builder.go b/pkg/commands/patch/patch_builder.go index 5ef81c72e..1c6fe286e 100644 --- a/pkg/commands/patch/patch_builder.go +++ b/pkg/commands/patch/patch_builder.go @@ -91,7 +91,7 @@ func (p *PatchBuilder) addFileWhole(info *fileInfo) { // add every line index // TODO: add tests and then use lo.Range to simplify info.includedLineIndices = make([]int, lineCount) - for i := 0; i < lineCount; i++ { + for i := range lineCount { info.includedLineIndices[i] = i } } diff --git a/pkg/config/user_config_validation.go b/pkg/config/user_config_validation.go index a84b70aa7..f46dfca9a 100644 --- a/pkg/config/user_config_validation.go +++ b/pkg/config/user_config_validation.go @@ -56,7 +56,7 @@ func validateKeybindingsRecurse(path string, node any) error { } } } else if value.Kind() == reflect.Slice { - for i := 0; i < value.Len(); i++ { + for i := range value.Len() { if err := validateKeybindingsRecurse( fmt.Sprintf("%s[%d]", path, i), value.Index(i).Interface()); err != nil { return err diff --git a/pkg/gui/context/list_renderer_test.go b/pkg/gui/context/list_renderer_test.go index 9ed47d03f..08af680ff 100644 --- a/pkg/gui/context/list_renderer_test.go +++ b/pkg/gui/context/list_renderer_test.go @@ -257,11 +257,11 @@ func TestListRenderer_ModelIndexToViewIndex_and_back(t *testing.T) { // Need to render first so that it knows the non-model items self.renderLines(-1, -1) - for i := 0; i < len(s.modelIndices); i++ { + for i := range len(s.modelIndices) { assert.Equal(t, s.expectedViewIndices[i], self.ModelIndexToViewIndex(s.modelIndices[i])) } - for i := 0; i < len(s.viewIndices); i++ { + for i := range len(s.viewIndices) { assert.Equal(t, s.expectedModelIndices[i], self.ViewIndexToModelIndex(s.viewIndices[i])) } }) diff --git a/pkg/gui/controllers/workspace_reset_controller.go b/pkg/gui/controllers/workspace_reset_controller.go index 3a2abc0d3..7ecf79c78 100644 --- a/pkg/gui/controllers/workspace_reset_controller.go +++ b/pkg/gui/controllers/workspace_reset_controller.go @@ -180,7 +180,7 @@ func (self *FilesController) Explode(v *gocui.View, onDone func()) { self.c.OnWorker(func(_ gocui.Task) error { max := 25 - for i := 0; i < max; i++ { + for i := range max { image := getExplodeImage(width, height, i, max) style := styles[(i*len(styles)/max)%len(styles)] coloredImage := style.Sprint(image) @@ -229,8 +229,8 @@ func getExplodeImage(width int, height int, frame int, max int) string { innerRadius = (progress - 0.5) * 2 * maxRadius } - for y := 0; y < height; y++ { - for x := 0; x < width; x++ { + for y := range height { + for x := range width { // calculate distance from center, scale x by 2 to compensate for character aspect ratio distance := math.Hypot(float64(x-centerX), float64(y-centerY)*2) diff --git a/pkg/gui/presentation/graph/graph.go b/pkg/gui/presentation/graph/graph.go index 4e204c03f..fc33f3135 100644 --- a/pkg/gui/presentation/graph/graph.go +++ b/pkg/gui/presentation/graph/graph.go @@ -79,7 +79,7 @@ func RenderAux(pipeSets [][]Pipe, commits []*models.Commit, selectedCommitHashPt wg := sync.WaitGroup{} wg.Add(maxProcs) - for i := 0; i < maxProcs; i++ { + for i := range maxProcs { go func() { from := i * perProc to := (i + 1) * perProc diff --git a/pkg/gui/presentation/graph/graph_test.go b/pkg/gui/presentation/graph/graph_test.go index 13709267e..e567ec674 100644 --- a/pkg/gui/presentation/graph/graph_test.go +++ b/pkg/gui/presentation/graph/graph_test.go @@ -579,7 +579,7 @@ func generateCommits(hashPool *utils.StringPool, count int) []*models.Commit { parentCount := rnd.Intn(2) + 1 parentHashes := currentCommit.Parents() - for j := 0; j < parentCount; j++ { + for j := range parentCount { reuseParent := rnd.Intn(6) != 1 && j <= len(pool)-1 && j != 0 var newParent *models.Commit if reuseParent { diff --git a/pkg/integration/components/commit_description_panel_driver.go b/pkg/integration/components/commit_description_panel_driver.go index 0aa200757..6bde2cd29 100644 --- a/pkg/integration/components/commit_description_panel_driver.go +++ b/pkg/integration/components/commit_description_panel_driver.go @@ -33,7 +33,7 @@ func (self *CommitDescriptionPanelDriver) AddNewline() *CommitDescriptionPanelDr func (self *CommitDescriptionPanelDriver) GoToBeginning() *CommitDescriptionPanelDriver { numLines := len(self.getViewDriver().getView().BufferLines()) - for i := 0; i < numLines; i++ { + for range numLines { self.t.pressFast("") } diff --git a/pkg/integration/components/runner.go b/pkg/integration/components/runner.go index 7952b462c..f32fde618 100644 --- a/pkg/integration/components/runner.go +++ b/pkg/integration/components/runner.go @@ -53,7 +53,7 @@ func RunTests(args RunTestArgs) error { filepath.Join(testDir, test.Name()), ) - for i := 0; i < args.MaxAttempts; i++ { + for i := range args.MaxAttempts { err := runTest(test, args, paths, projectRootDir, gitVersion) if err != nil { if i == args.MaxAttempts-1 { diff --git a/pkg/integration/components/shell.go b/pkg/integration/components/shell.go index 4a66fc9e3..6b711e5a8 100644 --- a/pkg/integration/components/shell.go +++ b/pkg/integration/components/shell.go @@ -257,7 +257,7 @@ func (self *Shell) CreateNCommitsStartingAt(n, startIndex int) *Shell { // Only to be used in demos, because the list might change and we don't want // tests to break when it does. func (self *Shell) CreateNCommitsWithRandomMessages(n int) *Shell { - for i := 0; i < n; i++ { + for i := range n { file := RandomFiles[i] self.CreateFileAndAdd( file.Name, @@ -286,7 +286,7 @@ func (self *Shell) CreateRepoHistory() *Shell { totalCommits := 0 // Generate commits - for i := 0; i < numInitialCommits; i++ { + for i := range numInitialCommits { author := authors[i%numAuthors] commitMessage := RandomCommitMessages[totalCommits%len(RandomCommitMessages)] @@ -296,7 +296,7 @@ func (self *Shell) CreateRepoHistory() *Shell { } // Generate branches and merges - for i := 0; i < numBranches; i++ { + for i := range numBranches { // We'll have one author creating all the commits in the branch author := authors[i%numAuthors] branchName := RandomBranchNames[i%len(RandomBranchNames)] @@ -309,7 +309,7 @@ func (self *Shell) CreateRepoHistory() *Shell { self.NewBranchFrom(branchName, fmt.Sprintf("master~%d", commitOffset)) numCommitsInBranch := rand.Intn(maxCommitsPerBranch) + 1 - for j := 0; j < numCommitsInBranch; j++ { + for range numCommitsInBranch { commitMessage := RandomCommitMessages[totalCommits%len(RandomCommitMessages)] self.SetAuthor(author, "") diff --git a/pkg/integration/components/view_driver.go b/pkg/integration/components/view_driver.go index 44707289c..ea005d371 100644 --- a/pkg/integration/components/view_driver.go +++ b/pkg/integration/components/view_driver.go @@ -44,7 +44,7 @@ func (self *ViewDriver) Clear() *ViewDriver { // clearing multiple times in case there's multiple lines // (the clear button only clears a single line at a time) maxAttempts := 100 - for i := 0; i < maxAttempts+1; i++ { + for i := range maxAttempts + 1 { if self.getView().Buffer() == "" { break } @@ -104,7 +104,7 @@ func (self *ViewDriver) ContainsLines(matchers ...*TextMatcher) *ViewDriver { startIdx, endIdx := self.getSelectedRange() - for i := 0; i < len(lines)-len(matchers)+1; i++ { + for i := range len(lines) - len(matchers) + 1 { matches := true for j, matcher := range matchers { checkIsSelected, matcher := matcher.checkIsSelected() // strip the IsSelected matcher out @@ -375,11 +375,11 @@ func (self *ViewDriver) Focus() *ViewDriver { currentViewName := self.t.gui.CurrentContext().GetViewName() currentViewTabIndex := lo.IndexOf(window.viewNames, currentViewName) if tabIndex > currentViewTabIndex { - for i := 0; i < tabIndex-currentViewTabIndex; i++ { + for range tabIndex - currentViewTabIndex { self.t.press(self.t.keys.Universal.NextTab) } } else if tabIndex < currentViewTabIndex { - for i := 0; i < currentViewTabIndex-tabIndex; i++ { + for range currentViewTabIndex - tabIndex { self.t.press(self.t.keys.Universal.PrevTab) } } @@ -534,7 +534,7 @@ func (self *ViewDriver) NavigateToLine(matcher *TextMatcher) *ViewDriver { keyPress = func() { self.SelectPreviousItem() } } - for i := 0; i < maxNumKeyPresses; i++ { + for range maxNumKeyPresses { keyPress() idx := self.getSelectedLineIdx() // It is important to use view.BufferLines() here and not lines, because it diff --git a/pkg/integration/tests/filter_by_author/shared.go b/pkg/integration/tests/filter_by_author/shared.go index 160bde1c0..22d08ad5c 100644 --- a/pkg/integration/tests/filter_by_author/shared.go +++ b/pkg/integration/tests/filter_by_author/shared.go @@ -18,7 +18,7 @@ func commonSetup(shell *Shell) { repoStartDaysAgo := 100 for _, authorInfo := range authors { - for i := 0; i < authorInfo.numberOfCommits; i++ { + for i := range authorInfo.numberOfCommits { authorEmail := strings.ToLower(strings.ReplaceAll(authorInfo.name, " ", ".")) + "@email.com" commitMessage := fmt.Sprintf("commit %d", i) diff --git a/pkg/jsonschema/generate.go b/pkg/jsonschema/generate.go index d8514e3b6..5350ca46c 100644 --- a/pkg/jsonschema/generate.go +++ b/pkg/jsonschema/generate.go @@ -114,7 +114,7 @@ func setDefaultVals(rootSchema, schema *jsonschema.Schema, defaults any) { return } - for i := 0; i < t.NumField(); i++ { + for i := range t.NumField() { value := v.Field(i).Interface() parentKey := t.Field(i).Name @@ -152,7 +152,7 @@ func isZeroValue(v any) bool { case reflect.Ptr, reflect.Interface: return rv.IsNil() case reflect.Struct: - for i := 0; i < rv.NumField(); i++ { + for i := range rv.NumField() { if !isZeroValue(rv.Field(i).Interface()) { return false } diff --git a/pkg/snake/snake.go b/pkg/snake/snake.go index 68feec15c..62fc0ddfd 100644 --- a/pkg/snake/snake.go +++ b/pkg/snake/snake.go @@ -129,7 +129,7 @@ func (self *Game) newFoodPos(snakePositions []Position) Position { // arbitrarily setting a limit of attempts to place food attemptLimit := 1000 - for i := 0; i < attemptLimit; i++ { + for range attemptLimit { newFoodPos := Position{self.randIntFn(self.width), self.randIntFn(self.height)} if !lo.Contains(snakePositions, newFoodPos) { @@ -183,7 +183,7 @@ func (self *Game) getCells(state State) [][]CellType { cells[pos.y][pos.x] = value } - for i := 0; i < self.height; i++ { + for i := range self.height { cells[i] = make([]CellType, self.width) } diff --git a/pkg/utils/formatting.go b/pkg/utils/formatting.go index b13a2ffa8..08cc7d49a 100644 --- a/pkg/utils/formatting.go +++ b/pkg/utils/formatting.go @@ -25,7 +25,7 @@ type ColumnConfig struct { func StringWidth(s string) int { // We are intentionally not using a range loop here, because that would // convert the characters to runes, which is unnecessary work in this case. - for i := 0; i < len(s); i++ { + for i := range len(s) { if s[i] > unicode.MaxASCII { return runewidth.StringWidth(s) } diff --git a/pkg/utils/search.go b/pkg/utils/search.go index 4ec26bc22..c96cda4ab 100644 --- a/pkg/utils/search.go +++ b/pkg/utils/search.go @@ -41,7 +41,7 @@ func FindSubstringsFrom(pattern string, data fuzzy.Source) fuzzy.Matches { result := fuzzy.Matches{} outer: - for i := 0; i < data.Len(); i++ { + for i := range data.Len() { s := data.String(i) for _, sub := range substrings { if !CaseAwareContains(s, sub) { diff --git a/pkg/utils/thread_safe_map_test.go b/pkg/utils/thread_safe_map_test.go index 9676cfe5f..768aa392c 100644 --- a/pkg/utils/thread_safe_map_test.go +++ b/pkg/utils/thread_safe_map_test.go @@ -48,12 +48,12 @@ func TestThreadSafeMapConcurrentReadWrite(t *testing.T) { m := NewThreadSafeMap[int, int]() go func() { - for i := 0; i < 10000; i++ { + for range 10000 { m.Set(0, 0) } }() - for i := 0; i < 10000; i++ { + for range 10000 { m.Get(0) } } diff --git a/pkg/utils/yaml_utils/yaml_utils.go b/pkg/utils/yaml_utils/yaml_utils.go index 432915f5e..f8f7f0679 100644 --- a/pkg/utils/yaml_utils/yaml_utils.go +++ b/pkg/utils/yaml_utils/yaml_utils.go @@ -139,7 +139,7 @@ func walk(node *yaml.Node, path string, callback func(*yaml.Node, string)) error } } case yaml.SequenceNode: - for i := 0; i < len(node.Content); i++ { + for i := range len(node.Content) { childPath := fmt.Sprintf("%s[%d]", path, i) err := walk(node.Content[i], childPath, callback) if err != nil { From 7aa426fa71007c601ce2305d53719f3fbc8bcfdf Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Mon, 30 Jun 2025 11:11:35 +0200 Subject: [PATCH 12/13] Enable errorlint linter, and fix warnings --- .golangci.yml | 1 + pkg/commands/git_config/get_key.go | 4 +++- pkg/config/app_config.go | 12 ++++++------ pkg/gui/controllers/commit_message_controller.go | 2 +- pkg/gui/gui.go | 9 ++++----- pkg/integration/clients/tui.go | 6 ++---- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index ecc8193e2..b2329171f 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -4,6 +4,7 @@ run: linters: enable: - copyloopvar + - errorlint - exhaustive - intrange - makezero diff --git a/pkg/commands/git_config/get_key.go b/pkg/commands/git_config/get_key.go index cd5a678ef..7369fa08e 100644 --- a/pkg/commands/git_config/get_key.go +++ b/pkg/commands/git_config/get_key.go @@ -2,6 +2,7 @@ package git_config import ( "bytes" + "errors" "fmt" "io" "os/exec" @@ -39,7 +40,8 @@ func runGitConfigCmd(cmd *exec.Cmd) (string, error) { cmd.Stderr = io.Discard err := cmd.Run() - if exitError, ok := err.(*exec.ExitError); ok { + var exitError *exec.ExitError + if errors.As(err, &exitError) { if waitStatus, ok := exitError.Sys().(syscall.WaitStatus); ok { if waitStatus.ExitStatus() == 1 { return "", fmt.Errorf("the key is not found for %s", cmd.Args) diff --git a/pkg/config/app_config.go b/pkg/config/app_config.go index 5d6b5e219..90c6c1013 100644 --- a/pkg/config/app_config.go +++ b/pkg/config/app_config.go @@ -288,7 +288,7 @@ func computeMigratedConfig(path string, content []byte, changes *ChangesSet) ([] for _, pathToReplace := range pathsToReplace { err, didReplace := yaml_utils.RenameYamlKey(&rootNode, pathToReplace.oldPath, pathToReplace.newName) if err != nil { - return nil, false, fmt.Errorf("Couldn't migrate config file at `%s` for key %s: %s", path, strings.Join(pathToReplace.oldPath, "."), err) + return nil, false, fmt.Errorf("Couldn't migrate config file at `%s` for key %s: %w", path, strings.Join(pathToReplace.oldPath, "."), err) } if didReplace { changes.Add(fmt.Sprintf("Renamed '%s' to '%s'", strings.Join(pathToReplace.oldPath, "."), pathToReplace.newName)) @@ -297,27 +297,27 @@ func computeMigratedConfig(path string, content []byte, changes *ChangesSet) ([] err = changeNullKeybindingsToDisabled(&rootNode, changes) if err != nil { - return nil, false, fmt.Errorf("Couldn't migrate config file at `%s`: %s", path, err) + return nil, false, fmt.Errorf("Couldn't migrate config file at `%s`: %w", path, err) } err = changeElementToSequence(&rootNode, []string{"git", "commitPrefix"}, changes) if err != nil { - return nil, false, fmt.Errorf("Couldn't migrate config file at `%s`: %s", path, err) + return nil, false, fmt.Errorf("Couldn't migrate config file at `%s`: %w", path, err) } err = changeCommitPrefixesMap(&rootNode, changes) if err != nil { - return nil, false, fmt.Errorf("Couldn't migrate config file at `%s`: %s", path, err) + return nil, false, fmt.Errorf("Couldn't migrate config file at `%s`: %w", path, err) } err = changeCustomCommandStreamAndOutputToOutputEnum(&rootNode, changes) if err != nil { - return nil, false, fmt.Errorf("Couldn't migrate config file at `%s`: %s", path, err) + return nil, false, fmt.Errorf("Couldn't migrate config file at `%s`: %w", path, err) } err = migrateAllBranchesLogCmd(&rootNode, changes) if err != nil { - return nil, false, fmt.Errorf("Couldn't migrate config file at `%s`: %s", path, err) + return nil, false, fmt.Errorf("Couldn't migrate config file at `%s`: %w", path, err) } // Add more migrations here... diff --git a/pkg/gui/controllers/commit_message_controller.go b/pkg/gui/controllers/commit_message_controller.go index b72d5d45a..6f96cdd21 100644 --- a/pkg/gui/controllers/commit_message_controller.go +++ b/pkg/gui/controllers/commit_message_controller.go @@ -153,7 +153,7 @@ func (self *CommitMessageController) handleCommitIndexChange(value int) error { func (self *CommitMessageController) setCommitMessageAtIndex(index int) (bool, error) { commitMessage, err := self.c.Git().Commit.GetCommitMessageFromHistory(index) if err != nil { - if err == git_commands.ErrInvalidCommitIndex { + if errors.Is(err, git_commands.ErrInvalidCommitIndex) { return false, nil } return false, errors.New(self.c.Tr.CommitWithoutMessageErr) diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index 84ab86a62..2f65cde8c 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -2,6 +2,7 @@ package gui import ( goContext "context" + "errors" "fmt" "io" "os" @@ -872,8 +873,7 @@ func (gui *Gui) RunAndHandleError(startArgs appTypes.StartArgs) error { close(gui.stopChan) - switch err { - case gocui.ErrQuit: + if errors.Is(err, gocui.ErrQuit) { if gui.c.State().GetRetainOriginalDir() { if err := gui.helpers.RecordDirectory.RecordDirectory(gui.InitialDir); err != nil { return err @@ -885,10 +885,9 @@ func (gui *Gui) RunAndHandleError(startArgs appTypes.StartArgs) error { } return nil - - default: - return err } + + return err } return nil diff --git a/pkg/integration/clients/tui.go b/pkg/integration/clients/tui.go index f93644597..992f107e8 100644 --- a/pkg/integration/clients/tui.go +++ b/pkg/integration/clients/tui.go @@ -214,12 +214,10 @@ func RunTUI(raceDetector bool) { err = g.MainLoop() g.Close() - switch err { - case gocui.ErrQuit: + if errors.Is(err, gocui.ErrQuit) { return - default: - log.Panicln(err) } + log.Panicln(err) } type app struct { From ca05a2cceae9b42003f80aaec44c38c032c3fda6 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Mon, 30 Jun 2025 19:13:12 +0200 Subject: [PATCH 13/13] Enable revive linter, and fix a bunch of warnings I took the set of enabled checks from revive's recommended configuration [1], and removed some that I didn't like. There might be other useful checks in revive that we might want to enable, but this is a nice improvement already. The bulk of the changes here are removing unnecessary else statements after returns, but there are a few others too. [1] https://github.com/mgechev/revive?tab=readme-ov-file#recommended-configuration --- .golangci.yml | 15 +++++ pkg/app/app.go | 4 +- pkg/app/daemon/rebase.go | 3 +- pkg/commands/git_commands/branch_loader.go | 3 +- pkg/commands/git_commands/commit.go | 3 +- pkg/commands/git_commands/deps_test.go | 2 +- .../git_commands/git_command_builder.go | 3 +- pkg/commands/git_commands/rebase.go | 11 ++-- pkg/commands/git_commands/repo_paths.go | 2 +- pkg/commands/git_commands/repo_paths_test.go | 4 +- pkg/commands/git_commands/submodule.go | 3 +- pkg/commands/git_commands/working_tree.go | 3 +- .../hosting_service/hosting_service.go | 3 +- pkg/commands/patch/patch_builder.go | 3 +- pkg/commands/patch/transform.go | 4 +- pkg/gui/context/menu_context.go | 2 +- pkg/gui/context/suggestions_context.go | 3 +- pkg/gui/context/traits/list_cursor.go | 3 +- pkg/gui/context_config.go | 4 +- pkg/gui/controllers/bisect_controller.go | 11 ++-- pkg/gui/controllers/branches_controller.go | 16 +++--- .../custom_patch_options_menu_action.go | 4 +- pkg/gui/controllers/files_controller.go | 7 +-- pkg/gui/controllers/helpers/gpg_helper.go | 4 +- .../helpers/merge_and_rebase_helper.go | 3 +- pkg/gui/controllers/helpers/refs_helper.go | 4 +- .../helpers/window_arrangement_helper.go | 57 +++++++++---------- .../helpers/working_tree_helper.go | 4 +- .../controllers/helpers/worktree_helper.go | 32 +++++------ pkg/gui/controllers/sync_controller.go | 36 ++++++------ pkg/gui/filetree/file_tree_view_model.go | 3 +- pkg/gui/gui.go | 4 +- pkg/gui/information_panel.go | 4 +- pkg/gui/keybindings/keybindings.go | 3 +- pkg/gui/mergeconflicts/merge_conflict.go | 6 +- pkg/gui/patch_exploring/focus.go | 6 +- pkg/gui/patch_exploring/state.go | 3 +- pkg/gui/presentation/commits.go | 6 +- pkg/gui/presentation/files.go | 3 +- pkg/gui/presentation/graph/cell.go | 4 +- pkg/gui/presentation/graph/graph.go | 3 +- pkg/tasks/tasks.go | 2 +- pkg/tasks/tasks_test.go | 2 +- pkg/utils/formatting.go | 6 +- pkg/utils/once_writer_test.go | 2 +- pkg/utils/utils.go | 3 +- pkg/utils/yaml_utils/yaml_utils_test.go | 6 +- 47 files changed, 152 insertions(+), 170 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index b2329171f..6a02b1dc5 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -11,6 +11,7 @@ linters: - nakedret - nolintlint - prealloc + - revive - thelper - tparallel - unconvert @@ -76,6 +77,20 @@ linters: dot-import-whitelist: - github.com/jesseduffield/lazygit/pkg/integration/components + revive: + severity: warning + rules: + - name: atomic + - name: context-as-argument + - name: context-keys-type + - name: error-naming + - name: var-declaration + - name: package-comments + - name: range + - name: time-naming + - name: indent-error-flow + - name: errorf + - name: superfluous-else exclusions: generated: lax presets: diff --git a/pkg/app/app.go b/pkg/app/app.go index 8d1d1568c..ad0d487ec 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -86,9 +86,9 @@ func newLogger(cfg config.AppConfigurer) *logrus.Entry { log.Fatal(err) } return logs.NewDevelopmentLogger(logPath) - } else { - return logs.NewProductionLogger() } + + return logs.NewProductionLogger() } // NewApp bootstrap a new application diff --git a/pkg/app/daemon/rebase.go b/pkg/app/daemon/rebase.go index 30740d09c..1cb3b844f 100644 --- a/pkg/app/daemon/rebase.go +++ b/pkg/app/daemon/rebase.go @@ -21,9 +21,8 @@ type TodoLine struct { func (self *TodoLine) ToString() string { if self.Action == "break" { return self.Action + "\n" - } else { - return self.Action + " " + self.Commit.Hash() + " " + self.Commit.Name + "\n" } + return self.Action + " " + self.Commit.Hash() + " " + self.Commit.Name + "\n" } func TodoLinesToString(todoLines []TodoLine) string { diff --git a/pkg/commands/git_commands/branch_loader.go b/pkg/commands/git_commands/branch_loader.go index 798a2ebef..73127ae63 100644 --- a/pkg/commands/git_commands/branch_loader.go +++ b/pkg/commands/git_commands/branch_loader.go @@ -356,9 +356,8 @@ func parseDifference(track string, regexStr string) string { match := re.FindStringSubmatch(track) if len(match) > 1 { return match[1] - } else { - return "0" } + return "0" } // TODO: only look at the new reflog commits, and otherwise store the recencies in diff --git a/pkg/commands/git_commands/commit.go b/pkg/commands/git_commands/commit.go index adf7dcf19..3568dbb33 100644 --- a/pkg/commands/git_commands/commit.go +++ b/pkg/commands/git_commands/commit.go @@ -149,9 +149,8 @@ func (self *CommitCommands) CommitEditorCmdObj() *oscommands.CmdObj { func (self *CommitCommands) signoffFlag() string { if self.UserConfig().Git.Commit.SignOff { return "--signoff" - } else { - return "" } + return "" } func (self *CommitCommands) GetCommitMessage(commitHash string) (string, error) { diff --git a/pkg/commands/git_commands/deps_test.go b/pkg/commands/git_commands/deps_test.go index bb079c063..a8fff5edd 100644 --- a/pkg/commands/git_commands/deps_test.go +++ b/pkg/commands/git_commands/deps_test.go @@ -97,7 +97,7 @@ func buildGitCommon(deps commonDeps) *GitCommon { func buildRepo() *gogit.Repository { // TODO: think of a way to actually mock this out - var repo *gogit.Repository = nil + var repo *gogit.Repository return repo } diff --git a/pkg/commands/git_commands/git_command_builder.go b/pkg/commands/git_commands/git_command_builder.go index a7edc144c..5e9c3b258 100644 --- a/pkg/commands/git_commands/git_command_builder.go +++ b/pkg/commands/git_commands/git_command_builder.go @@ -32,9 +32,8 @@ func (self *GitCommandBuilder) ArgIf(condition bool, ifTrue ...string) *GitComma func (self *GitCommandBuilder) ArgIfElse(condition bool, ifTrue string, ifFalse string) *GitCommandBuilder { if condition { return self.Arg(ifTrue) - } else { - return self.Arg(ifFalse) } + return self.Arg(ifFalse) } func (self *GitCommandBuilder) Config(value string) *GitCommandBuilder { diff --git a/pkg/commands/git_commands/rebase.go b/pkg/commands/git_commands/rebase.go index f6302fc28..8c52dc62f 100644 --- a/pkg/commands/git_commands/rebase.go +++ b/pkg/commands/git_commands/rebase.go @@ -327,9 +327,8 @@ func (self *RebaseCommands) MoveFixupCommitDown(commits []*models.Commit, target func todoFromCommit(commit *models.Commit) utils.Todo { if commit.Action == todo.UpdateRef { return utils.Todo{Ref: commit.Name} - } else { - return utils.Todo{Hash: commit.Hash()} } + return utils.Todo{Hash: commit.Hash()} } // Sets the action for the given commits in the git-rebase-todo file @@ -412,9 +411,9 @@ func (self *RebaseCommands) BeginInteractiveRebaseForCommit( instruction: daemon.NewInsertBreakInstruction(), keepCommitsThatBecomeEmpty: keepCommitsThatBecomeEmpty, }).Run() - } else { - return self.BeginInteractiveRebaseForCommitRange(commits, commitIndex, commitIndex, keepCommitsThatBecomeEmpty) } + + return self.BeginInteractiveRebaseForCommitRange(commits, commitIndex, commitIndex, keepCommitsThatBecomeEmpty) } func (self *RebaseCommands) BeginInteractiveRebaseForCommitRange( @@ -574,7 +573,7 @@ func getBaseHashOrRoot(commits []*models.Commit, index int) string { // at time of writing) if index < len(commits) { return commits[index].Hash() - } else { - return "--root" } + + return "--root" } diff --git a/pkg/commands/git_commands/repo_paths.go b/pkg/commands/git_commands/repo_paths.go index a355a45ba..543ab5cd0 100644 --- a/pkg/commands/git_commands/repo_paths.go +++ b/pkg/commands/git_commands/repo_paths.go @@ -21,7 +21,7 @@ type RepoPaths struct { isBareRepo bool } -var gitPathFormatVersion GitVersion = GitVersion{2, 31, 0, ""} +var gitPathFormatVersion = GitVersion{2, 31, 0, ""} // Path to the current worktree. If we're in the main worktree, this will // be the same as RepoPath() diff --git a/pkg/commands/git_commands/repo_paths_test.go b/pkg/commands/git_commands/repo_paths_test.go index 77f451671..2d02a9ed3 100644 --- a/pkg/commands/git_commands/repo_paths_test.go +++ b/pkg/commands/git_commands/repo_paths_test.go @@ -184,9 +184,7 @@ func TestGetRepoPaths(t *testing.T) { Expected: nil, Err: func(getRevParseArgs argFn) error { args := strings.Join(getRevParseArgs(), " ") - return errors.New( - fmt.Sprintf("'git %v --show-toplevel --absolute-git-dir --git-common-dir --is-bare-repository --show-superproject-working-tree' failed: fatal: invalid gitfile format: /path/to/repo/worktree2/.git", args), - ) + return fmt.Errorf("'git %v --show-toplevel --absolute-git-dir --git-common-dir --is-bare-repository --show-superproject-working-tree' failed: fatal: invalid gitfile format: /path/to/repo/worktree2/.git", args) }, }, } diff --git a/pkg/commands/git_commands/submodule.go b/pkg/commands/git_commands/submodule.go index fbe4802c4..f06e10134 100644 --- a/pkg/commands/git_commands/submodule.go +++ b/pkg/commands/git_commands/submodule.go @@ -49,9 +49,8 @@ func (self *SubmoduleCommands) GetConfigs(parentModule *models.SubmoduleConfig) if len(matches) > 0 { return matches[1], true - } else { - return "", false } + return "", false } configs := []*models.SubmoduleConfig{} diff --git a/pkg/commands/git_commands/working_tree.go b/pkg/commands/git_commands/working_tree.go index 8ba9b196d..a5faa801b 100644 --- a/pkg/commands/git_commands/working_tree.go +++ b/pkg/commands/git_commands/working_tree.go @@ -66,9 +66,8 @@ func (self *WorkingTreeCommands) UnstageAll() error { func (self *WorkingTreeCommands) UnStageFile(paths []string, tracked bool) error { if tracked { return self.UnstageTrackedFiles(paths) - } else { - return self.UnstageUntrackedFiles(paths) } + return self.UnstageUntrackedFiles(paths) } func (self *WorkingTreeCommands) UnstageTrackedFiles(paths []string) error { diff --git a/pkg/commands/hosting_service/hosting_service.go b/pkg/commands/hosting_service/hosting_service.go index 2e913b654..1c328fd0d 100644 --- a/pkg/commands/hosting_service/hosting_service.go +++ b/pkg/commands/hosting_service/hosting_service.go @@ -46,9 +46,8 @@ func (self *HostingServiceMgr) GetPullRequestURL(from string, to string) (string if to == "" { return gitService.getPullRequestURLIntoDefaultBranch(url.QueryEscape(from)), nil - } else { - return gitService.getPullRequestURLIntoTargetBranch(url.QueryEscape(from), url.QueryEscape(to)), nil } + return gitService.getPullRequestURLIntoTargetBranch(url.QueryEscape(from), url.QueryEscape(to)), nil } func (self *HostingServiceMgr) GetCommitURL(commitHash string) (string, error) { diff --git a/pkg/commands/patch/patch_builder.go b/pkg/commands/patch/patch_builder.go index 1c6fe286e..3fc8ebcf7 100644 --- a/pkg/commands/patch/patch_builder.go +++ b/pkg/commands/patch/patch_builder.go @@ -211,9 +211,8 @@ func (p *PatchBuilder) RenderPatchForFile(opts RenderPatchForFileOpts) string { if opts.Plain { return patch.FormatPlain() - } else { - return patch.FormatView(FormatViewOpts{}) } + return patch.FormatView(FormatViewOpts{}) } func (p *PatchBuilder) renderEachFilePatch(plain bool) []string { diff --git a/pkg/commands/patch/transform.go b/pkg/commands/patch/transform.go index db35bb4a1..4cd4c0207 100644 --- a/pkg/commands/patch/transform.go +++ b/pkg/commands/patch/transform.go @@ -84,9 +84,9 @@ func (self *patchTransformer) transformHeader() []string { result = append(result, line) } return result - } else { - return self.patch.header } + + return self.patch.header } func (self *patchTransformer) transformHunks() []*Hunk { diff --git a/pkg/gui/context/menu_context.go b/pkg/gui/context/menu_context.go index 26425af3d..3d5937a9d 100644 --- a/pkg/gui/context/menu_context.go +++ b/pkg/gui/context/menu_context.go @@ -144,7 +144,7 @@ func (self *MenuViewModel) GetNonModelItems() []*NonModelItem { } menuItems := self.FilteredListViewModel.GetItems() - var prevSection *types.MenuSection = nil + var prevSection *types.MenuSection for i, menuItem := range menuItems { if menuItem.Section != nil && menuItem.Section != prevSection { if prevSection != nil { diff --git a/pkg/gui/context/suggestions_context.go b/pkg/gui/context/suggestions_context.go index 9e3b8ba95..45364b3b5 100644 --- a/pkg/gui/context/suggestions_context.go +++ b/pkg/gui/context/suggestions_context.go @@ -79,9 +79,8 @@ func (self *SuggestionsContext) RefreshSuggestions() { if findSuggestionsFn != nil { suggestions := findSuggestionsFn(self.c.GetPromptInput()) return func() { self.SetSuggestions(suggestions) } - } else { - return func() {} } + return func() {} }) } diff --git a/pkg/gui/context/traits/list_cursor.go b/pkg/gui/context/traits/list_cursor.go index a8ff89716..c471d9a0f 100644 --- a/pkg/gui/context/traits/list_cursor.go +++ b/pkg/gui/context/traits/list_cursor.go @@ -77,9 +77,8 @@ func (self *ListCursor) SetSelectionRangeAndMode(selectedIdx, rangeStartIdx int, func (self *ListCursor) GetSelectionRangeAndMode() (int, int, RangeSelectMode) { if self.IsSelectingRange() { return self.selectedIdx, self.rangeStartIdx, self.rangeSelectMode - } else { - return self.selectedIdx, self.selectedIdx, self.rangeSelectMode } + return self.selectedIdx, self.selectedIdx, self.rangeSelectMode } func (self *ListCursor) clampValue(value int) int { diff --git a/pkg/gui/context_config.go b/pkg/gui/context_config.go index 748482a35..e1b35c492 100644 --- a/pkg/gui/context_config.go +++ b/pkg/gui/context_config.go @@ -24,7 +24,7 @@ func OnFocusWrapper(f func() error) func(opts types.OnFocusOpts) error { func (gui *Gui) defaultSideContext() types.Context { if gui.State.Modes.Filtering.Active() { return gui.State.Contexts.LocalCommits - } else { - return gui.State.Contexts.Files } + + return gui.State.Contexts.Files } diff --git a/pkg/gui/controllers/bisect_controller.go b/pkg/gui/controllers/bisect_controller.go index 0cd8d1d0b..401550c98 100644 --- a/pkg/gui/controllers/bisect_controller.go +++ b/pkg/gui/controllers/bisect_controller.go @@ -54,9 +54,8 @@ func (self *BisectController) openMenu(commit *models.Commit) error { info := self.c.Git().Bisect.GetInfo() if info.Started() { return self.openMidBisectMenu(info, commit) - } else { - return self.openStartBisectMenu(info, commit) } + return self.openStartBisectMenu(info, commit) } func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, commit *models.Commit) error { @@ -280,11 +279,11 @@ func (self *BisectController) afterBisectMarkRefresh(selectCurrent bool, waitToR if waitToReselect { return self.c.Refresh(types.RefreshOptions{Mode: types.SYNC, Scope: []types.RefreshableView{}, Then: selectFn}) - } else { - _ = selectFn() - - return self.c.Helpers().Bisect.PostBisectCommandRefresh() } + + _ = selectFn() + + return self.c.Helpers().Bisect.PostBisectCommandRefresh() } func (self *BisectController) selectCurrentBisectCommit() { diff --git a/pkg/gui/controllers/branches_controller.go b/pkg/gui/controllers/branches_controller.go index 4b5318dcb..528bfcf49 100644 --- a/pkg/gui/controllers/branches_controller.go +++ b/pkg/gui/controllers/branches_controller.go @@ -657,15 +657,15 @@ func (self *BranchesController) fastForward(branch *models.Branch) error { ) _ = self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC}) return err - } else { - self.c.LogAction(action) - - err := self.c.Git().Sync.FastForward( - task, branch.Name, branch.UpstreamRemote, branch.UpstreamBranch, - ) - _ = self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.BRANCHES}}) - return err } + + self.c.LogAction(action) + + err := self.c.Git().Sync.FastForward( + task, branch.Name, branch.UpstreamRemote, branch.UpstreamBranch, + ) + _ = self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.BRANCHES}}) + return err }) } diff --git a/pkg/gui/controllers/custom_patch_options_menu_action.go b/pkg/gui/controllers/custom_patch_options_menu_action.go index 92b77f514..d83228793 100644 --- a/pkg/gui/controllers/custom_patch_options_menu_action.go +++ b/pkg/gui/controllers/custom_patch_options_menu_action.go @@ -189,9 +189,9 @@ func (self *CustomPatchOptionsMenuAction) handleMovePatchIntoWorkingTree() error }) return nil - } else { - return pull(false) } + + return pull(false) } func (self *CustomPatchOptionsMenuAction) handlePullPatchIntoNewCommit() error { diff --git a/pkg/gui/controllers/files_controller.go b/pkg/gui/controllers/files_controller.go index 0c8db786f..ab5b6e277 100644 --- a/pkg/gui/controllers/files_controller.go +++ b/pkg/gui/controllers/files_controller.go @@ -901,11 +901,10 @@ func (self *FilesController) setStatusFiltering(filter filetree.FileTreeDisplayF // because the untracked files filter applies when running `git status`. if previousFilter != filter && (previousFilter == filetree.DisplayUntracked || filter == filetree.DisplayUntracked) { return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.FILES}, Mode: types.ASYNC}) - } else { - self.c.PostRefreshUpdate(self.context()) - - return nil } + + self.c.PostRefreshUpdate(self.context()) + return nil } func (self *FilesController) edit(nodes []*filetree.FileNode) error { diff --git a/pkg/gui/controllers/helpers/gpg_helper.go b/pkg/gui/controllers/helpers/gpg_helper.go index 65f226067..aabd6964a 100644 --- a/pkg/gui/controllers/helpers/gpg_helper.go +++ b/pkg/gui/controllers/helpers/gpg_helper.go @@ -37,9 +37,9 @@ func (self *GpgHelper) WithGpgHandling(cmdObj *oscommands.CmdObj, configKey git_ } return err - } else { - return self.runAndStream(cmdObj, waitingStatus, onSuccess, refreshScope) } + + return self.runAndStream(cmdObj, waitingStatus, onSuccess, refreshScope) } func (self *GpgHelper) runAndStream(cmdObj *oscommands.CmdObj, waitingStatus string, onSuccess func() error, refreshScope []types.RefreshableView) error { diff --git a/pkg/gui/controllers/helpers/merge_and_rebase_helper.go b/pkg/gui/controllers/helpers/merge_and_rebase_helper.go index 079e2ab68..bd3cee7b7 100644 --- a/pkg/gui/controllers/helpers/merge_and_rebase_helper.go +++ b/pkg/gui/controllers/helpers/merge_and_rebase_helper.go @@ -162,9 +162,8 @@ func (self *MergeAndRebaseHelper) CheckMergeOrRebaseWithRefreshOptions(result er } else if strings.Contains(result.Error(), "No rebase in progress?") { // assume in this case that we're already done return nil - } else { - return self.CheckForConflicts(result) } + return self.CheckForConflicts(result) } func (self *MergeAndRebaseHelper) CheckMergeOrRebase(result error) error { diff --git a/pkg/gui/controllers/helpers/refs_helper.go b/pkg/gui/controllers/helpers/refs_helper.go index 7a7f29d8e..0222f575c 100644 --- a/pkg/gui/controllers/helpers/refs_helper.go +++ b/pkg/gui/controllers/helpers/refs_helper.go @@ -56,9 +56,9 @@ func (self *RefsHelper) CheckoutRef(ref string, options types.CheckoutRefOptions withCheckoutStatus := func(f func(gocui.Task) error) error { if found { return self.c.WithInlineStatus(localBranch, types.ItemOperationCheckingOut, context.LOCAL_BRANCHES_CONTEXT_KEY, f) - } else { - return self.c.WithWaitingStatus(waitingStatus, f) } + + return self.c.WithWaitingStatus(waitingStatus, f) } return withCheckoutStatus(func(gocui.Task) error { diff --git a/pkg/gui/controllers/helpers/window_arrangement_helper.go b/pkg/gui/controllers/helpers/window_arrangement_helper.go index 393b0ffb1..51c5cf37a 100644 --- a/pkg/gui/controllers/helpers/window_arrangement_helper.go +++ b/pkg/gui/controllers/helpers/window_arrangement_helper.go @@ -385,9 +385,8 @@ func splitMainPanelSideBySide(args WindowArrangementArgs) bool { default: if args.Width < 200 && args.Height > 30 { // 2 80 character width panels + 40 width for side panel return false - } else { - return true } + return true } } @@ -431,11 +430,11 @@ func sidePanelChildren(args WindowArrangementArgs) func(width int, height int) [ Window: window, Weight: 1, } - } else { - return &boxlayout.Box{ - Window: window, - Size: 0, - } + } + + return &boxlayout.Box{ + Window: window, + Size: 0, } } @@ -469,33 +468,33 @@ func sidePanelChildren(args WindowArrangementArgs) func(width int, height int) [ accordionBox(&boxlayout.Box{Window: "commits", Weight: 1}), accordionBox(getDefaultStashWindowBox(args)), } - } else { - squashedHeight := 1 - if height >= 21 { - squashedHeight = 3 - } + } - squashedSidePanelBox := func(window string) *boxlayout.Box { - if window == args.CurrentSideWindow { - return &boxlayout.Box{ - Window: window, - Weight: 1, - } - } else { - return &boxlayout.Box{ - Window: window, - Size: squashedHeight, - } + squashedHeight := 1 + if height >= 21 { + squashedHeight = 3 + } + + squashedSidePanelBox := func(window string) *boxlayout.Box { + if window == args.CurrentSideWindow { + return &boxlayout.Box{ + Window: window, + Weight: 1, } } - return []*boxlayout.Box{ - squashedSidePanelBox("status"), - squashedSidePanelBox("files"), - squashedSidePanelBox("branches"), - squashedSidePanelBox("commits"), - squashedSidePanelBox("stash"), + return &boxlayout.Box{ + Window: window, + Size: squashedHeight, } } + + return []*boxlayout.Box{ + squashedSidePanelBox("status"), + squashedSidePanelBox("files"), + squashedSidePanelBox("branches"), + squashedSidePanelBox("commits"), + squashedSidePanelBox("stash"), + } } } diff --git a/pkg/gui/controllers/helpers/working_tree_helper.go b/pkg/gui/controllers/helpers/working_tree_helper.go index 9bff3dbc7..1e8226363 100644 --- a/pkg/gui/controllers/helpers/working_tree_helper.go +++ b/pkg/gui/controllers/helpers/working_tree_helper.go @@ -245,7 +245,7 @@ func (self *WorkingTreeHelper) commitPrefixConfigsForRepo() []config.CommitPrefi cfg, ok := self.c.UserConfig().Git.CommitPrefixes[self.c.Git().RepoPaths.RepoName()] if ok { return append(cfg, self.c.UserConfig().Git.CommitPrefix...) - } else { - return self.c.UserConfig().Git.CommitPrefix } + + return self.c.UserConfig().Git.CommitPrefix } diff --git a/pkg/gui/controllers/helpers/worktree_helper.go b/pkg/gui/controllers/helpers/worktree_helper.go index 2d6460dcb..ac4e01cf6 100644 --- a/pkg/gui/controllers/helpers/worktree_helper.go +++ b/pkg/gui/controllers/helpers/worktree_helper.go @@ -132,24 +132,24 @@ func (self *WorktreeHelper) NewWorktreeCheckout(base string, canCheckoutBase boo }, }) - return nil - } else { - // prompt for the new branch name where a blank means we just check out the branch - self.c.Prompt(types.PromptOpts{ - Title: self.c.Tr.NewBranchName, - HandleConfirm: func(branchName string) error { - if branchName == "" { - return errors.New(self.c.Tr.BranchNameCannotBeBlank) - } - - opts.Branch = branchName - - return f() - }, - }) - return nil } + + // prompt for the new branch name where a blank means we just check out the branch + self.c.Prompt(types.PromptOpts{ + Title: self.c.Tr.NewBranchName, + HandleConfirm: func(branchName string) error { + if branchName == "" { + return errors.New(self.c.Tr.BranchNameCannotBeBlank) + } + + opts.Branch = branchName + + return f() + }, + }) + + return nil }, }) diff --git a/pkg/gui/controllers/sync_controller.go b/pkg/gui/controllers/sync_controller.go index 66c480b93..c1c79fa35 100644 --- a/pkg/gui/controllers/sync_controller.go +++ b/pkg/gui/controllers/sync_controller.go @@ -92,27 +92,27 @@ func (self *SyncController) push(currentBranch *models.Branch) error { opts := pushOpts{remoteBranchStoredLocally: currentBranch.RemoteBranchStoredLocally()} if currentBranch.IsBehindForPush() { return self.requestToForcePush(currentBranch, opts) - } else { - return self.pushAux(currentBranch, opts) } - } else { - if self.c.Git().Config.GetPushToCurrent() { - return self.pushAux(currentBranch, pushOpts{setUpstream: true}) - } else { - return self.c.Helpers().Upstream.PromptForUpstreamWithInitialContent(currentBranch, func(upstream string) error { - upstreamRemote, upstreamBranch, err := self.c.Helpers().Upstream.ParseUpstream(upstream) - if err != nil { - return err - } - return self.pushAux(currentBranch, pushOpts{ - setUpstream: true, - upstreamRemote: upstreamRemote, - upstreamBranch: upstreamBranch, - }) - }) - } + return self.pushAux(currentBranch, opts) } + + if self.c.Git().Config.GetPushToCurrent() { + return self.pushAux(currentBranch, pushOpts{setUpstream: true}) + } + + return self.c.Helpers().Upstream.PromptForUpstreamWithInitialContent(currentBranch, func(upstream string) error { + upstreamRemote, upstreamBranch, err := self.c.Helpers().Upstream.ParseUpstream(upstream) + if err != nil { + return err + } + + return self.pushAux(currentBranch, pushOpts{ + setUpstream: true, + upstreamRemote: upstreamRemote, + upstreamBranch: upstreamBranch, + }) + }) } func (self *SyncController) pull(currentBranch *models.Branch) error { diff --git a/pkg/gui/filetree/file_tree_view_model.go b/pkg/gui/filetree/file_tree_view_model.go index 470c2ca1c..3db39d0a1 100644 --- a/pkg/gui/filetree/file_tree_view_model.go +++ b/pkg/gui/filetree/file_tree_view_model.go @@ -138,9 +138,8 @@ func (self *FileTreeViewModel) findNewSelectedIdx(prevNodes []*FileNode, currNod } if node.File != nil && node.File.IsRename() { return node.File.Names() - } else { - return []string{node.path} } + return []string{node.path} } for _, prevNode := range prevNodes { diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index 2f65cde8c..f2ea43156 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -611,9 +611,9 @@ func initialScreenMode(startArgs appTypes.StartArgs, config config.AppConfigurer return parseScreenModeArg(startArgs.ScreenMode) } else if startArgs.FilterPath != "" || startArgs.GitArg != appTypes.GitArgNone { return types.SCREEN_HALF - } else { - return parseScreenModeArg(config.GetUserConfig().Gui.ScreenMode) } + + return parseScreenModeArg(config.GetUserConfig().Gui.ScreenMode) } func parseScreenModeArg(screenModeArg string) types.ScreenMode { diff --git a/pkg/gui/information_panel.go b/pkg/gui/information_panel.go index f94ed785a..ab2f3512d 100644 --- a/pkg/gui/information_panel.go +++ b/pkg/gui/information_panel.go @@ -17,9 +17,9 @@ func (gui *Gui) informationStr() string { donate := style.FgMagenta.Sprint(style.PrintHyperlink(gui.c.Tr.Donate, constants.Links.Donate)) askQuestion := style.FgYellow.Sprint(style.PrintHyperlink(gui.c.Tr.AskQuestion, constants.Links.Discussions)) return fmt.Sprintf("%s %s %s", donate, askQuestion, gui.Config.GetVersion()) - } else { - return gui.Config.GetVersion() } + + return gui.Config.GetVersion() } func (gui *Gui) handleInfoClick() error { diff --git a/pkg/gui/keybindings/keybindings.go b/pkg/gui/keybindings/keybindings.go index 923a30c3b..0db3e8a61 100644 --- a/pkg/gui/keybindings/keybindings.go +++ b/pkg/gui/keybindings/keybindings.go @@ -41,9 +41,8 @@ func GetKey(key string) types.Key { binding, ok := config.KeyByLabel[strings.ToLower(key)] if !ok { log.Fatalf("Unrecognized key %s for keybinding. For permitted values see %s", strings.ToLower(key), constants.Links.Docs.CustomKeybindings) - } else { - return binding } + return binding } else if runeCount == 1 { return []rune(key)[0] } diff --git a/pkg/gui/mergeconflicts/merge_conflict.go b/pkg/gui/mergeconflicts/merge_conflict.go index e6b617f57..9b9b72f55 100644 --- a/pkg/gui/mergeconflicts/merge_conflict.go +++ b/pkg/gui/mergeconflicts/merge_conflict.go @@ -50,9 +50,8 @@ func (s Selection) bounds(c *mergeConflict) (int, int) { case TOP: if c.hasAncestor() { return c.start, c.ancestor - } else { - return c.start, c.target } + return c.start, c.target case MIDDLE: return c.ancestor, c.target case BOTTOM: @@ -72,7 +71,6 @@ func (s Selection) selected(c *mergeConflict, idx int) bool { func availableSelections(c *mergeConflict) []Selection { if c.hasAncestor() { return []Selection{TOP, MIDDLE, BOTTOM} - } else { - return []Selection{TOP, BOTTOM} } + return []Selection{TOP, BOTTOM} } diff --git a/pkg/gui/patch_exploring/focus.go b/pkg/gui/patch_exploring/focus.go index c2b43c4a3..3548f09d4 100644 --- a/pkg/gui/patch_exploring/focus.go +++ b/pkg/gui/patch_exploring/focus.go @@ -25,9 +25,8 @@ func calculateNewOriginWithNeededAndWantedIdx(currentOrigin int, bufferHeight in requiredChange := wantToSeeIdx - bottom allowedChange := needToSeeIdx - origin return origin + min(requiredChange, allowedChange) - } else { - return origin } + return origin } func getNeedAndWantLineIdx(firstLineIdx int, lastLineIdx int, selectedLineIdx int, mode selectMode) (int, int) { @@ -37,9 +36,8 @@ func getNeedAndWantLineIdx(firstLineIdx int, lastLineIdx int, selectedLineIdx in case RANGE: if selectedLineIdx == firstLineIdx { return firstLineIdx, lastLineIdx - } else { - return lastLineIdx, firstLineIdx } + return lastLineIdx, firstLineIdx case HUNK: return firstLineIdx, lastLineIdx default: diff --git a/pkg/gui/patch_exploring/state.go b/pkg/gui/patch_exploring/state.go index 73ce0a756..53e120849 100644 --- a/pkg/gui/patch_exploring/state.go +++ b/pkg/gui/patch_exploring/state.go @@ -267,9 +267,8 @@ func (s *State) SelectedViewRange() (int, int) { case RANGE: if s.rangeStartLineIdx > s.selectedLineIdx { return s.selectedLineIdx, s.rangeStartLineIdx - } else { - return s.rangeStartLineIdx, s.selectedLineIdx } + return s.rangeStartLineIdx, s.selectedLineIdx case LINE: return s.selectedLineIdx, s.selectedLineIdx default: diff --git a/pkg/gui/presentation/commits.go b/pkg/gui/presentation/commits.go index 63c2b3c9b..a5799bcb3 100644 --- a/pkg/gui/presentation/commits.go +++ b/pkg/gui/presentation/commits.go @@ -145,9 +145,8 @@ func GetCommitListDisplayStrings( getGraphLine = func(idx int) string { if idx >= graphOffset { return graphLines[idx-graphOffset] - } else { - return "" } + return "" } } } else { @@ -305,9 +304,8 @@ func getBisectStatus(index int, commitHash string, bisectInfo *git_commands.Bise } else { if bisectBounds != nil && index >= bisectBounds.newIndex && index <= bisectBounds.oldIndex { return BisectStatusCandidate - } else { - return BisectStatusNone } + return BisectStatusNone } // should never land here diff --git a/pkg/gui/presentation/files.go b/pkg/gui/presentation/files.go index 4222fb68d..cc0a93889 100644 --- a/pkg/gui/presentation/files.go +++ b/pkg/gui/presentation/files.go @@ -63,9 +63,8 @@ func commitFilePatchStatus(node *filetree.Node[models.CommitFile], tree *filetre return patchBuilder.GetFileStatus(file.Path, tree.GetRef().RefName()) == patch.UNSELECTED }) { return patch.UNSELECTED - } else { - return patch.PART } + return patch.PART } func renderAux[T any]( diff --git a/pkg/gui/presentation/graph/cell.go b/pkg/gui/presentation/graph/cell.go index a890613f0..be039a018 100644 --- a/pkg/gui/presentation/graph/cell.go +++ b/pkg/gui/presentation/graph/cell.go @@ -177,7 +177,7 @@ func getBoxDrawingChars(up, down, left, right bool) (string, string) { return "╶", "─" } else if !up && !down && !left && !right { return " ", " " - } else { - panic("should not be possible") } + + panic("should not be possible") } diff --git a/pkg/gui/presentation/graph/graph.go b/pkg/gui/presentation/graph/graph.go index fc33f3135..1639a62e6 100644 --- a/pkg/gui/presentation/graph/graph.go +++ b/pkg/gui/presentation/graph/graph.go @@ -246,9 +246,8 @@ func getNextPipes(prevPipes []Pipe, commit *models.Commit, getStyle func(c *mode for i := pipe.toPos; i > pos; i-- { if takenSpots.Includes(int(i)) || traversedSpots.Includes(int(i)) { break - } else { - last = i } + last = i } newPipes = append(newPipes, Pipe{ fromPos: pipe.toPos, diff --git a/pkg/tasks/tasks.go b/pkg/tasks/tasks.go index 8de96b249..5de7fb232 100644 --- a/pkg/tasks/tasks.go +++ b/pkg/tasks/tasks.go @@ -260,7 +260,7 @@ func (self *ViewBufferManager) NewCmdTask(start func() (*exec.Cmd, io.Reader), p callThen() break outer case line, ok = <-lineChan: - break + // process line below } loadingMutex.Lock() diff --git a/pkg/tasks/tasks_test.go b/pkg/tasks/tasks_test.go index 72da6d83c..c7a499d46 100644 --- a/pkg/tasks/tasks_test.go +++ b/pkg/tasks/tasks_test.go @@ -167,7 +167,7 @@ func (d *BlankLineReader) Read(p []byte) (n int, err error) { return 0, io.EOF } - d.linesYielded += 1 + d.linesYielded++ p[0] = '\n' return 1, nil } diff --git a/pkg/utils/formatting.go b/pkg/utils/formatting.go index 08cc7d49a..0e5a6ee03 100644 --- a/pkg/utils/formatting.go +++ b/pkg/utils/formatting.go @@ -44,9 +44,8 @@ func WithPadding(str string, padding int, alignment Alignment) string { space := strings.Repeat(" ", padding-width) if alignment == AlignLeft { return str + space - } else { - return space + str } + return space + str } // defaults to left-aligning each column. If you want to set the alignment of @@ -187,9 +186,8 @@ func TruncateWithEllipsis(str string, limit int) string { func SafeTruncate(str string, limit int) string { if len(str) > limit { return str[0:limit] - } else { - return str } + return str } const COMMIT_HASH_SHORT_SIZE = 8 diff --git a/pkg/utils/once_writer_test.go b/pkg/utils/once_writer_test.go index 47f64bb61..aa57ff163 100644 --- a/pkg/utils/once_writer_test.go +++ b/pkg/utils/once_writer_test.go @@ -9,7 +9,7 @@ func TestOnceWriter(t *testing.T) { innerWriter := bytes.NewBuffer(nil) counter := 0 onceWriter := NewOnceWriter(innerWriter, func() { - counter += 1 + counter++ }) _, _ = onceWriter.Write([]byte("hello")) _, _ = onceWriter.Write([]byte("hello")) diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 5eecc6e70..950555512 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -45,9 +45,8 @@ func ModuloWithWrap(n, max int) int { return n % max } else if n < 0 { return max + n - } else { - return n } + return n } func FindStringSubmatch(str string, regexpStr string) (bool, []string) { diff --git a/pkg/utils/yaml_utils/yaml_utils_test.go b/pkg/utils/yaml_utils/yaml_utils_test.go index 9ae099396..d4d1fe074 100644 --- a/pkg/utils/yaml_utils/yaml_utils_test.go +++ b/pkg/utils/yaml_utils/yaml_utils_test.go @@ -224,12 +224,10 @@ func TestTransformNode(t *testing.T) { } else if node.ShortTag() == "!!str" { // We have already transformed it, return nil - } else { - return fmt.Errorf("Node was of bad type") } - } else { - return fmt.Errorf("Node was not a scalar") + return fmt.Errorf("Node was of bad type") } + return fmt.Errorf("Node was not a scalar") } tests := []struct {