Skip to content

Commit e13d2f1

Browse files
author
Sisyphus Agent
committed
feat(config): 优化配置文件搜索路径和加载逻辑
- 新增 getConfigSearchPaths() 函数,返回所有可能的配置路径 - 使用 os.user.Current() 获取真实主目录 - 支持 os.UserHomeDir()、HOME、USERPROFILE 环境变量 - 添加相对路径 fallback - 自动去重搜索路径 - 新增 findConfigFile() 函数,查找第一个存在的配置文件 - 重构 Init() 函数: - 优先尝试多路径配置文件加载 - 改进环境变量处理逻辑作为中间优先级 - 添加详细的调试信息输出 - 改进 getConfigPath() 函数的 fallback 逻辑 修复问题:在某些环境下(如 WSL)os.UserHomeDir() 可能返回不正确的主目录
1 parent a5b18dc commit e13d2f1

1 file changed

Lines changed: 91 additions & 21 deletions

File tree

oho/internal/config/config.go

Lines changed: 91 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"encoding/json"
55
"fmt"
66
"os"
7+
"os/user"
78
"path/filepath"
89

910
"github.com/spf13/pflag"
@@ -32,29 +33,38 @@ func Init() error {
3233
JSON: false,
3334
}
3435

35-
// 2. 检查配置文件是否存在
36-
configFile := getConfigPath()
37-
if data, err := os.ReadFile(configFile); err == nil {
38-
// 配置文件存在,加载配置
39-
if err := json.Unmarshal(data, cfg); err != nil {
40-
return fmt.Errorf("解析配置文件失败:%w", err)
36+
// 2. 加载配置文件(尝试多个可能的位置)
37+
configFile := findConfigFile()
38+
if configFile != "" {
39+
if data, err := os.ReadFile(configFile); err == nil {
40+
fmt.Fprintf(os.Stderr, "[config] 成功读取配置文件: %s\n", configFile)
41+
if err := json.Unmarshal(data, cfg); err != nil {
42+
return fmt.Errorf("解析配置文件失败:%w", err)
43+
}
4144
}
4245
} else {
43-
// 3. 配置文件不存在时,使用环境变量
44-
if envHost := os.Getenv("OPENCODE_SERVER_HOST"); envHost != "" {
45-
cfg.Host = envHost
46-
}
47-
if envPort := os.Getenv("OPENCODE_SERVER_PORT"); envPort != "" {
48-
_, _ = fmt.Sscanf(envPort, "%d", &cfg.Port)
49-
}
50-
if envUsername := os.Getenv("OPENCODE_SERVER_USERNAME"); envUsername != "" {
51-
cfg.Username = envUsername
52-
}
53-
if envPassword := os.Getenv("OPENCODE_SERVER_PASSWORD"); envPassword != "" {
54-
cfg.Password = envPassword
46+
fmt.Fprintf(os.Stderr, "[config] 配置文件不存在,请创建或设置环境变量\n")
47+
fmt.Fprintf(os.Stderr, "[config] 尝试过的路径:\n")
48+
for _, p := range getConfigSearchPaths() {
49+
fmt.Fprintf(os.Stderr, "[config] - %s\n", p)
5550
}
5651
}
5752

53+
// 3. 环境变量覆盖配置文件(始终检查,作为中间优先级)
54+
// 优先级:命令行标志 > 环境变量 > 配置文件 > 默认值
55+
if envHost := os.Getenv("OPENCODE_SERVER_HOST"); envHost != "" {
56+
cfg.Host = envHost
57+
}
58+
if envPort := os.Getenv("OPENCODE_SERVER_PORT"); envPort != "" {
59+
_, _ = fmt.Sscanf(envPort, "%d", &cfg.Port)
60+
}
61+
if envUsername := os.Getenv("OPENCODE_SERVER_USERNAME"); envUsername != "" {
62+
cfg.Username = envUsername
63+
}
64+
if envPassword := os.Getenv("OPENCODE_SERVER_PASSWORD"); envPassword != "" {
65+
cfg.Password = envPassword
66+
}
67+
5868
return nil
5969
}
6070

@@ -101,8 +111,68 @@ func Save() error {
101111
return os.WriteFile(configFile, data, 0600)
102112
}
103113

104-
// getConfigPath 获取配置文件路径
114+
// getConfigSearchPaths 返回所有可能配置文件的搜索路径
115+
func getConfigSearchPaths() []string {
116+
var paths []string
117+
118+
// 方式1: 操作系统用户数据库中的真实主目录(不受环境变量影响)
119+
if usr, err := user.Current(); err == nil && usr.HomeDir != "" {
120+
paths = append(paths, filepath.Join(usr.HomeDir, ".config", "oho", "config.json"))
121+
}
122+
123+
// 方式2: os.UserHomeDir()(某些情况下会读取 HOME 环境变量)
124+
if home, err := os.UserHomeDir(); err == nil && home != "" {
125+
paths = append(paths, filepath.Join(home, ".config", "oho", "config.json"))
126+
}
127+
128+
// 方式3: $HOME 环境变量
129+
if home := os.Getenv("HOME"); home != "" {
130+
paths = append(paths, filepath.Join(home, ".config", "oho", "config.json"))
131+
}
132+
133+
// 方式4: $USERPROFILE (Windows)
134+
if home := os.Getenv("USERPROFILE"); home != "" {
135+
paths = append(paths, filepath.Join(home, ".config", "oho", "config.json"))
136+
}
137+
138+
// 方式5: 相对于当前工作目录
139+
paths = append(paths, filepath.Join(".", ".config", "oho", "config.json"))
140+
141+
// 去重
142+
seen := make(map[string]bool)
143+
var unique []string
144+
for _, p := range paths {
145+
if !seen[p] {
146+
seen[p] = true
147+
unique = append(unique, p)
148+
}
149+
}
150+
return unique
151+
}
152+
153+
// findConfigFile 查找配置文件,返回第一个存在的路径
154+
func findConfigFile() string {
155+
for _, p := range getConfigSearchPaths() {
156+
if _, err := os.Stat(p); err == nil {
157+
return p
158+
}
159+
}
160+
return ""
161+
}
162+
163+
// getConfigPath 获取配置文件路径(用于保存)
105164
func getConfigPath() string {
106-
home, _ := os.UserHomeDir()
107-
return filepath.Join(home, ".config", "oho", "config.json")
165+
// 优先使用 os.UserHomeDir() 对应的路径
166+
if home, err := os.UserHomeDir(); err == nil && home != "" {
167+
return filepath.Join(home, ".config", "oho", "config.json")
168+
}
169+
// fallback 到 $HOME
170+
if home := os.Getenv("HOME"); home != "" {
171+
return filepath.Join(home, ".config", "oho", "config.json")
172+
}
173+
// fallback 到 $USERPROFILE
174+
if home := os.Getenv("USERPROFILE"); home != "" {
175+
return filepath.Join(home, ".config", "oho", "config.json")
176+
}
177+
return filepath.Join(".", ".config", "oho", "config.json")
108178
}

0 commit comments

Comments
 (0)