code.gitea.io/gitea@v1.19.3/modules/doctor/doctor.go (about) 1 // Copyright 2020 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package doctor 5 6 import ( 7 "context" 8 "fmt" 9 "sort" 10 "strings" 11 12 "code.gitea.io/gitea/models/db" 13 "code.gitea.io/gitea/modules/git" 14 "code.gitea.io/gitea/modules/log" 15 "code.gitea.io/gitea/modules/setting" 16 ) 17 18 // Check represents a Doctor check 19 type Check struct { 20 Title string 21 Name string 22 IsDefault bool 23 Run func(ctx context.Context, logger log.Logger, autofix bool) error 24 AbortIfFailed bool 25 SkipDatabaseInitialization bool 26 Priority int 27 } 28 29 type wrappedLevelLogger struct { 30 log.LevelLogger 31 } 32 33 func (w *wrappedLevelLogger) Log(skip int, level log.Level, format string, v ...interface{}) error { 34 return w.LevelLogger.Log( 35 skip+1, 36 level, 37 " - %s "+format, 38 append( 39 []interface{}{ 40 log.NewColoredValueBytes( 41 fmt.Sprintf("[%s]", strings.ToUpper(level.String()[0:1])), 42 level.Color()), 43 }, v...)...) 44 } 45 46 func initDBDisableConsole(ctx context.Context, disableConsole bool) error { 47 setting.InitProviderFromExistingFile() 48 setting.LoadCommonSettings() 49 setting.LoadDBSetting() 50 setting.InitSQLLog(disableConsole) 51 if err := db.InitEngine(ctx); err != nil { 52 return fmt.Errorf("db.InitEngine: %w", err) 53 } 54 // some doctor sub-commands need to use git command 55 if err := git.InitFull(ctx); err != nil { 56 return fmt.Errorf("git.InitFull: %w", err) 57 } 58 return nil 59 } 60 61 // Checks is the list of available commands 62 var Checks []*Check 63 64 // RunChecks runs the doctor checks for the provided list 65 func RunChecks(ctx context.Context, logger log.Logger, autofix bool, checks []*Check) error { 66 wrappedLogger := log.LevelLoggerLogger{ 67 LevelLogger: &wrappedLevelLogger{logger}, 68 } 69 70 dbIsInit := false 71 for i, check := range checks { 72 if !dbIsInit && !check.SkipDatabaseInitialization { 73 // Only open database after the most basic configuration check 74 setting.Log.EnableXORMLog = false 75 if err := initDBDisableConsole(ctx, true); err != nil { 76 logger.Error("Error whilst initializing the database: %v", err) 77 logger.Error("Check if you are using the right config file. You can use a --config directive to specify one.") 78 return nil 79 } 80 dbIsInit = true 81 } 82 logger.Info("[%d] %s", log.NewColoredIDValue(i+1), check.Title) 83 logger.Flush() 84 if err := check.Run(ctx, &wrappedLogger, autofix); err != nil { 85 if check.AbortIfFailed { 86 logger.Critical("FAIL") 87 return err 88 } 89 logger.Error("ERROR") 90 } else { 91 logger.Info("OK") 92 logger.Flush() 93 } 94 } 95 return nil 96 } 97 98 // Register registers a command with the list 99 func Register(command *Check) { 100 Checks = append(Checks, command) 101 sort.SliceStable(Checks, func(i, j int) bool { 102 if Checks[i].Priority == Checks[j].Priority { 103 return Checks[i].Name < Checks[j].Name 104 } 105 if Checks[i].Priority == 0 { 106 return false 107 } 108 return Checks[i].Priority < Checks[j].Priority 109 }) 110 }