Skip to content

Commit 2474e43

Browse files
committed
Move config and logs under ~/.cloudcanal-cli
1 parent ae90fd9 commit 2474e43

5 files changed

Lines changed: 120 additions & 8 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ cloudcanal jobs list --type SYNC --output json
5555
配置文件默认保存在:
5656

5757
```text
58-
~/.cloudcanal/config.json
58+
~/.cloudcanal-cli/config.json
5959
```
6060

6161
最小配置示例:

docs/cloudcanal-cli-usage.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ curl -fsSL https://raw.githubusercontent.com/Arlowen/cloudcanal-openapi-cli/main
5050
首次启动会进入初始化向导,配置文件默认保存到:
5151

5252
```text
53-
~/.cloudcanal/config.json
53+
~/.cloudcanal-cli/config.json
5454
```
5555

5656
配置格式:

internal/config/config.go

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,17 +111,28 @@ func (c AppConfig) HTTPReadRetryBackoffMillisValue() int {
111111
}
112112

113113
type Service struct {
114-
path string
114+
path string
115+
defaultManaged bool
115116
}
116117

117118
func NewService(path string) *Service {
119+
defaultManaged := false
118120
if strings.TrimSpace(path) == "" {
119121
path = DefaultPath()
122+
defaultManaged = true
120123
}
121-
return &Service{path: path}
124+
return &Service{path: path, defaultManaged: defaultManaged}
122125
}
123126

