Repository: exercism/cli
Pull request #686 (2018-07-27 00:12:37)

Rename config.Configuration to config.Config
Now that we got rid of the complicated viper wrapper, we
can name this Config, which is a bit more idiomatic.


Patch:
diff --git a/cmd/configure.go b/cmd/configure.go
index 2dbcb51..dd1c47e 100644
--- a/cmd/configure.go
+++ b/cmd/configure.go
@@ -31,7 +31,7 @@ places.
 You can also override certain default settings to suit your preferences.
 `,
 	RunE: func(cmd *cobra.Command, args []string) error {
-		configuration := config.NewConfiguration()
+		configuration := config.NewConfig()
 
 		viperConfig.AddConfigPath(configuration.Dir)
 		viperConfig.SetConfigName("user")
@@ -44,7 +44,7 @@ You can also override certain default settings to suit your preferences.
 	},
 }
 
-func runConfigure(configuration config.Configuration, flags *pflag.FlagSet) error {
+func runConfigure(configuration config.Config, flags *pflag.FlagSet) error {
 	cfg := configuration.UserViperConfig
 
 	// Show the existing configuration and exit.
@@ -196,7 +196,7 @@ func runConfigure(configuration config.Configuration, flags *pflag.FlagSet) erro
 	return nil
 }
 
-func printCurrentConfig(configuration config.Configuration) {
+func printCurrentConfig(configuration config.Config) {
 	w := tabwriter.NewWriter(Err, 0, 0, 2, ' ', 0)
 	defer w.Flush()
 
diff --git a/cmd/download.go b/cmd/download.go
index 2b9dc30..206ee93 100644
--- a/cmd/download.go
+++ b/cmd/download.go
@@ -32,7 +32,7 @@ latest solution.
 Download other people's solutions by providing the UUID.
 `,
 	RunE: func(cmd *cobra.Command, args []string) error {
-		cfg := config.NewConfiguration()
+		cfg := config.NewConfig()
 
 		v := viper.New()
 		v.AddConfigPath(cfg.Dir)
@@ -46,7 +46,7 @@ Download other people's solutions by providing the UUID.
 	},
 }
 
