2025-12-08 09:49:07 +01:00
|
|
|
package config
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"os"
|
|
|
|
|
"path/filepath"
|
|
|
|
|
|
|
|
|
|
"github.com/spf13/viper"
|
|
|
|
|
"gopkg.in/yaml.v3"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Config struct {
|
|
|
|
|
Hosts map[string]HostConfig `yaml:"hosts"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type HostConfig struct {
|
2026-01-28 14:29:59 +01:00
|
|
|
Hostname string `yaml:"hostname"`
|
|
|
|
|
Token string `yaml:"token"`
|
|
|
|
|
User string `yaml:"user,omitempty"`
|
2025-12-08 09:49:07 +01:00
|
|
|
GitProtocol string `yaml:"git_protocol,omitempty"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func GetConfigDir() (string, error) {
|
|
|
|
|
home, err := os.UserHomeDir()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
return filepath.Join(home, ".config", "fgj"), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func GetConfigPath() (string, error) {
|
|
|
|
|
dir, err := GetConfigDir()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
return filepath.Join(dir, "config.yaml"), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Load() (*Config, error) {
|
|
|
|
|
path, err := GetConfigPath()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2025-12-08 10:14:47 +01:00
|
|
|
return LoadFromPath(path)
|
|
|
|
|
}
|
2025-12-08 09:49:07 +01:00
|
|
|
|
2025-12-08 10:14:47 +01:00
|
|
|
func LoadFromPath(path string) (*Config, error) {
|
2025-12-08 09:49:07 +01:00
|
|
|
data, err := os.ReadFile(path)
|
|
|
|
|
if err != nil {
|
|
|
|
|
if os.IsNotExist(err) {
|
|
|
|
|
return &Config{Hosts: make(map[string]HostConfig)}, nil
|
|
|
|
|
}
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var cfg Config
|
|
|
|
|
if err := yaml.Unmarshal(data, &cfg); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if cfg.Hosts == nil {
|
|
|
|
|
cfg.Hosts = make(map[string]HostConfig)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return &cfg, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *Config) Save() error {
|
|
|
|
|
path, err := GetConfigPath()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2025-12-08 10:14:47 +01:00
|
|
|
return c.SaveToPath(path)
|
|
|
|
|
}
|
2025-12-08 09:49:07 +01:00
|
|
|
|
2025-12-08 10:14:47 +01:00
|
|
|
func (c *Config) SaveToPath(path string) error {
|
2025-12-08 09:49:07 +01:00
|
|
|
dir := filepath.Dir(path)
|
|
|
|
|
if err := os.MkdirAll(dir, 0755); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data, err := yaml.Marshal(c)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return os.WriteFile(path, data, 0600)
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-05 12:47:28 +01:00
|
|
|
// GetHost resolves the hostname to use for API client creation.
|
|
|
|
|
// Priority order:
|
|
|
|
|
// 1. Explicitly provided hostname parameter
|
|
|
|
|
// 2. CLI flag (--hostname)
|
|
|
|
|
// 3. Environment variable (FGJ_HOST)
|
|
|
|
|
// 4. Auto-detected hostname from git remote
|
|
|
|
|
// 5. Default to codeberg.org
|
|
|
|
|
func (c *Config) GetHost(hostname string, detectedHost string) (HostConfig, error) {
|
2025-12-08 09:49:07 +01:00
|
|
|
if hostname == "" {
|
|
|
|
|
hostname = viper.GetString("hostname")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if hostname == "" {
|
|
|
|
|
hostname = os.Getenv("FGJ_HOST")
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-05 12:47:28 +01:00
|
|
|
if hostname == "" {
|
|
|
|
|
hostname = detectedHost
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-08 09:49:07 +01:00
|
|
|
if hostname == "" {
|
|
|
|
|
hostname = "codeberg.org"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
host, ok := c.Hosts[hostname]
|
|
|
|
|
if !ok {
|
|
|
|
|
return HostConfig{}, fmt.Errorf("no configuration found for host %s", hostname)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return host, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *Config) SetHost(hostname string, host HostConfig) {
|
|
|
|
|
if c.Hosts == nil {
|
|
|
|
|
c.Hosts = make(map[string]HostConfig)
|
|
|
|
|
}
|
|
|
|
|
c.Hosts[hostname] = host
|
|
|
|
|
}
|