fix: пути (db, worktree) и config.yaml резолвятся рядом с .exe, а не от CWD
This commit is contained in:
@@ -3,6 +3,7 @@ package config
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
@@ -11,11 +12,13 @@ import (
|
||||
|
||||
// Load читает конфиг из yaml-файла, подставляет ${VAR:-default}, накладывает
|
||||
// env-переменные (тег env) и валидирует. Если path пустой — ищет config.yaml
|
||||
// в CWD. Ошибка C4 если файл не существует (но не fatal при path="").
|
||||
// сначала в каталоге бинаря (exeDir), затем в CWD (fallback). Ошибка C4 если
|
||||
// файл не существует (но не fatal при path="").
|
||||
func Load(path string) (*Config, error) {
|
||||
noFile := false
|
||||
if path == "" {
|
||||
path = "config.yaml"
|
||||
// приоритет — рядом с .exe, фоллбэк на CWD
|
||||
path = firstExistingPath(filepath.Join(ExeDir(), "config.yaml"), "config.yaml")
|
||||
}
|
||||
raw, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
@@ -47,6 +50,40 @@ func Load(path string) (*Config, error) {
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
// ExeDir возвращает каталог исполняемого файла (бинаря). Используется для
|
||||
// поиска config.yaml и резолва относительных путей "рядом с .exe".
|
||||
func ExeDir() string {
|
||||
exe, err := os.Executable()
|
||||
if err != nil {
|
||||
return "."
|
||||
}
|
||||
return filepath.Dir(exe)
|
||||
}
|
||||
|
||||
// firstExistingPath возвращает первый существующий путь из списка.
|
||||
func firstExistingPath(paths ...string) string {
|
||||
for _, p := range paths {
|
||||
if _, err := os.Stat(p); err == nil {
|
||||
return p
|
||||
}
|
||||
}
|
||||
return paths[len(paths)-1] // фоллбэк на последний
|
||||
}
|
||||
|
||||
// ResolveExePaths подставляет относительные пути ПУТЕЙ (db, worktree) к каталогу
|
||||
// бинаря, чтобы они были стабильны независимо от CWD запуска. Абсолютные пути
|
||||
// не трогает. Вызывается после Load (в app.New), а не внутри Load, чтобы
|
||||
// персист-тесты дефолтов оставались независимыми от окружения.
|
||||
func (c *Config) ResolveExePaths() {
|
||||
base := ExeDir()
|
||||
if c.Paths.DB != "" && !filepath.IsAbs(c.Paths.DB) {
|
||||
c.Paths.DB = filepath.Join(base, c.Paths.DB)
|
||||
}
|
||||
if c.Paths.Worktree != "" && !filepath.IsAbs(c.Paths.Worktree) {
|
||||
c.Paths.Worktree = filepath.Join(base, c.Paths.Worktree)
|
||||
}
|
||||
}
|
||||
|
||||
// envLookup обрабатывает ${VAR:-default} в YAML.
|
||||
func envLookup(key string) string {
|
||||
parts := strings.SplitN(key, ":-", 2)
|
||||
|
||||
Reference in New Issue
Block a user