mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-11-22 08:42:32 -05:00
71d2a6a41a
Backport #25480 by @wxiaoguang Fix #25481 The `InitWorkPathAndCommonConfig` calls `LoadCommonSettings` which does many checks like "current user is root or not". Some commands like "environment-to-ini" shouldn't do such check, because it might be run with "root" user at the moment (eg: the docker's setup script) ps: in the future, the docker's setup script should be improved to avoid Gitea's command running with "root" Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
195 lines
5.3 KiB
Go
195 lines
5.3 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"
|
|
)
|
|
|
|
var (
|
|
// AppPath represents the path to the gitea binary
|
|
AppPath string
|
|
|
|
// AppWorkPath is the "working directory" of Gitea. It maps to the 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)
|
|
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
|
|
}
|