Skip to content

Commit 1ec622d

Browse files
GiteaBotwxiaoguang
andauthored
Improve doctor cli behavior (go-gitea#28422) (go-gitea#28424)
Backport go-gitea#28422 by wxiaoguang 1. Do not sort the "checks" slice again and again when "Register", it just wastes CPU when the Gitea instance runs 2. If a check doesn't exist, tell the end user 3. Add some tests Co-authored-by: wxiaoguang <[email protected]>
1 parent 40d5118 commit 1ec622d

File tree

3 files changed

+66
-34
lines changed

3 files changed

+66
-34
lines changed

cmd/doctor.go

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"code.gitea.io/gitea/models/db"
1515
"code.gitea.io/gitea/models/migrations"
1616
migrate_base "code.gitea.io/gitea/models/migrations/base"
17+
"code.gitea.io/gitea/modules/container"
1718
"code.gitea.io/gitea/modules/doctor"
1819
"code.gitea.io/gitea/modules/log"
1920
"code.gitea.io/gitea/modules/setting"
@@ -22,6 +23,19 @@ import (
2223
"xorm.io/xorm"
2324
)
2425

26+
// CmdDoctor represents the available doctor sub-command.
27+
var CmdDoctor = &cli.Command{
28+
Name: "doctor",
29+
Usage: "Diagnose and optionally fix problems",
30+
Description: "A command to diagnose problems with the current Gitea instance according to the given configuration. Some problems can optionally be fixed by modifying the database or data storage.",
31+
32+
Subcommands: []*cli.Command{
33+
cmdDoctorCheck,
34+
cmdRecreateTable,
35+
cmdDoctorConvert,
36+
},
37+
}
38+
2539
var cmdDoctorCheck = &cli.Command{
2640
Name: "check",
2741
Usage: "Diagnose and optionally fix problems",
@@ -60,19 +74,6 @@ var cmdDoctorCheck = &cli.Command{
6074
},
6175
}
6276

63-
// CmdDoctor represents the available doctor sub-command.
64-
var CmdDoctor = &cli.Command{
65-
Name: "doctor",
66-
Usage: "Diagnose and optionally fix problems",
67-
Description: "A command to diagnose problems with the current Gitea instance according to the given configuration. Some problems can optionally be fixed by modifying the database or data storage.",
68-
69-
Subcommands: []*cli.Command{
70-
cmdDoctorCheck,
71-
cmdRecreateTable,
72-
cmdDoctorConvert,
73-
},
74-
}
75-
7677
var cmdRecreateTable = &cli.Command{
7778
Name: "recreate-table",
7879
Usage: "Recreate tables from XORM definitions and copy the data.",
@@ -177,6 +178,7 @@ func runDoctorCheck(ctx *cli.Context) error {
177178
if ctx.IsSet("list") {
178179
w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0)
179180
_, _ = w.Write([]byte("Default\tName\tTitle\n"))
181+
doctor.SortChecks(doctor.Checks)
180182
for _, check := range doctor.Checks {
181183
if check.IsDefault {
182184
_, _ = w.Write([]byte{'*'})
@@ -192,33 +194,26 @@ func runDoctorCheck(ctx *cli.Context) error {
192194

193195
var checks []*doctor.Check
194196
if ctx.Bool("all") {
195-
checks = doctor.Checks
197+
checks = make([]*doctor.Check, len(doctor.Checks))
198+
copy(checks, doctor.Checks)
196199
} else if ctx.IsSet("run") {
197200
addDefault := ctx.Bool("default")
198-
names := ctx.StringSlice("run")
199-
for i, name := range names {
200-
names[i] = strings.ToLower(strings.TrimSpace(name))
201-
}
202-
201+
runNamesSet := container.SetOf(ctx.StringSlice("run")...)
203202
for _, check := range doctor.Checks {
204-
if addDefault && check.IsDefault {
203+
if (addDefault && check.IsDefault) || runNamesSet.Contains(check.Name) {
205204
checks = append(checks, check)
206-
continue
207-
}
208-
for _, name := range names {
209-
if name == check.Name {
210-
checks = append(checks, check)
211-
break
212-
}
205+
runNamesSet.Remove(check.Name)
213206
}
214207
}
208+
if len(runNamesSet) > 0 {
209+
return fmt.Errorf("unknown checks: %q", strings.Join(runNamesSet.Values(), ","))
210+
}
215211
} else {
216212
for _, check := range doctor.Checks {
217213
if check.IsDefault {
218214
checks = append(checks, check)
219215
}
220216
}
221217
}
222-
223218
return doctor.RunChecks(stdCtx, colorize, ctx.Bool("fix"), checks)
224219
}

cmd/doctor_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2023 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package cmd
5+
6+
import (
7+
"context"
8+
"testing"
9+
10+
"code.gitea.io/gitea/modules/doctor"
11+
"code.gitea.io/gitea/modules/log"
12+
13+
"github.com/stretchr/testify/assert"
14+
"github.com/urfave/cli/v2"
15+
)
16+
17+
func TestDoctorRun(t *testing.T) {
18+
doctor.Register(&doctor.Check{
19+
Title: "Test Check",
20+
Name: "test-check",
21+
Run: func(ctx context.Context, logger log.Logger, autofix bool) error { return nil },
22+
23+
SkipDatabaseInitialization: true,
24+
})
25+
app := cli.NewApp()
26+
app.Commands = []*cli.Command{cmdDoctorCheck}
27+
err := app.Run([]string{"./gitea", "check", "--run", "test-check"})
28+
assert.NoError(t, err)
29+
err = app.Run([]string{"./gitea", "check", "--run", "no-such"})
30+
assert.ErrorContains(t, err, `unknown checks: "no-such"`)
31+
err = app.Run([]string{"./gitea", "check", "--run", "test-check,no-such"})
32+
assert.ErrorContains(t, err, `unknown checks: "no-such"`)
33+
}

modules/doctor/doctor.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ var Checks []*Check
7979

8080
// RunChecks runs the doctor checks for the provided list
8181
func RunChecks(ctx context.Context, colorize, autofix bool, checks []*Check) error {
82+
SortChecks(checks)
8283
// the checks output logs by a special logger, they do not use the default logger
8384
logger := log.BaseLoggerToGeneralLogger(&doctorCheckLogger{colorize: colorize})
8485
loggerStep := log.BaseLoggerToGeneralLogger(&doctorCheckStepLogger{colorize: colorize})
@@ -104,20 +105,23 @@ func RunChecks(ctx context.Context, colorize, autofix bool, checks []*Check) err
104105
logger.Info("OK")
105106
}
106107
}
107-
logger.Info("\nAll done.")
108+
logger.Info("\nAll done (checks: %d).", len(checks))
108109
return nil
109110
}
110111

111112
// Register registers a command with the list
112113
func Register(command *Check) {
113114
Checks = append(Checks, command)
114-
sort.SliceStable(Checks, func(i, j int) bool {
115-
if Checks[i].Priority == Checks[j].Priority {
116-
return Checks[i].Name < Checks[j].Name
115+
}
116+
117+
func SortChecks(checks []*Check) {
118+
sort.SliceStable(checks, func(i, j int) bool {
119+
if checks[i].Priority == checks[j].Priority {
120+
return checks[i].Name < checks[j].Name
117121
}
118-
if Checks[i].Priority == 0 {
122+
if checks[i].Priority == 0 {
119123
return false
120124
}
121-
return Checks[i].Priority < Checks[j].Priority
125+
return checks[i].Priority < checks[j].Priority
122126
})
123127
}

0 commit comments

Comments
 (0)