mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-09-10 07:36:27 -04:00
Validate the context names in the "context" field of custom commands (#5989)
If a custom command's "context" field contains a context name that doesn't exist, lazygit panics when building the keybindings. This could happen either because of a typo, or because a context is removed or renamed in a later version. Prevent the panic by validating those names at config load time, and rejecting the config as invalid there, like we do for other config errors.
This commit is contained in:
commit
e7de68331a
|
|
@ -191,6 +191,51 @@ func validateCustomCommandKey(key Keybinding) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// ValidCustomCommandContexts lists the names a custom command's 'context' may
|
||||
// use. It mirrors context.AllContextKeys in the gui package, which this package
|
||||
// can't import; a test over there keeps the two in sync.
|
||||
var ValidCustomCommandContexts = []string{
|
||||
"global",
|
||||
"status",
|
||||
"files",
|
||||
"localBranches",
|
||||
"remotes",
|
||||
"worktrees",
|
||||
"remoteBranches",
|
||||
"tags",
|
||||
"commits",
|
||||
"reflogCommits",
|
||||
"subCommits",
|
||||
"commitFiles",
|
||||
"stash",
|
||||
"normal",
|
||||
"normalSecondary",
|
||||
"staging",
|
||||
"stagingSecondary",
|
||||
"patchBuilding",
|
||||
"patchBuildingSecondary",
|
||||
"mergeConflicts",
|
||||
"menu",
|
||||
"confirmation",
|
||||
"prompt",
|
||||
"search",
|
||||
"commitMessage",
|
||||
"submodules",
|
||||
"suggestions",
|
||||
"cmdLog",
|
||||
}
|
||||
|
||||
func validateCustomCommandContext(context string) error {
|
||||
for _, name := range strings.Split(context, ",") {
|
||||
name = strings.TrimSpace(name)
|
||||
if !slices.Contains(ValidCustomCommandContexts, name) {
|
||||
return fmt.Errorf("Unknown context '%s' for custom command. Allowed values: %s",
|
||||
name, strings.Join(ValidCustomCommandContexts, ", "))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateCustomCommands(customCommands []CustomCommand) error {
|
||||
for _, customCommand := range customCommands {
|
||||
if err := validateCustomCommandKey(customCommand.Key); err != nil {
|
||||
|
|
@ -216,6 +261,15 @@ func validateCustomCommands(customCommands []CustomCommand) error {
|
|||
return err
|
||||
}
|
||||
} else {
|
||||
// A command in a menu may leave the context out, in which case it is
|
||||
// offered whatever is focused; a top-level one may not, but that is
|
||||
// only noticed when the keybindings are built.
|
||||
if customCommand.Context != "" {
|
||||
if err := validateCustomCommandContext(customCommand.Context); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, prompt := range customCommand.Prompts {
|
||||
if err := validateCustomCommandPrompt(prompt); err != nil {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -225,6 +225,43 @@ func TestUserConfigValidate_enums(t *testing.T) {
|
|||
{value: "invalid_value", valid: false},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Custom command context",
|
||||
setup: func(config *UserConfig, value string) {
|
||||
config.CustomCommands = []CustomCommand{
|
||||
{
|
||||
Context: value,
|
||||
},
|
||||
}
|
||||
},
|
||||
testCases: []testCase{
|
||||
{value: "", valid: true},
|
||||
{value: "global", valid: true},
|
||||
{value: "commits", valid: true},
|
||||
{value: "commits, subCommits", valid: true},
|
||||
{value: "commits,subCommits", valid: true},
|
||||
{value: "invalid_value", valid: false},
|
||||
{value: "commits, invalid_value", valid: false},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Custom command context in a sub menu",
|
||||
setup: func(config *UserConfig, value string) {
|
||||
config.CustomCommands = []CustomCommand{
|
||||
{
|
||||
Key: Keybinding{"X"},
|
||||
CommandMenu: []CustomCommand{
|
||||
{Key: Keybinding{"1"}, Command: "echo 'hello'", Context: value},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
testCases: []testCase{
|
||||
{value: "", valid: true},
|
||||
{value: "commits", valid: true},
|
||||
{value: "invalid_value", valid: false},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Custom command sub menu",
|
||||
setup: func(config *UserConfig, _ string) {
|
||||
|
|
|
|||
22
pkg/gui/context/context_test.go
Normal file
22
pkg/gui/context/context_test.go
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
package context
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/samber/lo"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// The config package validates a custom command's context against its own copy of
|
||||
// these names, being unable to import this package. A name in one list but not the
|
||||
// other would be either a context that validation rejects although you can bind to
|
||||
// it, or one it accepts although binding to it exits lazygit.
|
||||
func TestValidCustomCommandContextsMatchesAllContextKeys(t *testing.T) {
|
||||
keys := lo.Map(AllContextKeys, func(key types.ContextKey, _ int) string {
|
||||
return string(key)
|
||||
})
|
||||
|
||||
assert.Equal(t, keys, config.ValidCustomCommandContexts)
|
||||
}
|
||||
Loading…
Reference in a new issue