diff options
Diffstat (limited to 'modules/setting')
-rw-r--r-- | modules/setting/config_provider.go | 80 | ||||
-rw-r--r-- | modules/setting/config_provider_test.go | 11 | ||||
-rw-r--r-- | modules/setting/path.go | 191 | ||||
-rw-r--r-- | modules/setting/path_test.go | 151 | ||||
-rw-r--r-- | modules/setting/server.go | 2 | ||||
-rw-r--r-- | modules/setting/setting.go | 131 |
6 files changed, 398 insertions, 168 deletions
diff --git a/modules/setting/config_provider.go b/modules/setting/config_provider.go index deec5cc586..94dd989850 100644 --- a/modules/setting/config_provider.go +++ b/modules/setting/config_provider.go @@ -55,15 +55,15 @@ type ConfigProvider interface { DisableSaving() PrepareSaving() (ConfigProvider, error) + IsLoadedFromEmpty() bool } type iniConfigProvider struct { - opts *Options + file string ini *ini.File - disableSaving bool - - newFile bool // whether the file has not existed previously + disableSaving bool // disable the "Save" method because the config options could be polluted + loadedFromEmpty bool // whether the file has not existed previously } type iniConfigSection struct { @@ -182,53 +182,43 @@ func NewConfigProviderFromData(configContent string) (ConfigProvider, error) { } cfg.NameMapper = ini.SnackCase return &iniConfigProvider{ - ini: cfg, - newFile: true, + ini: cfg, + loadedFromEmpty: true, }, nil } -type Options struct { - CustomConf string // the ini file path - AllowEmpty bool // whether not finding configuration files is allowed - ExtraConfig string - - DisableLoadCommonSettings bool // only used by "Init()", not used by "NewConfigProvider()" -} - // NewConfigProviderFromFile load configuration from file. // NOTE: do not print any log except error. -func NewConfigProviderFromFile(opts *Options) (ConfigProvider, error) { +func NewConfigProviderFromFile(file string, extraConfigs ...string) (ConfigProvider, error) { cfg := ini.Empty(ini.LoadOptions{KeyValueDelimiterOnWrite: " = "}) - newFile := true + loadedFromEmpty := true - if opts.CustomConf != "" { - isFile, err := util.IsFile(opts.CustomConf) + if file != "" { + isFile, err := util.IsFile(file) if err != nil { - return nil, fmt.Errorf("unable to check if %s is a file. Error: %v", opts.CustomConf, err) + return nil, fmt.Errorf("unable to check if %q is a file. Error: %v", file, err) } if isFile { - if err := cfg.Append(opts.CustomConf); err != nil { - return nil, fmt.Errorf("failed to load custom conf '%s': %v", opts.CustomConf, err) + if err = cfg.Append(file); err != nil { + return nil, fmt.Errorf("failed to load config file %q: %v", file, err) } - newFile = false + loadedFromEmpty = false } } - if newFile && !opts.AllowEmpty { - return nil, fmt.Errorf("unable to find configuration file: %q, please ensure you are running in the correct environment or set the correct configuration file with -c", CustomConf) - } - - if opts.ExtraConfig != "" { - if err := cfg.Append([]byte(opts.ExtraConfig)); err != nil { - return nil, fmt.Errorf("unable to append more config: %v", err) + if len(extraConfigs) > 0 { + for _, s := range extraConfigs { + if err := cfg.Append([]byte(s)); err != nil { + return nil, fmt.Errorf("unable to append more config: %v", err) + } } } cfg.NameMapper = ini.SnackCase return &iniConfigProvider{ - opts: opts, - ini: cfg, - newFile: newFile, + file: file, + ini: cfg, + loadedFromEmpty: loadedFromEmpty, }, nil } @@ -266,20 +256,17 @@ func (p *iniConfigProvider) Save() error { if p.disableSaving { return errDisableSaving } - filename := p.opts.CustomConf + filename := p.file if filename == "" { - if !p.opts.AllowEmpty { - return fmt.Errorf("custom config path must not be empty") - } - return nil + return fmt.Errorf("config file path must not be empty") } - if p.newFile { + if p.loadedFromEmpty { if err := os.MkdirAll(filepath.Dir(filename), os.ModePerm); err != nil { - return fmt.Errorf("failed to create '%s': %v", filename, err) + return fmt.Errorf("failed to create %q: %v", filename, err) } } if err := p.ini.SaveTo(filename); err != nil { - return fmt.Errorf("failed to save '%s': %v", filename, err) + return fmt.Errorf("failed to save %q: %v", filename, err) } // Change permissions to be more restrictive @@ -313,11 +300,14 @@ func (p *iniConfigProvider) DisableSaving() { // it makes the "Save" outputs a lot of garbage options // After the INI package gets refactored, no "MustXxx" pollution, this workaround can be dropped. func (p *iniConfigProvider) PrepareSaving() (ConfigProvider, error) { - cfgFile := p.opts.CustomConf - if cfgFile == "" { + if p.file == "" { return nil, errors.New("no config file to save") } - return NewConfigProviderFromFile(p.opts) + return NewConfigProviderFromFile(p.file) +} + +func (p *iniConfigProvider) IsLoadedFromEmpty() bool { + return p.loadedFromEmpty } func mustMapSetting(rootCfg ConfigProvider, sectionName string, setting any) { @@ -356,8 +346,8 @@ func NewConfigProviderForLocale(source any, others ...any) (ConfigProvider, erro } iniFile.BlockMode = false return &iniConfigProvider{ - ini: iniFile, - newFile: true, + ini: iniFile, + loadedFromEmpty: true, }, nil } diff --git a/modules/setting/config_provider_test.go b/modules/setting/config_provider_test.go index c5c5196e04..7e7c6be2bb 100644 --- a/modules/setting/config_provider_test.go +++ b/modules/setting/config_provider_test.go @@ -67,13 +67,14 @@ key = 123 } func TestNewConfigProviderFromFile(t *testing.T) { - _, err := NewConfigProviderFromFile(&Options{CustomConf: "no-such.ini", AllowEmpty: false}) - assert.ErrorContains(t, err, "unable to find configuration file") + cfg, err := NewConfigProviderFromFile("no-such.ini") + assert.NoError(t, err) + assert.True(t, cfg.IsLoadedFromEmpty()) // load non-existing file and save testFile := t.TempDir() + "/test.ini" testFile1 := t.TempDir() + "/test1.ini" - cfg, err := NewConfigProviderFromFile(&Options{CustomConf: testFile, AllowEmpty: true}) + cfg, err = NewConfigProviderFromFile(testFile) assert.NoError(t, err) sec, _ := cfg.NewSection("foo") @@ -91,7 +92,7 @@ func TestNewConfigProviderFromFile(t *testing.T) { assert.Equal(t, "[foo]\nk1 = a\nk2 = b\n", string(bs)) // load existing file and save - cfg, err = NewConfigProviderFromFile(&Options{CustomConf: testFile, AllowEmpty: true}) + cfg, err = NewConfigProviderFromFile(testFile) assert.NoError(t, err) assert.Equal(t, "a", cfg.Section("foo").Key("k1").String()) sec, _ = cfg.NewSection("bar") @@ -123,7 +124,7 @@ func TestNewConfigProviderForLocale(t *testing.T) { func TestDisableSaving(t *testing.T) { testFile := t.TempDir() + "/test.ini" _ = os.WriteFile(testFile, []byte("k1=a\nk2=b"), 0o644) - cfg, err := NewConfigProviderFromFile(&Options{CustomConf: testFile, AllowEmpty: true}) + cfg, err := NewConfigProviderFromFile(testFile) assert.NoError(t, err) cfg.DisableSaving() diff --git a/modules/setting/path.go b/modules/setting/path.go new file mode 100644 index 0000000000..91bb2e9bb7 --- /dev/null +++ b/modules/setting/path.go @@ -0,0 +1,191 @@ +// 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) { + 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 + + LoadCommonSettings() +} diff --git a/modules/setting/path_test.go b/modules/setting/path_test.go new file mode 100644 index 0000000000..fc6a2116dc --- /dev/null +++ b/modules/setting/path_test.go @@ -0,0 +1,151 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package setting + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" +) + +type envVars map[string]string + +func (e envVars) Getenv(key string) string { + return e[key] +} + +func TestInitWorkPathAndCommonConfig(t *testing.T) { + testInit := func(defaultWorkPath, defaultCustomPath, defaultCustomConf string) { + AppWorkPathMismatch = false + AppWorkPath = defaultWorkPath + appWorkPathBuiltin = defaultWorkPath + CustomPath = defaultCustomPath + customPathBuiltin = defaultCustomPath + CustomConf = defaultCustomConf + customConfBuiltin = defaultCustomConf + } + + fp := filepath.Join + + tmpDir := t.TempDir() + dirFoo := fp(tmpDir, "foo") + dirBar := fp(tmpDir, "bar") + dirXxx := fp(tmpDir, "xxx") + dirYyy := fp(tmpDir, "yyy") + + t.Run("Default", func(t *testing.T) { + testInit(dirFoo, "", "") + InitWorkPathAndCommonConfig(envVars{}.Getenv, ArgWorkPathAndCustomConf{}) + assert.Equal(t, dirFoo, AppWorkPath) + assert.Equal(t, fp(dirFoo, "custom"), CustomPath) + assert.Equal(t, fp(dirFoo, "custom/conf/app.ini"), CustomConf) + }) + + t.Run("WorkDir(env)", func(t *testing.T) { + testInit(dirFoo, "", "") + InitWorkPathAndCommonConfig(envVars{"GITEA_WORK_DIR": dirBar}.Getenv, ArgWorkPathAndCustomConf{}) + assert.Equal(t, dirBar, AppWorkPath) + assert.Equal(t, fp(dirBar, "custom"), CustomPath) + assert.Equal(t, fp(dirBar, "custom/conf/app.ini"), CustomConf) + }) + + t.Run("WorkDir(env,arg)", func(t *testing.T) { + testInit(dirFoo, "", "") + InitWorkPathAndCommonConfig(envVars{"GITEA_WORK_DIR": dirBar}.Getenv, ArgWorkPathAndCustomConf{WorkPath: dirXxx}) + assert.Equal(t, dirXxx, AppWorkPath) + assert.Equal(t, fp(dirXxx, "custom"), CustomPath) + assert.Equal(t, fp(dirXxx, "custom/conf/app.ini"), CustomConf) + }) + + t.Run("CustomPath(env)", func(t *testing.T) { + testInit(dirFoo, "", "") + InitWorkPathAndCommonConfig(envVars{"GITEA_CUSTOM": fp(dirBar, "custom1")}.Getenv, ArgWorkPathAndCustomConf{}) + assert.Equal(t, dirFoo, AppWorkPath) + assert.Equal(t, fp(dirBar, "custom1"), CustomPath) + assert.Equal(t, fp(dirBar, "custom1/conf/app.ini"), CustomConf) + }) + + t.Run("CustomPath(env,arg)", func(t *testing.T) { + testInit(dirFoo, "", "") + InitWorkPathAndCommonConfig(envVars{"GITEA_CUSTOM": fp(dirBar, "custom1")}.Getenv, ArgWorkPathAndCustomConf{CustomPath: "custom2"}) + assert.Equal(t, dirFoo, AppWorkPath) + assert.Equal(t, fp(dirFoo, "custom2"), CustomPath) + assert.Equal(t, fp(dirFoo, "custom2/conf/app.ini"), CustomConf) + }) + + t.Run("CustomConf", func(t *testing.T) { + testInit(dirFoo, "", "") + InitWorkPathAndCommonConfig(envVars{}.Getenv, ArgWorkPathAndCustomConf{CustomConf: "app1.ini"}) + assert.Equal(t, dirFoo, AppWorkPath) + cwd, _ := os.Getwd() + assert.Equal(t, fp(cwd, "app1.ini"), CustomConf) + + testInit(dirFoo, "", "") + InitWorkPathAndCommonConfig(envVars{}.Getenv, ArgWorkPathAndCustomConf{CustomConf: fp(dirBar, "app1.ini")}) + assert.Equal(t, dirFoo, AppWorkPath) + assert.Equal(t, fp(dirBar, "app1.ini"), CustomConf) + }) + + t.Run("CustomConfOverrideWorkPath", func(t *testing.T) { + iniWorkPath := fp(tmpDir, "app-workpath.ini") + _ = os.WriteFile(iniWorkPath, []byte("WORK_PATH="+dirXxx), 0o644) + + testInit(dirFoo, "", "") + InitWorkPathAndCommonConfig(envVars{}.Getenv, ArgWorkPathAndCustomConf{CustomConf: iniWorkPath}) + assert.Equal(t, dirXxx, AppWorkPath) + assert.Equal(t, fp(dirXxx, "custom"), CustomPath) + assert.Equal(t, iniWorkPath, CustomConf) + assert.False(t, AppWorkPathMismatch) + + testInit(dirFoo, "", "") + InitWorkPathAndCommonConfig(envVars{"GITEA_WORK_DIR": dirBar}.Getenv, ArgWorkPathAndCustomConf{CustomConf: iniWorkPath}) + assert.Equal(t, dirXxx, AppWorkPath) + assert.Equal(t, fp(dirXxx, "custom"), CustomPath) + assert.Equal(t, iniWorkPath, CustomConf) + assert.True(t, AppWorkPathMismatch) + + testInit(dirFoo, "", "") + InitWorkPathAndCommonConfig(envVars{}.Getenv, ArgWorkPathAndCustomConf{WorkPath: dirBar, CustomConf: iniWorkPath}) + assert.Equal(t, dirXxx, AppWorkPath) + assert.Equal(t, fp(dirXxx, "custom"), CustomPath) + assert.Equal(t, iniWorkPath, CustomConf) + assert.True(t, AppWorkPathMismatch) + }) + + t.Run("Builtin", func(t *testing.T) { + testInit(dirFoo, dirBar, dirXxx) + InitWorkPathAndCommonConfig(envVars{}.Getenv, ArgWorkPathAndCustomConf{}) + assert.Equal(t, dirFoo, AppWorkPath) + assert.Equal(t, dirBar, CustomPath) + assert.Equal(t, dirXxx, CustomConf) + + testInit(dirFoo, "custom1", "cfg.ini") + InitWorkPathAndCommonConfig(envVars{}.Getenv, ArgWorkPathAndCustomConf{}) + assert.Equal(t, dirFoo, AppWorkPath) + assert.Equal(t, fp(dirFoo, "custom1"), CustomPath) + assert.Equal(t, fp(dirFoo, "custom1/cfg.ini"), CustomConf) + + testInit(dirFoo, "custom1", "cfg.ini") + InitWorkPathAndCommonConfig(envVars{"GITEA_WORK_DIR": dirYyy}.Getenv, ArgWorkPathAndCustomConf{}) + assert.Equal(t, dirYyy, AppWorkPath) + assert.Equal(t, fp(dirYyy, "custom1"), CustomPath) + assert.Equal(t, fp(dirYyy, "custom1/cfg.ini"), CustomConf) + + testInit(dirFoo, "custom1", "cfg.ini") + InitWorkPathAndCommonConfig(envVars{"GITEA_CUSTOM": dirYyy}.Getenv, ArgWorkPathAndCustomConf{}) + assert.Equal(t, dirFoo, AppWorkPath) + assert.Equal(t, dirYyy, CustomPath) + assert.Equal(t, fp(dirYyy, "cfg.ini"), CustomConf) + + iniWorkPath := fp(tmpDir, "app-workpath.ini") + _ = os.WriteFile(iniWorkPath, []byte("WORK_PATH="+dirXxx), 0o644) + testInit(dirFoo, "custom1", "cfg.ini") + InitWorkPathAndCommonConfig(envVars{}.Getenv, ArgWorkPathAndCustomConf{CustomConf: iniWorkPath}) + assert.Equal(t, dirXxx, AppWorkPath) + assert.Equal(t, fp(dirXxx, "custom1"), CustomPath) + assert.Equal(t, iniWorkPath, CustomConf) + }) +} diff --git a/modules/setting/server.go b/modules/setting/server.go index d937faca10..7c033bcc6b 100644 --- a/modules/setting/server.go +++ b/modules/setting/server.go @@ -61,6 +61,7 @@ var ( AssetVersion string // Server settings + Protocol Scheme UseProxyProtocol bool // `ini:"USE_PROXY_PROTOCOL"` ProxyProtocolTLSBridging bool //`ini:"PROXY_PROTOCOL_TLS_BRIDGING"` @@ -324,7 +325,6 @@ func loadServerFrom(rootCfg ConfigProvider) { StaticCacheTime = sec.Key("STATIC_CACHE_TIME").MustDuration(6 * time.Hour) AppDataPath = sec.Key("APP_DATA_PATH").MustString(path.Join(AppWorkPath, "data")) if !filepath.IsAbs(AppDataPath) { - log.Info("The provided APP_DATA_PATH: %s is not absolute - it will be made absolute against the work path: %s", AppDataPath, AppWorkPath) AppDataPath = filepath.ToSlash(filepath.Join(AppWorkPath, AppDataPath)) } diff --git a/modules/setting/setting.go b/modules/setting/setting.go index 6eaddbe2b5..0d69847dbe 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -5,12 +5,8 @@ package setting import ( - "errors" "fmt" "os" - "os/exec" - "path" - "path/filepath" "runtime" "strings" "time" @@ -28,19 +24,9 @@ var ( // AppStartTime store time gitea has started AppStartTime time.Time - // 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. - // - // AppWorkPath is used as the base path for several other paths. - AppWorkPath string - // Other global setting objects CfgProvider ConfigProvider - CustomPath string // Custom directory path - CustomConf string RunMode string RunUser string IsProd bool @@ -51,62 +37,6 @@ var ( IsInTesting = false ) -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: 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 getWorkPath(appPath string) string { - workPath := AppWorkPath - - if giteaWorkPath, ok := os.LookupEnv("GITEA_WORK_DIR"); ok { - workPath = giteaWorkPath - } - if len(workPath) == 0 { - i := strings.LastIndex(appPath, "/") - if i == -1 { - workPath = appPath - } else { - workPath = appPath[:i] - } - } - workPath = strings.ReplaceAll(workPath, "\\", "/") - if !filepath.IsAbs(workPath) { - log.Info("Provided work path %s is not absolute - will be made absolute against the current working directory", workPath) - - absPath, err := filepath.Abs(workPath) - if err != nil { - log.Error("Unable to absolute %s against the current working directory %v. Will absolute against the AppPath %s", workPath, err, appPath) - workPath = filepath.Join(appPath, workPath) - } else { - workPath = absPath - } - } - return strings.ReplaceAll(workPath, "\\", "/") -} - func init() { IsWindows = runtime.GOOS == "windows" if AppVer == "" { @@ -116,12 +46,6 @@ func init() { // We can rely on log.CanColorStdout being set properly because modules/log/console_windows.go comes before modules/setting/setting.go lexicographically // By default set this logger at Info - we'll change it later, but we need to start with something. log.SetConsoleLogger(log.DEFAULT, "console", log.INFO) - - var err error - if AppPath, err = getAppPath(); err != nil { - log.Fatal("Failed to get app path: %v", err) - } - AppWorkPath = getWorkPath(AppPath) } // IsRunUserMatchCurrentUser returns false if configured run user does not match @@ -137,36 +61,6 @@ func IsRunUserMatchCurrentUser(runUser string) (string, bool) { return currentUser, runUser == currentUser } -// SetCustomPathAndConf will set CustomPath and CustomConf with reference to the -// GITEA_CUSTOM environment variable and with provided overrides before stepping -// back to the default -func SetCustomPathAndConf(providedCustom, providedConf, providedWorkPath string) { - if len(providedWorkPath) != 0 { - AppWorkPath = filepath.ToSlash(providedWorkPath) - } - if giteaCustom, ok := os.LookupEnv("GITEA_CUSTOM"); ok { - CustomPath = giteaCustom - } - if len(providedCustom) != 0 { - CustomPath = providedCustom - } - if len(CustomPath) == 0 { - CustomPath = path.Join(AppWorkPath, "custom") - } else if !filepath.IsAbs(CustomPath) { - CustomPath = path.Join(AppWorkPath, CustomPath) - } - - if len(providedConf) != 0 { - CustomConf = providedConf - } - if len(CustomConf) == 0 { - CustomConf = path.Join(CustomPath, "conf/app.ini") - } else if !filepath.IsAbs(CustomConf) { - CustomConf = path.Join(CustomPath, CustomConf) - log.Warn("Using 'custom' directory as relative origin for configuration file: '%s'", CustomConf) - } -} - // PrepareAppDataPath creates app data directory if necessary func PrepareAppDataPath() error { // FIXME: There are too many calls to MkdirAll in old code. It is incorrect. @@ -196,20 +90,23 @@ func PrepareAppDataPath() error { return nil } -func Init(opts *Options) { - if opts.CustomConf == "" { - opts.CustomConf = CustomConf - } +func InitCfgProvider(file string, extraConfigs ...string) { var err error - CfgProvider, err = NewConfigProviderFromFile(opts) + if CfgProvider, err = NewConfigProviderFromFile(file, extraConfigs...); err != nil { + log.Fatal("Unable to init config provider from %q: %v", file, err) + } CfgProvider.DisableSaving() // do not allow saving the CfgProvider into file, it will be polluted by the "MustXxx" calls - if err != nil { - log.Fatal("newConfigProviderFromFile[%v]: %v", opts, err) +} + +func MustInstalled() { + if !InstallLock { + log.Fatal(`Unable to load config file for a installed Gitea instance, you should either use "--config" to set your config file (app.ini), or run "gitea web" command to install Gitea.`) } - if !opts.DisableLoadCommonSettings { - if err := loadCommonSettingsFrom(CfgProvider); err != nil { - log.Fatal("loadCommonSettingsFrom[%v]: %v", opts, err) - } +} + +func LoadCommonSettings() { + if err := loadCommonSettingsFrom(CfgProvider); err != nil { + log.Fatal("Unable to load settings from config: %v", err) } } |