forgejo/modules/setting/path.go
Loïc Dachary 234e6d3648
[BRANDING] alias {FORGEJO,GITEA}_{CUSTOM,WORK_DIR}
FORGEJO_* environment variables are set to the corresponding GITEA_*
variable when the cli starts. This approach is intended to minimize
the conflicts on rebase. All occurences of GITEA_* are left untouched
in the codebase and they are only changed to FORGEJO_* if exposed to
the user.

(cherry picked from commit e466f9d10e145a3ed750f0c86cfcafad5f141ea8)
(cherry picked from commit e33e95931b0d91c41433db68ddb19a8724b8ed80)
(cherry picked from commit 2cfc6519b7cbc758f8322fd7f7b84dfc6d14ae73)
(cherry picked from commit af8864373a65441c817dad1c3b696157c4024a7e)
(cherry picked from commit a0550ff3391f0575b72c3d0d1fdf1fcd9b51e4d6)
(cherry picked from commit 24dc0a5191a26fac0aef6b3a53fd58b9185edc88)
(cherry picked from commit e255eea2b48ad39eeb3eae227ca0d4fd4b667d99)
(cherry picked from commit 0c4f5afa7a37e6b805efb452b9d4166f7e2cec61)
(cherry picked from commit 42fce708d05d616ebbdfb2eecf384ad2fdaa1d7a)
(cherry picked from commit e7278c3c22b656e5730ec2ba0c1b4ee2ef6627ce)
(cherry picked from commit 0fb9ed7e0eb5db59ab5b574d3d69b4b161f50b0b)
(cherry picked from commit a98308aa4d6659f46f7f69996167f9c2f3c4e859)
(cherry picked from commit b8695fcbe04792cb75acb62fdf9c6dee237e8365)
(cherry picked from commit 4aee8719f57b40f8645905c10ba8966b29052295)
(cherry picked from commit 1c503c1ba7414fe0b960187bcc370b44c536ec7f)
(cherry picked from commit cf1ed8551e6a8abc56d3ed45b65b0e6ca4e1e891)
(cherry picked from commit c52459b088cd52bf3b11b68cadf95d738fd09269)
(cherry picked from commit 92cac277b28f9b68d3346f5dd463bc41c1952af6)
(cherry picked from commit 2c744f11189ca76de62be908069500d7dbfc2a8f)
(cherry picked from commit 1482cfabe56ea37b1e4dbf60d62a0008d38ba0a4)
2023-07-17 00:25:56 +02:00

214 lines
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"
)
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")
}
}
envWorkPath = getEnvFn("FORGEJO_WORK_DIR")
if envWorkPath != "" {
tmpWorkPath.Set(envWorkPath)
if !filepath.IsAbs(tmpWorkPath.Value) {
log.Fatal("FORGEJO_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")
}
}
envCustomPath = getEnvFn("FORGEJO_CUSTOM")
if envCustomPath != "" {
tmpCustomPath.Set(envCustomPath)
if !filepath.IsAbs(tmpCustomPath.Value) {
log.Fatal("FORGEJO_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") != "" || getEnvFn("FORGEJO_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
}