From 8adc79815b3af60a1cd205a85fb54915071a4f9c Mon Sep 17 00:00:00 2001 From: Hau Nguyen Date: Sat, 25 Feb 2023 22:30:20 +0700 Subject: [PATCH] feat: support config validate --- internal/cli/action.go | 13 +++++++++ internal/cli/app.go | 16 +++++++++++ internal/config/config.go | 1 + internal/config/config_demo.go | 4 +++ internal/config/config_real.go | 51 +++++++++++++++++++++++----------- 5 files changed, 69 insertions(+), 16 deletions(-) diff --git a/internal/cli/action.go b/internal/cli/action.go index b7319a8..a325263 100644 --- a/internal/cli/action.go +++ b/internal/cli/action.go @@ -86,6 +86,19 @@ func (a *action) runDiff(c *cli.Context) error { return nil } +func (a *action) runValidate(c *cli.Context) error { + cfg, err := a.loadConfig(c, validateCommand) + if err != nil { + return err + } + + if err := cfg.Validate(); err != nil { + return fmt.Errorf("config: failed to validate: %w", err) + } + + return nil +} + func (a *action) loadConfig(c *cli.Context, command string) (config.Config, error) { a.getFlags(c) a.log("start %s with flags %+v\n", command, a.flags) diff --git a/internal/cli/app.go b/internal/cli/app.go index 1aef6a0..2ff8270 100644 --- a/internal/cli/app.go +++ b/internal/cli/app.go @@ -29,6 +29,9 @@ const ( diffCommand = "diff" diffUsage = "diff dotfiles with user configs" + validateCommand = "validate" + validateUsage = "validate config" + verboseFlag = "verbose" verboseUsage = "show what is going on" @@ -44,6 +47,7 @@ var ( downloadAliases = []string{"d"} cleanAliases = []string{"c"} diffAliases = []string{"df"} + validateAliases = []string{"vl"} ) // denyOSes contains OS which is not supported @@ -139,6 +143,18 @@ func NewApp() *App { }, Action: a.runDiff, }, + { + Name: validateCommand, + Aliases: validateAliases, + Usage: validateUsage, + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: verboseFlag, + Usage: verboseUsage, + }, + }, + Action: a.runValidate, + }, }, Action: a.runHelp, } diff --git a/internal/config/config.go b/internal/config/config.go index 482e565..3767e4f 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -25,6 +25,7 @@ type Config interface { Clean() error Diff() error Download() error + Validate() error } type ConfigApps struct { diff --git a/internal/config/config_demo.go b/internal/config/config_demo.go index 14f55ea..7385862 100644 --- a/internal/config/config_demo.go +++ b/internal/config/config_demo.go @@ -66,3 +66,7 @@ func (c *configDemo) Clean() error { func (c *configDemo) Diff() error { return nil } + +func (c *configDemo) Validate() error { + return nil +} diff --git a/internal/config/config_real.go b/internal/config/config_real.go index 610b6ef..34d7d75 100644 --- a/internal/config/config_real.go +++ b/internal/config/config_real.go @@ -1,6 +1,7 @@ package config import ( + "errors" "fmt" "io" "net/http" @@ -11,6 +12,8 @@ import ( "github.com/make-go-great/diff-go" ) +var ErrConfigInvalid = errors.New("config invalid") + type configReal struct { httpClient *http.Client ConfigApps @@ -105,22 +108,6 @@ func (c *configReal) Clean() error { return nil } -func (c *configReal) Diff() error { - for _, app := range c.Apps { - for _, p := range app.Paths { - if p.External == "" { - continue - } - - if err := diff.Diff(p.Internal, p.External); err != nil { - return fmt.Errorf("failed to compare %s with %s: %w", p.Internal, p.External, err) - } - } - } - - return nil -} - func getUnusedDirs(apps map[string]App) (map[string]struct{}, error) { files, err := os.ReadDir(configDirPath) if err != nil { @@ -145,3 +132,35 @@ func getUnusedDirs(apps map[string]App) (map[string]struct{}, error) { return unusedDirs, nil } + +func (c *configReal) Diff() error { + for _, app := range c.Apps { + for _, p := range app.Paths { + if p.External == "" { + continue + } + + if err := diff.Diff(p.Internal, p.External); err != nil { + return fmt.Errorf("failed to compare %s with %s: %w", p.Internal, p.External, err) + } + } + } + + return nil +} + +func (c *configReal) Validate() error { + for _, app := range c.Apps { + for _, p := range app.Paths { + if p.Internal == "" { + return fmt.Errorf("empty internal app [%s]: %w", app, ErrConfigInvalid) + } + + if p.External == "" && p.URL == "" { + return fmt.Errorf("empty external and url app [%s]: %w", app, ErrConfigInvalid) + } + } + } + + return nil +}