forked from sequelize/cli
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request sequelize#441 from exercism/nextercism-cli-cfg
[nextercism] Add CLI-specific config
- Loading branch information
Showing
7 changed files
with
263 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package config | ||
|
||
import "github.com/spf13/viper" | ||
|
||
// CLIConfig contains settings specific to the behavior of the CLI. | ||
type CLIConfig struct { | ||
*Config | ||
Tracks Tracks | ||
} | ||
|
||
// NewCLIConfig loads the config file in the config directory. | ||
func NewCLIConfig() (*CLIConfig, error) { | ||
cfg := NewEmptyCLIConfig() | ||
|
||
if err := cfg.Load(viper.New()); err != nil { | ||
return nil, err | ||
} | ||
cfg.SetDefaults() | ||
|
||
return cfg, nil | ||
} | ||
|
||
// NewEmptyCLIConfig doesn't load the config from file or set default values. | ||
func NewEmptyCLIConfig() *CLIConfig { | ||
return &CLIConfig{ | ||
Config: New(Dir(), "cli"), | ||
Tracks: Tracks{}, | ||
} | ||
} | ||
|
||
// Write stores the config to disk. | ||
func (cfg *CLIConfig) Write() error { | ||
cfg.SetDefaults() | ||
if err := cfg.Validate(); err != nil { | ||
return err | ||
} | ||
return Write(cfg) | ||
} | ||
|
||
// Validate ensures that the config is valid. | ||
// This is called before writing it. | ||
func (cfg *CLIConfig) Validate() error { | ||
for _, track := range cfg.Tracks { | ||
if err := track.CompileRegexes(); err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// SetDefaults ensures that we have all the necessary settings for the CLI. | ||
func (cfg *CLIConfig) SetDefaults() { | ||
for _, track := range cfg.Tracks { | ||
track.SetDefaults() | ||
} | ||
} | ||
|
||
// Load reads a viper configuration into the config. | ||
func (cfg *CLIConfig) Load(v *viper.Viper) error { | ||
cfg.readIn(v) | ||
return v.Unmarshal(&cfg) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package config | ||
|
||
import ( | ||
"io/ioutil" | ||
"os" | ||
"sort" | ||
"testing" | ||
|
||
"github.com/spf13/viper" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestCLIConfig(t *testing.T) { | ||
dir, err := ioutil.TempDir("", "cli-config") | ||
assert.NoError(t, err) | ||
defer os.RemoveAll(dir) | ||
|
||
cfg := &CLIConfig{ | ||
Config: New(dir, "cli"), | ||
Tracks: Tracks{ | ||
"bogus": &Track{ID: "bogus"}, | ||
"fake": &Track{ID: "fake", IgnorePatterns: []string{"c", "b", "a"}}, | ||
}, | ||
} | ||
|
||
// write it | ||
err = cfg.Write() | ||
assert.NoError(t, err) | ||
|
||
// reload it | ||
cfg = &CLIConfig{ | ||
Config: New(dir, "cli"), | ||
} | ||
err = cfg.Load(viper.New()) | ||
assert.NoError(t, err) | ||
assert.Equal(t, "bogus", cfg.Tracks["bogus"].ID) | ||
assert.Equal(t, "fake", cfg.Tracks["fake"].ID) | ||
|
||
// The ignore patterns got sorted. | ||
expected := append(defaultIgnorePatterns, "a", "b", "c") | ||
sort.Strings(expected) | ||
assert.Equal(t, expected, cfg.Tracks["fake"].IgnorePatterns) | ||
} | ||
|
||
func TestCLIConfigValidate(t *testing.T) { | ||
cfg := &CLIConfig{ | ||
Tracks: Tracks{ | ||
"fake": &Track{ | ||
ID: "fake", | ||
IgnorePatterns: []string{"(?=re)"}, // not a valid regex | ||
}, | ||
}, | ||
} | ||
|
||
err := cfg.Validate() | ||
assert.Error(t, err) | ||
} | ||
|
||
func TestCLIConfigSetDefaults(t *testing.T) { | ||
// No tracks, no defaults. | ||
cfg := &CLIConfig{} | ||
cfg.SetDefaults() | ||
assert.Equal(t, &CLIConfig{}, cfg) | ||
|
||
// With a track, gets defaults. | ||
cfg = &CLIConfig{ | ||
Tracks: map[string]*Track{ | ||
"bogus": &Track{ | ||
ID: "bogus", | ||
}, | ||
}, | ||
} | ||
cfg.SetDefaults() | ||
assert.Equal(t, defaultIgnorePatterns, cfg.Tracks["bogus"].IgnorePatterns) | ||
|
||
// With partial defaults and extras, gets everything. | ||
cfg = &CLIConfig{ | ||
Tracks: map[string]*Track{ | ||
"bogus": &Track{ | ||
ID: "bogus", | ||
IgnorePatterns: []string{".solution.json", "_spec[.]ext$"}, | ||
}, | ||
}, | ||
} | ||
cfg.SetDefaults() | ||
expected := append(defaultIgnorePatterns, "_spec[.]ext$") | ||
sort.Strings(expected) | ||
assert.Equal(t, expected, cfg.Tracks["bogus"].IgnorePatterns) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package config | ||
|
||
import ( | ||
"regexp" | ||
"sort" | ||
) | ||
|
||
var defaultIgnorePatterns = []string{ | ||
".solution.json", | ||
"README.md", | ||
} | ||
|
||
// Track holds the CLI-related settings for a track. | ||
type Track struct { | ||
ID string | ||
IgnorePatterns []string | ||
ignoreRegexes []*regexp.Regexp | ||
} | ||
|
||
func NewTrack(id string) *Track { | ||
t := &Track{ | ||
ID: id, | ||
} | ||
t.SetDefaults() | ||
return t | ||
} | ||
|
||
func (t *Track) SetDefaults() { | ||
m := map[string]bool{} | ||
for _, pattern := range t.IgnorePatterns { | ||
m[pattern] = true | ||
} | ||
for _, pattern := range defaultIgnorePatterns { | ||
if !m[pattern] { | ||
t.IgnorePatterns = append(t.IgnorePatterns, pattern) | ||
} | ||
} | ||
sort.Strings(t.IgnorePatterns) | ||
} | ||
|
||
func (t *Track) AcceptFilename(f string) (bool, error) { | ||
if err := t.CompileRegexes(); err != nil { | ||
return false, err | ||
} | ||
|
||
for _, re := range t.ignoreRegexes { | ||
if re.MatchString(f) { | ||
return false, nil | ||
} | ||
} | ||
return true, nil | ||
} | ||
|
||
func (t *Track) CompileRegexes() error { | ||
if len(t.ignoreRegexes) == len(t.IgnorePatterns) { | ||
return nil | ||
} | ||
|
||
for _, pattern := range t.IgnorePatterns { | ||
re, err := regexp.Compile(pattern) | ||
if err != nil { | ||
return err | ||
} | ||
t.ignoreRegexes = append(t.ignoreRegexes, re) | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package config | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestTrackIgnoreString(t *testing.T) { | ||
track := &Track{ | ||
IgnorePatterns: []string{ | ||
"con[.]txt", | ||
"pro.f", | ||
}, | ||
} | ||
|
||
tests := map[string]bool{ | ||
"falcon.txt": false, | ||
"beacon|txt": true, | ||
"beacon.ext": true, | ||
"proof": false, | ||
} | ||
|
||
for name, acceptable := range tests { | ||
ok, err := track.AcceptFilename(name) | ||
assert.NoError(t, err, name) | ||
assert.Equal(t, acceptable, ok, name) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
package config | ||
|
||
// Tracks is a collection of track-specific settings. | ||
type Tracks map[string]*Track |