-func runDownload(cfg config.Configuration, flags *pflag.FlagSet, args []string) error {
+func runDownload(cfg config.Config, flags *pflag.FlagSet, args []string) error {
 	usrCfg := cfg.UserViperConfig
 	if usrCfg.GetString("token") == "" {
 		return fmt.Errorf(msgWelcomePleaseConfigure, config.SettingsURL(usrCfg.GetString("apibaseurl")), BinaryName)
diff --git a/cmd/open.go b/cmd/open.go
index a187227..0da33b0 100644
--- a/cmd/open.go
+++ b/cmd/open.go
@@ -24,7 +24,7 @@ the solution you want to see on the website.
 	`,
 	Args: cobra.ExactArgs(1),
 	RunE: func(cmd *cobra.Command, args []string) error {
-		cfg := config.NewConfiguration()
+		cfg := config.NewConfig()
 
 		v := viper.New()
 		v.AddConfigPath(cfg.Dir)
diff --git a/cmd/submit.go b/cmd/submit.go
index 930311c..2028c94 100644
--- a/cmd/submit.go
+++ b/cmd/submit.go
@@ -28,7 +28,7 @@ var submitCmd = &cobra.Command{
 	Call the command with the list of files you want to submit.
 `,
 	RunE: func(cmd *cobra.Command, args []string) error {
-		cfg := config.NewConfiguration()
+		cfg := config.NewConfig()
 
 		usrCfg := viper.New()
 		usrCfg.AddConfigPath(cfg.Dir)
@@ -49,7 +49,7 @@ var submitCmd = &cobra.Command{
 	},
 }
 
-func runSubmit(cfg config.Configuration, flags *pflag.FlagSet, args []string) error {
+func runSubmit(cfg config.Config, flags *pflag.FlagSet, args []string) error {
 	usrCfg := cfg.UserViperConfig
 
 	if usrCfg.GetString("token") == "" {
diff --git a/cmd/troubleshoot.go b/cmd/troubleshoot.go
index 66c3e2a..a205a67 100644
--- a/cmd/troubleshoot.go
+++ b/cmd/troubleshoot.go
@@ -33,7 +33,7 @@ command into a GitHub issue so we can help figure out what's going on.
 		cli.HTTPClient = &http.Client{Timeout: 20 * time.Second}
 		c := cli.New(Version)
 
-		cfg := config.NewConfiguration()
+		cfg := config.NewConfig()
 
 		v := viper.New()
 		v.AddConfigPath(cfg.Dir)
@@ -63,7 +63,7 @@ type Status struct {
 	System          systemStatus
 	Configuration   configurationStatus
 	APIReachability apiReachabilityStatus
-	cfg             config.Configuration
+	cfg             config.Config
 	cli             *cli.CLI
 }
 
@@ -101,7 +101,7 @@ type apiPing struct {
 }
 
 // newStatus prepares a value to perform a diagnostic self-check.
-func newStatus(cli *cli.CLI, cfg config.Configuration) Status {
+func newStatus(cli *cli.CLI, cfg config.Config) Status {
 	status := Status{
 		cfg: cfg,
 		cli: cli,
@@ -129,7 +129,7 @@ func (status *Status) compile() (string, error) {
 	return bb.String(), nil
 }
 
-func newAPIReachabilityStatus(cfg config.Configuration) apiReachabilityStatus {
+func newAPIReachabilityStatus(cfg config.Config) apiReachabilityStatus {
 	baseURL := cfg.UserViperConfig.GetString("apibaseurl")
 	if baseURL == "" {
 		baseURL = cfg.DefaultBaseURL
diff --git a/cmd/workspace.go b/cmd/workspace.go
index 03c1ffe..673ab36 100644
--- a/cmd/workspace.go
+++ b/cmd/workspace.go
@@ -27,7 +27,7 @@ need to be on the same drive as your workspace directory. Otherwise
 nothing will happen.
 	`,
 	RunE: func(cmd *cobra.Command, args []string) error {
-		cfg := config.NewConfiguration()
+		cfg := config.NewConfig()
 
 		v := viper.New()
 		v.AddConfigPath(cfg.Dir)
diff --git a/config/config.go b/config/config.go
index c072f5c..b9b1883 100644
--- a/config/config.go
+++ b/config/config.go
@@ -2,13 +2,119 @@ package config
 
 import (
 	"fmt"
+	"os"
+	"path/filepath"
 	"regexp"
+	"runtime"
+	"strings"
+
+	"github.com/spf13/viper"
 )
 
 var (
 	defaultBaseURL = "https://api.exercism.io/v1"
+
+	// DefaultDirName is the default name used for config and workspace directories.
+	DefaultDirName string
 )
 
+// Config lets us inject configuration options into commands.
+type Config struct {
+	OS              string
+	Home            string
+	Dir             string
+	DefaultBaseURL  string
+	DefaultDirName  string
+	UserViperConfig *viper.Viper
+	Persister       Persister
+}
+
+// NewConfig provides a configuration with default values.
+func NewConfig() Config {
+	home := userHome()
+	dir := Dir()
+
+	return Config{
+		OS:             runtime.GOOS,
+		Dir:            Dir(),
+		Home:           home,
+		DefaultBaseURL: defaultBaseURL,
+		DefaultDirName: DefaultDirName,
+		Persister:      FilePersister{Dir: dir},
+	}
+}
+
+// SetDefaultDirName configures the default directory name based on the name of the binary.
+func SetDefaultDirName(binaryName string) {
+	DefaultDirName = strings.Replace(filepath.Base(binaryName), ".exe", "", 1)
+}
+
+// Dir is the configured config home directory.
+// All the cli-related config files live in this directory.
+func Dir() string {
+	var dir string
+	if runtime.GOOS == "windows" {
+		dir = os.Getenv("APPDATA")
+		if dir != "" {
+			return filepath.Join(dir, DefaultDirName)
+		}
+	} else {
+		dir := os.Getenv("EXERCISM_CONFIG_HOME")
+		if dir != "" {
+			return dir
+		}
+		dir = os.Getenv("XDG_CONFIG_HOME")
+		if dir == "" {
+			dir = filepath.Join(os.Getenv("HOME"), ".config")
+		}
+		if dir != "" {
+			return filepath.Join(dir, DefaultDirName)
+		}
+	}
+	// If all else fails, use the current directory.
+	dir, _ = os.Getwd()
+	return dir
+}
+
+func userHome() string {
+	var dir string
+	if runtime.GOOS == "windows" {
+		dir = os.Getenv("USERPROFILE")
+		if dir != "" {
+			return dir
+		}
+		dir = filepath.Join(os.Getenv("HOMEDRIVE"), os.Getenv("HOMEPATH"))
+		if dir != "" {
+			return dir
+		}
+	} else {
+		dir = os.Getenv("HOME")
+		if dir != "" {
+			return dir
+		}
+	}
+	// If all else fails, use the current directory.
+	dir, _ = os.Getwd()
+	return dir
+}
+
+// DefaultWorkspaceDir provides a sensible default for the Exercism workspace.
+// The default is different depending on the platform, in order to best match
+// the conventions for that platform.
+// It places the directory in the user's home path.
+func DefaultWorkspaceDir(cfg Config) string {
+	dir := cfg.DefaultDirName
+	if cfg.OS != "linux" {
+		dir = strings.Title(dir)
+	}
+	return filepath.Join(cfg.Home, dir)
+}
+
+// Save persists a viper config of the base name.
+func (c Config) Save(basename string) error {
+	return c.Persister.Save(c.UserViperConfig, basename)
+}
+
 // InferSiteURL guesses what the website URL is.
 // The basis for the guess is which API we're submitting to.
 func InferSiteURL(apiURL string) string {
diff --git a/config/configuration.go b/config/configuration.go
deleted file mode 100644
index bf92c5b..0000000
--- a/config/configuration.go
+++ /dev/null
@@ -1,112 +0,0 @@
-package config
-
-import (
-	"os"
-	"path/filepath"
-	"runtime"
-	"strings"
-
-	"github.com/spf13/viper"
-)
-
-var (
-	// DefaultDirName is the default name used for config and workspace directories.
-	DefaultDirName string
-)
-
-// Configuration lets us inject configuration options into commands.
-type Configuration struct {
-	OS              string
-	Home            string
-	Dir             string
-	DefaultBaseURL  string
-	DefaultDirName  string
-	UserViperConfig *viper.Viper
-	Persister       Persister
-}
-
-// NewConfiguration provides a configuration with default values.
-func NewConfiguration() Configuration {
-	home := userHome()
-	dir := Dir()
-
-	return Configuration{
-		OS:             runtime.GOOS,
-		Dir:            Dir(),
-		Home:           home,
-		DefaultBaseURL: defaultBaseURL,
-		DefaultDirName: DefaultDirName,
-		Persister:      FilePersister{Dir: dir},
-	}
-}
-
-// SetDefaultDirName configures the default directory name based on the name of the binary.
-func SetDefaultDirName(binaryName string) {
-	DefaultDirName = strings.Replace(filepath.Base(binaryName), ".exe", "", 1)
-}
-
-// Dir is the configured config home directory.
-// All the cli-related config files live in this directory.
-func Dir() string {
-	var dir string
-	if runtime.GOOS == "windows" {
-		dir = os.Getenv("APPDATA")
-		if dir != "" {
-			return filepath.Join(dir, DefaultDirName)
-		}
-	} else {
-		dir := os.Getenv("EXERCISM_CONFIG_HOME")
-		if dir != "" {
-			return dir
-		}
-		dir = os.Getenv("XDG_CONFIG_HOME")
-		if dir == "" {
-			dir = filepath.Join(os.Getenv("HOME"), ".config")
-		}
-		if dir != "" {
-			return filepath.Join(dir, DefaultDirName)
-		}
-	}
-	// If all else fails, use the current directory.
-	dir, _ = os.Getwd()
-	return dir
-}
-
-func userHome() string {
-	var dir string
-	if runtime.GOOS == "windows" {
-		dir = os.Getenv("USERPROFILE")
-		if dir != "" {
-			return dir
-		}
-		dir = filepath.Join(os.Getenv("HOMEDRIVE"), os.Getenv("HOMEPATH"))
-		if dir != "" {
-			return dir
-		}
-	} else {
-		dir = os.Getenv("HOME")
-		if dir != "" {
-			return dir
-		}
-	}
-	// If all else fails, use the current directory.
-	dir, _ = os.Getwd()
-	return dir
-}
-
-// DefaultWorkspaceDir provides a sensible default for the Exercism workspace.
-// The default is different depending on the platform, in order to best match
-// the conventions for that platform.
-// It places the directory in the user's home path.
-func DefaultWorkspaceDir(cfg Configuration) string {
-	dir := cfg.DefaultDirName
-	if cfg.OS != "linux" {
-		dir = strings.Title(dir)
-	}
-	return filepath.Join(cfg.Home, dir)
-}
-
-// Save persists a viper config of the base name.
-func (c Configuration) Save(basename string) error {
-	return c.Persister.Save(c.UserViperConfig, basename)
-}


Test patch:
diff --git a/cmd/configure_test.go b/cmd/configure_test.go
index bdd565f..99e6472 100644
--- a/cmd/configure_test.go
+++ b/cmd/configure_test.go
@@ -33,7 +33,7 @@ func TestBareConfigure(t *testing.T) {
 	err := flags.Parse([]string{})
 	assert.NoError(t, err)
 
-	cfg := config.Configuration{
+	cfg := config.Config{
 		Persister:       config.InMemoryPersister{},
 		UserViperConfig: v,
 		DefaultBaseURL:  "http://example.com",
@@ -70,7 +70,7 @@ func TestConfigureShow(t *testing.T) {
 	err := flags.Parse(args)
 	assert.NoError(t, err)
 
-	cfg := config.Configuration{
+	cfg := config.Config{
 		Persister:       config.InMemoryPersister{},
 		UserViperConfig: v,
 	}
@@ -170,7 +170,7 @@ func TestConfigureToken(t *testing.T) {
 		err := flags.Parse(tc.args)
 		assert.NoError(t, err)
 
-		cfg := config.Configuration{
+		cfg := config.Config{
 			Persister:       config.InMemoryPersister{},
 			UserViperConfig: v,
 			DefaultBaseURL:  ts.URL,
@@ -258,7 +258,7 @@ func TestConfigureAPIBaseURL(t *testing.T) {
 		err := flags.Parse(tc.args)
 		assert.NoError(t, err)
 
-		cfg := config.Configuration{
+		cfg := config.Config{
 			Persister:       config.InMemoryPersister{},
 			UserViperConfig: v,
 			DefaultBaseURL:  ts.URL,
@@ -343,7 +343,7 @@ func TestConfigureWorkspace(t *testing.T) {
 		err := flags.Parse(tc.args)
 		assert.NoError(t, err)
 
-		cfg := config.Configuration{
+		cfg := config.Config{
 			Persister:       config.InMemoryPersister{},
 			UserViperConfig: v,
 			DefaultBaseURL:  ts.URL,
@@ -377,7 +377,7 @@ func TestConfigureDefaultWorkspaceWithoutClobbering(t *testing.T) {
 	defer os.RemoveAll(tmpDir)
 	assert.NoError(t, err)
 
-	cfg := config.Configuration{
+	cfg := config.Config{
 		OS:              "linux",
 		DefaultDirName:  "workspace",
 		Home:            tmpDir,
@@ -419,7 +419,7 @@ func TestConfigureExplicitWorkspaceWithoutClobberingNonDirectory(t *testing.T) {
 	v := viper.New()
 	v.Set("token", "abc123")
 
-	cfg := config.Configuration{
+	cfg := config.Config{
 		OS:              "linux",
 		DefaultDirName:  "workspace",
 		Home:            tmpDir,
diff --git a/cmd/download_test.go b/cmd/download_test.go
index 883372a..2c3200c 100644
--- a/cmd/download_test.go
+++ b/cmd/download_test.go
@@ -19,7 +19,7 @@ import (
 )
 
 func TestDownloadWithoutToken(t *testing.T) {
-	cfg := config.Configuration{
+	cfg := config.Config{
 		UserViperConfig: viper.New(),
 	}
 
@@ -34,7 +34,7 @@ func TestDownloadWithoutToken(t *testing.T) {
 func TestDownloadWithoutWorkspace(t *testing.T) {
 	v := viper.New()
 	v.Set("token", "abc123")
-	cfg := config.Configuration{
+	cfg := config.Config{
 		UserViperConfig: v,
 	}
 
@@ -48,7 +48,7 @@ func TestDownloadWithoutBaseURL(t *testing.T) {
 	v := viper.New()
 	v.Set("token", "abc123")
 	v.Set("workspace", "/home/whatever")
-	cfg := config.Configuration{
+	cfg := config.Config{
 		UserViperConfig: v,
 	}
 
@@ -64,7 +64,7 @@ func TestDownloadWithoutFlags(t *testing.T) {
 	v.Set("workspace", "/home/username")
 	v.Set("apibaseurl", "http://example.com")
 
-	cfg := config.Configuration{
+	cfg := config.Config{
 		UserViperConfig: v,
 	}
 
@@ -127,7 +127,7 @@ func TestDownload(t *testing.T) {
 		v.Set("apibaseurl", ts.URL)
 		v.Set("token", "abc123")
 
-		cfg := config.Configuration{
+		cfg := config.Config{
 			UserViperConfig: v,
 		}
 		flags := pflag.NewFlagSet("fake", pflag.PanicOnError)
diff --git a/cmd/submit_symlink_test.go b/cmd/submit_symlink_test.go
index a34b1f8..8b5781d 100644
--- a/cmd/submit_symlink_test.go
+++ b/cmd/submit_symlink_test.go
@@ -51,7 +51,7 @@ func TestSubmitFilesInSymlinkedPath(t *testing.T) {
 	v.Set("workspace", dstDir)
 	v.Set("apibaseurl", ts.URL)
 
-	cfg := config.Configuration{
+	cfg := config.Config{
 		Persister:       config.InMemoryPersister{},
 		UserViperConfig: v,
 	}
diff --git a/cmd/submit_test.go b/cmd/submit_test.go
index d40a55c..aae0f1f 100644
--- a/cmd/submit_test.go
+++ b/cmd/submit_test.go
@@ -16,7 +16,7 @@ import (
 )
 
 func TestSubmitWithoutToken(t *testing.T) {
-	cfg := config.Configuration{
+	cfg := config.Config{
 		Persister:       config.InMemoryPersister{},
 		UserViperConfig: viper.New(),
 	}
@@ -30,7 +30,7 @@ func TestSubmitWithoutWorkspace(t *testing.T) {
 	v := viper.New()
 	v.Set("token", "abc123")
 
-	cfg := config.Configuration{
+	cfg := config.Config{
 		Persister:       config.InMemoryPersister{},
 		UserViperConfig: v,
 		DefaultBaseURL:  "http://example.com",
@@ -49,7 +49,7 @@ func TestSubmitNonExistentFile(t *testing.T) {
 	v.Set("token", "abc123")
 	v.Set("workspace", tmpDir)
 
-	cfg := config.Configuration{
+	cfg := config.Config{
 		Persister:       config.InMemoryPersister{},
 		UserViperConfig: v,
 		DefaultBaseURL:  "http://example.com",
@@ -85,7 +85,7 @@ func TestSubmitExerciseWithoutSolutionMetadataFile(t *testing.T) {
 	v.Set("token", "abc123")
 	v.Set("workspace", tmpDir)
 
-	cfg := config.Configuration{
+	cfg := config.Config{
 		Persister:       config.InMemoryPersister{},
 		Dir:             tmpDir,
 		UserViperConfig: v,
@@ -105,7 +105,7 @@ func TestSubmitFilesAndDir(t *testing.T) {
 	v.Set("token", "abc123")
 	v.Set("workspace", tmpDir)
 
-	cfg := config.Configuration{
+	cfg := config.Config{
 		Persister:       config.InMemoryPersister{},
 		UserViperConfig: v,
 		DefaultBaseURL:  "http://example.com",
@@ -165,7 +165,7 @@ func TestSubmitFiles(t *testing.T) {
 	v.Set("workspace", tmpDir)
 	v.Set("apibaseurl", ts.URL)
 
-	cfg := config.Configuration{
+	cfg := config.Config{
 		Persister:       config.InMemoryPersister{},
 		Dir:             tmpDir,
 		UserViperConfig: v,
@@ -213,7 +213,7 @@ func TestSubmitWithEmptyFile(t *testing.T) {
 	v.Set("workspace", tmpDir)
 	v.Set("apibaseurl", ts.URL)
 
-	cfg := config.Configuration{
+	cfg := config.Config{
 		Persister:       config.InMemoryPersister{},
 		UserViperConfig: v,
 	}
@@ -264,7 +264,7 @@ func TestSubmitFilesForTeamExercise(t *testing.T) {
 	v.Set("workspace", tmpDir)
 	v.Set("apibaseurl", ts.URL)
 
-	cfg := config.Configuration{
+	cfg := config.Config{
 		Dir:             tmpDir,
 		UserViperConfig: v,
 	}
@@ -304,7 +304,7 @@ func TestSubmitOnlyEmptyFile(t *testing.T) {
 	v.Set("token", "abc123")
 	v.Set("workspace", tmpDir)
 
-	cfg := config.Configuration{
+	cfg := config.Config{
 		Persister:       config.InMemoryPersister{},
 		UserViperConfig: v,
 	}
@@ -342,7 +342,7 @@ func TestSubmitFilesFromDifferentSolutions(t *testing.T) {
 	v.Set("token", "abc123")
 	v.Set("workspace", tmpDir)
 
-	cfg := config.Configuration{
+	cfg := config.Config{
 		Persister:       config.InMemoryPersister{},
 		Dir:             tmpDir,
 		UserViperConfig: v,
@@ -406,7 +406,7 @@ func TestSubmitRelativePath(t *testing.T) {
 	v.Set("workspace", tmpDir)
 	v.Set("apibaseurl", ts.URL)
 
-	cfg := config.Configuration{
+	cfg := config.Config{
 		Persister:       config.InMemoryPersister{},
 		UserViperConfig: v,
 	}
diff --git a/config/configuration_test.go b/config/config_notwin_test.go
similarity index 68%
rename from config/configuration_test.go
rename to config/config_notwin_test.go
index ff64b49..f7e4564 100644
--- a/config/configuration_test.go
+++ b/config/config_notwin_test.go
@@ -11,15 +11,15 @@ import (
 
 func TestDefaultWorkspaceDir(t *testing.T) {
 	testCases := []struct {
-		cfg      Configuration
+		cfg      Config
 		expected string
 	}{
 		{
-			cfg:      Configuration{OS: "darwin", Home: "/User/charlie", DefaultDirName: "apple"},
+			cfg:      Config{OS: "darwin", Home: "/User/charlie", DefaultDirName: "apple"},
 			expected: "/User/charlie/Apple",
 		},
 		{
-			cfg:      Configuration{OS: "linux", Home: "/home/bob", DefaultDirName: "banana"},
+			cfg:      Config{OS: "linux", Home: "/home/bob", DefaultDirName: "banana"},
 			expected: "/home/bob/banana",
 		},
 	}
diff --git a/config/configuration_windows_test.go b/config/config_windows_test.go
similarity index 71%
rename from config/configuration_windows_test.go
rename to config/config_windows_test.go
index b07ccab..e4374de 100644
--- a/config/configuration_windows_test.go
+++ b/config/config_windows_test.go
@@ -9,6 +9,6 @@ import (
 )
 
 func TestDefaultWindowsWorkspaceDir(t *testing.T) {
-	cfg := Configuration{OS: "windows", Home: "C:\\Something", DefaultDirName: "basename"}
+	cfg := Config{OS: "windows", Home: "C:\\Something", DefaultDirName: "basename"}
 	assert.Equal(t, "C:\\Something\\Basename", DefaultWorkspaceDir(cfg))
 }