174 lines
4.0 KiB
Go
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
|
|
}
|
|
}
|