diff --git a/internal/lefthook/run/runner.go b/internal/lefthook/run/runner.go index dbac0a0d..3ccd3c52 100644 --- a/internal/lefthook/run/runner.go +++ b/internal/lefthook/run/runner.go @@ -332,7 +332,7 @@ func (r *Runner) runCommands(ctx context.Context) { } } - sortAlnum(commands, r.Hook.Commands) + sortCommands(commands, r.Hook.Commands) interactiveCommands := make([]string, 0) var wg sync.WaitGroup @@ -532,20 +532,20 @@ func (r *Runner) logExecute(name string, err error, out io.Reader) { } } -// sortAlnum sorts the command names by preceding numbers if they occur. +// sortCommands sorts the command names by preceding numbers if they occur and special priority if it is set. // If the command names starts with letter the command name will be sorted alphabetically. // // []string{"1_command", "10command", "3 command", "command5"} // -> 1_command, 3 command, 10command, command5 -func sortAlnum(strs []string, commands map[string]*config.Command) { +func sortCommands(strs []string, commands map[string]*config.Command) { sort.SliceStable(strs, func(i, j int) bool { - commandI, iok := commands[strs[i]] - commandJ, jok := commands[strs[j]] + commandI, iOk := commands[strs[i]] + commandJ, jOk := commands[strs[j]] - if iok && jok && (commandI.Priority != 0 || commandJ.Priority != 0) { - if commandI.Priority == 0 { + if iOk && commandI.Priority != 0 || jOk && commandJ.Priority != 0 { + if !iOk || commandI.Priority == 0 { return false } - if commandJ.Priority == 0 { + if !jOk || commandJ.Priority == 0 { return true } diff --git a/internal/lefthook/run/runner_test.go b/internal/lefthook/run/runner_test.go index 211b0c94..9206aae0 100644 --- a/internal/lefthook/run/runner_test.go +++ b/internal/lefthook/run/runner_test.go @@ -918,3 +918,38 @@ func TestReplaceQuoted(t *testing.T) { }) } } + +func TestSortCommands(t *testing.T) { + for i, tt := range [...]struct { + name string + names []string + commands map[string]*config.Command + result []string + }{ + { + name: "alphanumeric sort", + names: []string{"10_a", "1_a", "2_a", "5_a"}, + commands: map[string]*config.Command{}, + result: []string{"1_a", "2_a", "5_a", "10_a"}, + }, + { + name: "partial priority", + names: []string{"10_a", "1_a", "2_a", "5_a"}, + commands: map[string]*config.Command{ + "5_a": {Priority: 10}, + "2_a": {Priority: 1}, + "10_a": {}, + }, + result: []string{"2_a", "5_a", "1_a", "10_a"}, + }, + } { + t.Run(fmt.Sprintf("%d: %s", i+1, tt.name), func(t *testing.T) { + sortCommands(tt.names, tt.commands) + for i, name := range tt.result { + if tt.names[i] != name { + t.Errorf("Not matching on index %d: %s != %s", i, name, tt.names[i]) + } + } + }) + } +}