Files
voidraft/internal/syncer/config.go
2026-03-30 00:03:23 +08:00

174 lines
4.0 KiB
Go

package syncer
import (
"errors"
"fmt"
"strings"
"time"
)
const (
// DefaultBranch 是默认 Git 分支名。
DefaultBranch = "master"
// DefaultRemoteName 是默认 Git 远端名。
DefaultRemoteName = "origin"
// DefaultHeadKey 是默认同步头文件名。
DefaultHeadKey = "head.json"
)
const (
// TargetKindGit 表示 Git 同步目标。
TargetKindGit = "git"
// TargetKindLocalFS 表示本地文件系统同步目标。
TargetKindLocalFS = "localfs"
)
// Config 描述整个同步系统的运行配置。
type Config struct {
Targets []TargetConfig
}
// TargetConfig 描述单个同步目标的配置。
type TargetConfig struct {
Kind string
Enabled bool
Schedule ScheduleConfig
Git *GitTargetConfig
LocalFS *LocalFSTargetConfig
}
// ScheduleConfig 描述自动同步调度配置。
type ScheduleConfig struct {
AutoSync bool
Interval time.Duration
}
// GitTargetConfig 描述 Git 同步目标配置。
type GitTargetConfig struct {
RepoPath string
RepoURL string
Branch string
RemoteName string
AuthorName string
AuthorEmail string
Auth GitAuthConfig
}
// GitAuthConfig 描述 Git 鉴权配置。
type GitAuthConfig struct {
Method string
Username string
Password string
Token string
SSHKeyPath string
SSHKeyPassword string
}
// LocalFSTargetConfig 描述本地文件系统同步目标配置。
type LocalFSTargetConfig struct {
Namespace string
HeadKey string
RootPath string
}
// Normalize 返回带默认值的配置副本。
func (c Config) Normalize() Config {
if len(c.Targets) == 0 {
return Config{}
}
targets := make([]TargetConfig, 0, len(c.Targets))
for _, target := range c.Targets {
targets = append(targets, target.Normalize())
}
return Config{Targets: targets}
}
// Target 返回指定 kind 的目标配置。
func (c Config) Target(targetKind string) (TargetConfig, error) {
for _, target := range c.Targets {
if target.Kind == targetKind {
return target, nil
}
}
return TargetConfig{}, fmt.Errorf("%w: %s", ErrTargetNotFound, targetKind)
}
// Normalize 返回带默认值的目标配置副本。
func (t TargetConfig) Normalize() TargetConfig {
target := t
if target.Kind == "" {
target.Kind = TargetKindGit
}
if target.Schedule.Interval < 0 {
target.Schedule.Interval = 0
}
if target.Kind == TargetKindGit && target.Git != nil {
gitConfig := *target.Git
if strings.TrimSpace(gitConfig.Branch) == "" {
gitConfig.Branch = DefaultBranch
}
if strings.TrimSpace(gitConfig.RemoteName) == "" {
gitConfig.RemoteName = DefaultRemoteName
}
target.Git = &gitConfig
}
if target.Kind == TargetKindLocalFS && target.LocalFS != nil {
storeConfig := *target.LocalFS
if strings.TrimSpace(storeConfig.Namespace) == "" {
storeConfig.Namespace = target.Kind
}
if strings.TrimSpace(storeConfig.HeadKey) == "" {
storeConfig.HeadKey = DefaultHeadKey
}
target.LocalFS = &storeConfig
}
return target
}
// Validate 校验目标配置。
func (t TargetConfig) Validate() error {
switch t.Kind {
case TargetKindGit:
if t.Git == nil {
return errors.New("git target config is required")
}
if strings.TrimSpace(t.Git.RepoPath) == "" {
return errors.New("git repo path is required")
}
case TargetKindLocalFS:
if t.LocalFS == nil {
return errors.New("localfs target config is required")
}
if strings.TrimSpace(t.LocalFS.RootPath) == "" {
return errors.New("localfs root path is required")
}
default:
return fmt.Errorf("%w: %s", ErrUnsupportedBackend, t.Kind)
}
return nil
}
// Ready 判断目标是否具备执行同步的必要信息。
func (t TargetConfig) Ready() bool {
if !t.Enabled {
return false
}
switch t.Kind {
case TargetKindGit:
if t.Git == nil {
return false
}
return strings.TrimSpace(t.Git.RepoPath) != "" && strings.TrimSpace(t.Git.RepoURL) != ""
case TargetKindLocalFS:
if t.LocalFS == nil {
return false
}
return strings.TrimSpace(t.LocalFS.RootPath) != ""
default:
return false
}
}