mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-04 13:34:43 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			199 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			199 lines
		
	
	
		
			5.5 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: 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
 | 
						|
}
 |