// Package config provides shared configuration types for fetch_ml. // These types are embedded by per-command config structs. package config import ( "fmt" "os" "path/filepath" "strings" ) // RedisConfig holds Redis connection settings type RedisConfig struct { Addr string `yaml:"addr" json:"addr"` Password string `yaml:"password" json:"password"` DB int `yaml:"db" json:"db"` } // SSHConfig holds SSH connection settings type SSHConfig struct { Host string `yaml:"host" json:"host"` Port int `yaml:"port" json:"port"` User string `yaml:"user" json:"user"` KeyPath string `yaml:"key_path" json:"key_path"` KnownHosts string `yaml:"known_hosts" json:"known_hosts"` } // ExpandPath expands environment variables and tilde in a path // This remains in config package as it's a config parsing utility func ExpandPath(path string) string { if path == "" { return "" } expanded := os.ExpandEnv(path) if strings.HasPrefix(expanded, "~") { home, err := os.UserHomeDir() if err == nil { expanded = filepath.Join(home, expanded[1:]) } } return expanded } // ResolveConfigPath resolves a config file path, checking multiple locations func ResolveConfigPath(path string) (string, error) { candidates := []string{path} if !filepath.IsAbs(path) { candidates = append(candidates, filepath.Join("configs", path)) } var checked []string for _, candidate := range candidates { resolved := ExpandPath(candidate) checked = append(checked, resolved) if _, err := os.Stat(resolved); err == nil { return resolved, nil } } return "", fmt.Errorf("config file not found (looked in %s)", strings.Join(checked, ", ")) }