hugin/cli/internal/config/config.go
2026-10-27 08:33:21 +01:00

92 lines
2.2 KiB
Go

// Package config liest und schreibt .hugin.yaml (→ KONZEPT.md 11.2).
package config
import (
"errors"
"fmt"
"io/fs"
"os"
"path/filepath"
"gopkg.in/yaml.v3"
)
const Filename = ".hugin.yaml"
type Config struct {
Server string `yaml:"server"`
Project string `yaml:"project"`
// "auto" oder Liste aus claude, opencode
Tools Tools `yaml:"tools"`
OpencodeReadsClaude *bool `yaml:"opencode_reads_claude,omitempty"`
// warn | strict
ToolCheck string `yaml:"tool_check,omitempty"`
Packages []string `yaml:"packages"`
Unsubscribed []string `yaml:"unsubscribed"`
}
// Tools ist entweder automatisch (leer) oder eine feste Liste.
type Tools struct {
Auto bool
List []string
}
func (w Tools) MarshalYAML() (any, error) {
if w.Auto || len(w.List) == 0 {
return "auto", nil
}
return w.List, nil
}
func (w *Tools) UnmarshalYAML(n *yaml.Node) error {
if n.Kind == yaml.ScalarNode {
if n.Value != "auto" {
return fmt.Errorf("tools: %q, erwartet auto oder eine Liste", n.Value)
}
*w = Tools{Auto: true}
return nil
}
var items []string
if err := n.Decode(&items); err != nil {
return err
}
for _, name := range items {
if name != "claude" && name != "opencode" {
return fmt.Errorf("tools: unbekanntes Werkzeug %q", name)
}
}
*w = Tools{List: items}
return nil
}
func (k *Config) ReadsClaude() bool { return k.OpencodeReadsClaude == nil || *k.OpencodeReadsClaude }
func (k *Config) Strict() bool { return k.ToolCheck == "strict" }
func Load(repo string) (*Config, error) {
raw, err := os.ReadFile(filepath.Join(repo, Filename))
if errors.Is(err, fs.ErrNotExist) {
return nil, fmt.Errorf("%s fehlt; zuerst hugin init aufrufen", Filename)
}
if err != nil {
return nil, err
}
k := &Config{}
if err := yaml.Unmarshal(raw, k); err != nil {
return nil, fmt.Errorf("%s: %w", Filename, err)
}
switch k.ToolCheck {
case "", "warn", "strict":
default:
return nil, fmt.Errorf("%s: tool_check %q, erwartet warn oder strict", Filename, k.ToolCheck)
}
return k, nil
}
func (k *Config) Save(repo string) error {
raw, err := yaml.Marshal(k)
if err != nil {
return err
}
return os.WriteFile(filepath.Join(repo, Filename), raw, 0o644)
}