124127
func DefaultPath() string {
128+
home, err := os.UserHomeDir()
129+
if err != nil {
130+
return ".cloudcanal-cli/config.json"
131+
}
132+
return filepath.Join(home, ".cloudcanal-cli", "config.json")
133+
}
134+
135+
func LegacyDefaultPath() string {
125136
home, err := os.UserHomeDir()
126137
if err != nil {
127138
return ".cloudcanal/config.json"
@@ -135,15 +146,32 @@ func (s *Service) Path() string {
135146

136147
func (s *Service) Exists() bool {
137148
_, err := os.Stat(s.path)
138-
return err == nil
149+
if err == nil {
150+
return true
151+
}
152+
if s.defaultManaged {
153+
_, legacyErr := os.Stat(LegacyDefaultPath())
154+
return legacyErr == nil
155+
}
156+
return false
139157
}
140158

141159
func (s *Service) Load() (AppConfig, error) {
142-
data, err := os.ReadFile(s.path)
160+
cfg, err := s.loadFromPath(s.path)
161+
if err == nil {
162+
return cfg, nil
163+
}
164+
if s.defaultManaged && errors.Is(err, os.ErrNotExist) {
165+
return s.loadFromLegacyPath()
166+
}
167+
return AppConfig{}, err
168+
}
169+
170+
func (s *Service) loadFromPath(path string) (AppConfig, error) {
171+
data, err := os.ReadFile(path)
143172
if err != nil {
144173
return AppConfig{}, err
145174
}
146-
147175
var cfg AppConfig
148176
if err := json.Unmarshal(data, &cfg); err != nil {
149177
return AppConfig{}, errors.New(i18n.T("config.invalidJSON"))
@@ -155,6 +183,19 @@ func (s *Service) Load() (AppConfig, error) {
155183
return cfg, nil
156184
}
157185

186+
func (s *Service) loadFromLegacyPath() (AppConfig, error) {
187+
legacyPath := LegacyDefaultPath()
188+
cfg, err := s.loadFromPath(legacyPath)
189+
if err != nil {
190+
return AppConfig{}, err
191+
}
192+
if err := s.Save(cfg); err == nil {
193+
_ = os.Remove(legacyPath)
194+
_ = os.Remove(filepath.Dir(legacyPath))
195+
}
196+
return cfg, nil
197+
}
198+
158199
func (s *Service) Save(cfg AppConfig) error {
159200
cfg = cfg.WithDefaults()
160201
if err := cfg.Validate(); err != nil {

scripts/all_build.sh

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ source "$SCRIPT_DIR/lib/log.sh"
88

99
BIN_DIR="$ROOT_DIR/bin"
1010
BIN_PATH="$BIN_DIR/cloudcanal"
11-
LOG_DIR="$(mktemp -d "${TMPDIR:-/tmp}/cloudcanal-openapi-cli-build.XXXXXX")"
11+
CLI_HOME_DIR="${HOME}/.cloudcanal-cli"
12+
LOG_ROOT_DIR="${CLI_HOME_DIR}/logs"
13+
14+
mkdir -p "$LOG_ROOT_DIR"
15+
LOG_DIR="$(mktemp -d "${LOG_ROOT_DIR}/cloudcanal-openapi-cli-build.XXXXXX")"
1216

1317
cleanup() {
1418
rm -rf "$LOG_DIR"

test/config/config_test.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,70 @@ func TestConfigNetworkSettingsDefaultsAndValidation(t *testing.T) {
7777
t.Fatal("Validate() error = nil, want non-nil for negative retry count")
7878
}
7979
}
80+
81+
func TestDefaultPathUsesCloudCanalCLIDirectory(t *testing.T) {
82+
home := t.TempDir()
83+
t.Setenv("HOME", home)
84+
85+
got := config.DefaultPath()
86+
want := filepath.Join(home, ".cloudcanal-cli", "config.json")
87+
if got != want {
88+
t.Fatalf("DefaultPath() = %q, want %q", got, want)
89+
}
90+
}
91+
92+
func TestServiceLoadMigratesLegacyDefaultConfig(t *testing.T) {
93+
home := t.TempDir()
94+
t.Setenv("HOME", home)
95+
96+
legacyPath := config.LegacyDefaultPath()
97+
if err := os.MkdirAll(filepath.Dir(legacyPath), 0o755); err != nil {
98+
t.Fatalf("MkdirAll() error = %v", err)
99+
}
100+
content := []byte(`{"apiBaseUrl":"https://cc.example.com","accessKey":"legacy-ak","secretKey":"legacy-sk","language":"zh"}`)
101+
if err := os.WriteFile(legacyPath, content, 0o600); err != nil {
102+
t.Fatalf("WriteFile() error = %v", err)
103+
}
104+
105+
service := config.NewService("")
106+
if !service.Exists() {
107+
t.Fatal("Exists() = false, want true when only legacy config exists")
108+
}
109+
110+
loaded, err := service.Load()
111+
if err != nil {
112+
t.Fatalf("Load() error = %v", err)
113+
}
114+
if loaded.APIBaseURL != "https://cc.example.com" || loaded.AccessKey != "legacy-ak" || loaded.SecretKey != "legacy-sk" || loaded.Language != "zh" {
115+
t.Fatalf("loaded config = %+v, want legacy values", loaded)
116+
}
117+
118+
newPath := config.DefaultPath()
119+
if _, err := os.Stat(newPath); err != nil {
120+
t.Fatalf("new config path stat error = %v", err)
121+
}
122+
if _, err := os.Stat(legacyPath); !os.IsNotExist(err) {
123+
t.Fatalf("legacy config still exists, stat err = %v", err)
124+
}
125+
}
126+
127+
func TestServiceLoadWithCustomPathDoesNotReadLegacyConfig(t *testing.T) {
128+
home := t.TempDir()
129+
t.Setenv("HOME", home)
130+
131+
legacyPath := config.LegacyDefaultPath()
132+
if err := os.MkdirAll(filepath.Dir(legacyPath), 0o755); err != nil {
133+
t.Fatalf("MkdirAll() error = %v", err)
134+
}
135+
if err := os.WriteFile(legacyPath, []byte(`{"apiBaseUrl":"https://cc.example.com","accessKey":"legacy-ak","secretKey":"legacy-sk"}`), 0o600); err != nil {
136+
t.Fatalf("WriteFile() error = %v", err)
137+
}
138+
139+
service := config.NewService(filepath.Join(t.TempDir(), "config.json"))
140+
if service.Exists() {
141+
t.Fatal("Exists() = true, want false for custom path without file")
142+
}
143+
if _, err := service.Load(); !os.IsNotExist(err) {
144+
t.Fatalf("Load() error = %v, want os.ErrNotExist", err)
145+
}
146+
}

0 commit comments

Comments
 (0)