|
4 | 4 | "encoding/json" |
5 | 5 | "fmt" |
6 | 6 | "os" |
| 7 | + "os/user" |
7 | 8 | "path/filepath" |
8 | 9 |
|
9 | 10 | "github.com/spf13/pflag" |
@@ -32,29 +33,38 @@ func Init() error { |
32 | 33 | JSON: false, |
33 | 34 | } |
34 | 35 |
|
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 | + } |
41 | 44 | } |
42 | 45 | } 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) |
55 | 50 | } |
56 | 51 | } |
57 | 52 |
|
| 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 | + |
58 | 68 | return nil |
59 | 69 | } |
60 | 70 |
|
@@ -101,8 +111,68 @@ func Save() error { |
101 | 111 | return os.WriteFile(configFile, data, 0600) |
102 | 112 | } |
103 | 113 |
|
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 获取配置文件路径(用于保存) |
105 | 164 | 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") |
108 | 178 | } |
0 commit comments