mirror of
https://github.com/go-gitea/gitea.git
synced 2026-05-23 00:09:29 +01:00
8cfcef32c6
After 07ada3666b, PrepareConsoleLoggerLevel can fail in tests when
InstallLock is true, due to the incorrect config file is loaded. This PR
fixes cmd test setup by mocking builtin paths
Fixes #37368
---------
Co-authored-by: Morgan PEYRE <morgan.peyre@brickcode.tech>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
221 lines
6.6 KiB
Go
221 lines
6.6 KiB
Go
// Copyright 2023 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package setting
|
|
|
|
import (
|
|
"errors"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"code.gitea.io/gitea/modules/log"
|
|
"code.gitea.io/gitea/modules/tempdir"
|
|
)
|
|
|
|
var (
|
|
// AppPath represents the path to the gitea binary
|
|
AppPath string
|
|
|
|
// AppWorkPath is the "working directory" of Gitea. It maps to the: WORK_PATH in app.ini, "--work-path" flag, environment variable GITEA_WORK_DIR.
|
|
// If that is not set it is the default set here by the linker or failing that the directory of AppPath.
|
|
// It is used as the base path for several other paths.
|
|
AppWorkPath string
|
|
CustomPath string // Custom directory path. Env: GITEA_CUSTOM
|
|
CustomConf string
|
|
|
|
appWorkPathBuiltin string
|
|
customPathBuiltin string
|
|
customConfBuiltin string
|
|
|
|
AppWorkPathMismatch bool
|
|
)
|
|
|
|
func getAppPath() (string, error) {
|
|
var appPath string
|
|
var err error
|
|
if IsWindows && filepath.IsAbs(os.Args[0]) {
|
|
appPath = filepath.Clean(os.Args[0])
|
|
} else {
|
|
appPath, err = exec.LookPath(os.Args[0])
|
|
}
|
|
if err != nil {
|
|
if !errors.Is(err, exec.ErrDot) {
|
|
return "", err
|
|
}
|
|
appPath, err = filepath.Abs(os.Args[0])
|
|
}
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
appPath, err = filepath.Abs(appPath)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
// Note: (legacy code) we don't use path.Dir here because it does not handle case which path starts with two "/" in Windows: "//psf/Home/..."
|
|
return strings.ReplaceAll(appPath, "\\", "/"), err
|
|
}
|
|
|
|
func init() {
|
|
var err error
|
|
if AppPath, err = getAppPath(); err != nil {
|
|
log.Fatal("Failed to get app path: %v", err)
|
|
}
|
|
|
|
if AppWorkPath == "" {
|
|
AppWorkPath = filepath.Dir(AppPath)
|
|
}
|
|
|
|
appWorkPathBuiltin = AppWorkPath
|
|
customPathBuiltin = CustomPath
|
|
customConfBuiltin = CustomConf
|
|
}
|
|
|
|
type ArgWorkPathAndCustomConf struct {
|
|
WorkPath string
|
|
CustomPath string
|
|
CustomConf string
|
|
}
|
|
|
|
type stringWithDefault struct {
|
|
Value string
|
|
IsSet bool
|
|
}
|
|
|
|
func (s *stringWithDefault) Set(v string) {
|
|
s.Value = v
|
|
s.IsSet = true
|
|
}
|
|
|
|
// InitWorkPathAndCommonConfig will set AppWorkPath, CustomPath and CustomConf, init default config provider by CustomConf and load common settings,
|
|
func InitWorkPathAndCommonConfig(getEnvFn func(name string) string, args ArgWorkPathAndCustomConf) {
|
|
InitWorkPathAndCfgProvider(getEnvFn, args)
|
|
LoadCommonSettings()
|
|
}
|
|
|
|
// InitWorkPathAndCfgProvider will set AppWorkPath, CustomPath and CustomConf, init default config provider by CustomConf
|
|
func InitWorkPathAndCfgProvider(getEnvFn func(name string) string, args ArgWorkPathAndCustomConf) {
|
|
tryAbsPath := func(paths ...string) string {
|
|
s := paths[len(paths)-1]
|
|
for i := len(paths) - 2; i >= 0; i-- {
|
|
if filepath.IsAbs(s) {
|
|
break
|
|
}
|
|
s = filepath.Join(paths[i], s)
|
|
}
|
|
return s
|
|
}
|
|
|
|
var err error
|
|
tmpWorkPath := stringWithDefault{Value: appWorkPathBuiltin}
|
|
if tmpWorkPath.Value == "" {
|
|
tmpWorkPath.Value = filepath.Dir(AppPath)
|
|
}
|
|
tmpCustomPath := stringWithDefault{Value: customPathBuiltin}
|
|
if tmpCustomPath.Value == "" {
|
|
tmpCustomPath.Value = "custom"
|
|
}
|
|
tmpCustomConf := stringWithDefault{Value: customConfBuiltin}
|
|
if tmpCustomConf.Value == "" {
|
|
tmpCustomConf.Value = "conf/app.ini"
|
|
}
|
|
|
|
readFromEnv := func() {
|
|
envWorkPath := getEnvFn("GITEA_WORK_DIR")
|
|
if envWorkPath != "" {
|
|
tmpWorkPath.Set(envWorkPath)
|
|
if !filepath.IsAbs(tmpWorkPath.Value) {
|
|
log.Fatal("GITEA_WORK_DIR (work path) must be absolute path")
|
|
}
|
|
}
|
|
|
|
envCustomPath := getEnvFn("GITEA_CUSTOM")
|
|
if envCustomPath != "" {
|
|
tmpCustomPath.Set(envCustomPath)
|
|
if !filepath.IsAbs(tmpCustomPath.Value) {
|
|
log.Fatal("GITEA_CUSTOM (custom path) must be absolute path")
|
|
}
|
|
}
|
|
}
|
|
|
|
readFromArgs := func() {
|
|
if args.WorkPath != "" {
|
|
tmpWorkPath.Set(args.WorkPath)
|
|
if !filepath.IsAbs(tmpWorkPath.Value) {
|
|
log.Fatal("--work-path must be absolute path")
|
|
}
|
|
}
|
|
if args.CustomPath != "" {
|
|
tmpCustomPath.Set(args.CustomPath) // if it is not abs, it will be based on work-path, it shouldn't happen
|
|
if !filepath.IsAbs(tmpCustomPath.Value) {
|
|
log.Error("--custom-path must be absolute path")
|
|
}
|
|
}
|
|
if args.CustomConf != "" {
|
|
tmpCustomConf.Set(args.CustomConf)
|
|
if !filepath.IsAbs(tmpCustomConf.Value) {
|
|
// the config path can be relative to the real current working path
|
|
if tmpCustomConf.Value, err = filepath.Abs(tmpCustomConf.Value); err != nil {
|
|
log.Fatal("Failed to get absolute path of config %q: %v", tmpCustomConf.Value, err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
readFromEnv()
|
|
readFromArgs()
|
|
|
|
if !tmpCustomConf.IsSet {
|
|
tmpCustomConf.Set(tryAbsPath(tmpWorkPath.Value, tmpCustomPath.Value, tmpCustomConf.Value))
|
|
}
|
|
|
|
// only read the config but do not load/init anything more, because the AppWorkPath and CustomPath are not ready
|
|
InitCfgProvider(tmpCustomConf.Value)
|
|
if HasInstallLock(CfgProvider) {
|
|
ClearEnvConfigKeys() // if the instance has been installed, do not pass the environment variables to sub-processes
|
|
}
|
|
configWorkPath := ConfigSectionKeyString(CfgProvider.Section(""), "WORK_PATH")
|
|
if configWorkPath != "" {
|
|
if !filepath.IsAbs(configWorkPath) {
|
|
log.Fatal("WORK_PATH in %q must be absolute path", configWorkPath)
|
|
}
|
|
configWorkPath = filepath.Clean(configWorkPath)
|
|
if tmpWorkPath.Value != "" && (getEnvFn("GITEA_WORK_DIR") != "" || args.WorkPath != "") {
|
|
fi1, err1 := os.Stat(tmpWorkPath.Value)
|
|
fi2, err2 := os.Stat(configWorkPath)
|
|
if err1 != nil || err2 != nil || !os.SameFile(fi1, fi2) {
|
|
AppWorkPathMismatch = true
|
|
}
|
|
}
|
|
tmpWorkPath.Set(configWorkPath)
|
|
}
|
|
|
|
tmpCustomPath.Set(tryAbsPath(tmpWorkPath.Value, tmpCustomPath.Value))
|
|
|
|
AppWorkPath = tmpWorkPath.Value
|
|
CustomPath = tmpCustomPath.Value
|
|
CustomConf = tmpCustomConf.Value
|
|
}
|
|
|
|
func MockBuiltinPaths(workPath, customPath, customConf string) func() {
|
|
oldApp, oldCustom, oldConf := appWorkPathBuiltin, customPathBuiltin, customConfBuiltin
|
|
appWorkPathBuiltin, customPathBuiltin, customConfBuiltin = workPath, customPath, customConf
|
|
return func() { appWorkPathBuiltin, customPathBuiltin, customConfBuiltin = oldApp, oldCustom, oldConf }
|
|
}
|
|
|
|
// AppDataTempDir returns a managed temporary directory for the application data.
|
|
// Using empty sub will get the managed base temp directory, and it's safe to delete it.
|
|
// Gitea only creates subdirectories under it, but not the APP_TEMP_PATH directory itself.
|
|
// * When APP_TEMP_PATH="/tmp": the managed temp directory is "/tmp/gitea-tmp"
|
|
// * When APP_TEMP_PATH is not set: the managed temp directory is "/{APP_DATA_PATH}/tmp"
|
|
func AppDataTempDir(sub string) *tempdir.TempDir {
|
|
if appTempPathInternal != "" {
|
|
return tempdir.New(appTempPathInternal, "gitea-tmp/"+sub)
|
|
}
|
|
if AppDataPath == "" {
|
|
panic("setting.AppDataPath is not set")
|
|
}
|
|
return tempdir.New(AppDataPath, "tmp/"+sub)
|
|
}
|