Files
jukebox_maker/internal/config/config.go
Michael Chus 8f36d4e824 copier: rsync с возобновлением, папка назначения, права 777
- Заменить ручное копирование на rsync --partial --append-verify
- Структура на диске: <mount>/<dest_folder>/<rel path from /media>
- dest_folder настраивается (default: media)
- Права на диске: --no-perms --chmod=ugo=rwx
- rsync добавлен в Dockerfile
- Режим "удалить": удаляет только dest_folder, а не весь диск

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 21:56:26 +03:00

92 lines
1.9 KiB
Go

package config
import (
"encoding/json"
"errors"
"os"
"path/filepath"
)
type OverwriteMode string
type FileSelectMode string
const (
OverwriteSkip OverwriteMode = "skip"
OverwriteDelete OverwriteMode = "delete"
SelectNew FileSelectMode = "new"
SelectAll FileSelectMode = "all"
)
type SourceFolder struct {
Path string `json:"path"`
Enabled bool `json:"enabled"`
}
type Config struct {
ReserveFreeGB float64 `json:"reserve_free_gb"`
DestFolder string `json:"dest_folder"`
Sources []SourceFolder `json:"sources"`
OverwriteMode OverwriteMode `json:"overwrite_mode"`
FileSelectMode FileSelectMode `json:"file_select_mode"`
AutoCopy bool `json:"auto_copy"`
}
func defaults() Config {
return Config{
ReserveFreeGB: 2.0,
DestFolder: "media",
OverwriteMode: OverwriteSkip,
FileSelectMode: SelectNew,
AutoCopy: false,
}
}
func Load(path string) (*Config, error) {
data, err := os.ReadFile(path)
if errors.Is(err, os.ErrNotExist) {
cfg := defaults()
return &cfg, nil
}
if err != nil {
return nil, err
}
cfg := defaults()
if err := json.Unmarshal(data, &cfg); err != nil {
return nil, err
}
return &cfg, nil
}
func Save(path string, cfg *Config) error {
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
return err
}
data, err := json.MarshalIndent(cfg, "", " ")
if err != nil {
return err
}
tmp := path + ".tmp"
if err := os.WriteFile(tmp, data, 0o644); err != nil {
return err
}
return os.Rename(tmp, path)
}
func (c *Config) Validate() error {
if c.ReserveFreeGB < 0 {
return errors.New("reserve_free_gb must be >= 0")
}
switch c.OverwriteMode {
case OverwriteSkip, OverwriteDelete:
default:
return errors.New("overwrite_mode must be 'skip' or 'delete'")
}
switch c.FileSelectMode {
case SelectNew, SelectAll:
default:
return errors.New("file_select_mode must be 'new' or 'all'")
}
return nil
}