package main import ( "encoding/json" "errors" "fmt" "os" "path/filepath" "strings" ) const ( BootstrapReady = "ready" BootstrapSetup = "setup_required" BootstrapRecovery = "recovery_required" ) type BootstrapConfig struct { DatabasePath string `json:"databasePath"` Initialized bool `json:"initialized"` } type BootstrapStatus struct { State string `json:"state"` DatabasePath string `json:"databasePath"` DefaultPath string `json:"defaultPath"` ErrorCode string `json:"errorCode,omitempty"` ErrorDetail string `json:"errorDetail,omitempty"` } type CodedError struct{ Code, Detail string } func (e *CodedError) Error() string { if e.Detail == "" { return e.Code } return e.Code + ": " + e.Detail } func coded(code string, err error) error { if err == nil { return &CodedError{Code: code} } return &CodedError{Code: code, Detail: err.Error()} } func bootstrapPath() (string, error) { d, e := os.UserConfigDir() if e != nil { return "", e } return filepath.Join(d, "CodeCount", "bootstrap.json"), nil } func readBootstrap(path string) (BootstrapConfig, error) { b, e := os.ReadFile(path) if e != nil { return BootstrapConfig{}, e } var c BootstrapConfig if e = json.Unmarshal(b, &c); e != nil { return c, e } if !c.Initialized || strings.TrimSpace(c.DatabasePath) == "" { return c, errors.New("invalid bootstrap configuration") } return c, nil } func writeBootstrap(path string, c BootstrapConfig) error { if e := os.MkdirAll(filepath.Dir(path), 0755); e != nil { return e } b, e := json.MarshalIndent(c, "", " ") if e != nil { return e } tmp := path + ".tmp" if e = os.WriteFile(tmp, b, 0600); e != nil { return e } if e = os.Rename(tmp, path); e != nil { _ = os.Remove(tmp) return e } return nil } func createValidatedStore(target string) (*Store, error) { target = filepath.Clean(strings.TrimSpace(target)) if target == "" { return nil, coded("DB_PATH_REQUIRED", nil) } dir := filepath.Dir(target) if e := os.MkdirAll(dir, 0755); e != nil { return nil, coded("DB_DIRECTORY_UNWRITABLE", e) } probe := filepath.Join(dir, ".code-count-write-test") if e := os.WriteFile(probe, []byte("ok"), 0600); e != nil { return nil, coded("DB_DIRECTORY_UNWRITABLE", e) } _ = os.Remove(probe) if _, e := os.Stat(target); e == nil { return OpenStore(target) } else if !os.IsNotExist(e) { return nil, coded("DB_FILE_UNREADABLE", e) } tmp := target + ".initializing" _ = os.Remove(tmp) _ = os.Remove(tmp + "-wal") _ = os.Remove(tmp + "-shm") s, e := OpenStore(tmp) if e != nil { return nil, coded("DB_INITIALIZE_FAILED", e) } var result string e = s.db.QueryRow(`PRAGMA integrity_check`).Scan(&result) _ = s.db.Close() if e != nil || result != "ok" { _ = os.Remove(tmp) return nil, coded("DB_INTEGRITY_FAILED", e) } if e = os.Rename(tmp, target); e != nil { _ = os.Remove(tmp) return nil, coded("DB_INITIALIZE_FAILED", e) } s, e = OpenStore(target) if e != nil { return nil, coded("DB_OPEN_FAILED", e) } return s, nil } func bootstrapFailure(defaultPath, path string, e error) BootstrapStatus { code := "DB_OPEN_FAILED" var ce *CodedError if errors.As(e, &ce) { code = ce.Code } return BootstrapStatus{State: BootstrapRecovery, DatabasePath: path, DefaultPath: defaultPath, ErrorCode: code, ErrorDetail: fmt.Sprint(e)} }