From d964158bf7a1dd71e9b9554bd9dd1e944fc9a476 Mon Sep 17 00:00:00 2001 From: Grzegorz Dlugoszewski Date: Tue, 30 Jun 2020 21:25:42 +0200 Subject: [PATCH] Fix problems with loading values from gitconfig --- cmd/get/main.go | 6 ++++-- cmd/list/main.go | 3 ++- pkg/cfg/config.go | 49 +++++++++++++++++------------------------- pkg/cfg/config_test.go | 8 +++---- pkg/git/config.go | 2 +- 5 files changed, 31 insertions(+), 37 deletions(-) diff --git a/cmd/get/main.go b/cmd/get/main.go index 027fbd4..de445bd 100644 --- a/cmd/get/main.go +++ b/cmd/get/main.go @@ -36,16 +36,18 @@ func init() { viper.BindPFlag(cfg.KeyDefaultHost, cmd.PersistentFlags().Lookup(cfg.KeyDefaultHost)) viper.BindPFlag(cfg.KeyDump, cmd.PersistentFlags().Lookup(cfg.KeyDump)) viper.BindPFlag(cfg.KeyReposRoot, cmd.PersistentFlags().Lookup(cfg.KeyReposRoot)) + + cfg.Init(&git.ConfigGlobal{}) } func run(cmd *cobra.Command, args []string) error { - cfg.Init(&git.ConfigGlobal{}) - var url string if len(args) > 0 { url = args[0] } + cfg.Expand(cfg.KeyReposRoot) + config := &pkg.GetCfg{ Branch: viper.GetString(cfg.KeyBranch), DefHost: viper.GetString(cfg.KeyDefaultHost), diff --git a/cmd/list/main.go b/cmd/list/main.go index dc64f45..0bffae6 100644 --- a/cmd/list/main.go +++ b/cmd/list/main.go @@ -31,10 +31,11 @@ func init() { viper.BindPFlag(cfg.KeyOutput, cmd.PersistentFlags().Lookup(cfg.KeyOutput)) viper.BindPFlag(cfg.KeyReposRoot, cmd.PersistentFlags().Lookup(cfg.KeyReposRoot)) + cfg.Init(&git.ConfigGlobal{}) } func run(cmd *cobra.Command, args []string) error { - cfg.Init(&git.ConfigGlobal{}) + cfg.Expand(cfg.KeyReposRoot) config := &pkg.ListCfg{ Fetch: viper.GetBool(cfg.KeyFetch), diff --git a/pkg/cfg/config.go b/pkg/cfg/config.go index 3147fa4..9381f76 100644 --- a/pkg/cfg/config.go +++ b/pkg/cfg/config.go @@ -3,6 +3,7 @@ package cfg import ( + "bytes" "fmt" "path/filepath" "strings" @@ -64,43 +65,33 @@ type Gitconfig interface { } // Init initializes viper config registry. Values are looked up in the following order: cli flag, env variable, gitconfig file, default value. -// Viper doesn't support gitconfig file format so it can't find missing values there automatically. They need to be specified in setMissingValues func. -// -// Because it reads the cli flags it needs to be called after the cmd.Execute(). func Init(cfg Gitconfig) { + readGitconfig(cfg) + viper.SetEnvPrefix(strings.ToUpper(GitgetPrefix)) viper.AutomaticEnv() - - setMissingValues(cfg) - expandValues() } -// setMissingValues checks if config values are provided by flags or env vars. If not, it tries loading them from gitconfig file. -// If that fails, the default values are used. -func setMissingValues(cfg Gitconfig) { - for key, def := range Defaults { - if isUnsetOrEmpty(key) { - viper.Set(key, getOrDef(cfg, key, def)) +// readGitConfig loads values from gitconfig file into viper's registry. +// Viper doesn't support the gitconfig format so we load it using "git config --global" command and populate a temporary "env" string, +// which is then feed to Viper. +func readGitconfig(cfg Gitconfig) { + var lines []string + + for key := range Defaults { + if val := cfg.Get(fmt.Sprintf("%s.%s", GitgetPrefix, key)); val != "" { + lines = append(lines, fmt.Sprintf("%s=%s", key, val)) } } + + viper.SetConfigType("env") + viper.ReadConfig(bytes.NewBuffer([]byte(strings.Join(lines, "\n")))) } -func isUnsetOrEmpty(key string) bool { - return !viper.IsSet(key) || strings.TrimSpace(viper.GetString(key)) == "" -} - -func getOrDef(cfg Gitconfig, key string, def string) string { - if val := cfg.Get(fmt.Sprintf("%s.%s", GitgetPrefix, key)); val != "" { - return val - } - return def -} - -// expandValues applies the homedir expansion to a config value. If expansion is not needed value is not modified. -func expandValues() { - for _, key := range viper.AllKeys() { - if expanded, err := homedir.Expand(viper.GetString(key)); err == nil { - viper.Set(key, expanded) - } +// Expand applies the variables expansion to a viper config of given key. +// If expansion fails or is not needed, the config is not modified. +func Expand(key string) { + if expanded, err := homedir.Expand(viper.GetString(key)); err == nil { + viper.Set(key, expanded) } } diff --git a/pkg/cfg/config_test.go b/pkg/cfg/config_test.go index 0a336db..215e1ab 100644 --- a/pkg/cfg/config_test.go +++ b/pkg/cfg/config_test.go @@ -58,6 +58,7 @@ func TestConfig(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { + viper.SetDefault(test.key, Defaults[KeyDefaultHost]) test.configMaker(t) got := viper.GetString(test.key) @@ -93,18 +94,18 @@ func testConfigOnlyInGitconfig(t *testing.T) { } func testConfigOnlyInEnvVar(t *testing.T) { + Init(&gitconfigEmpty{}) os.Setenv(envVarName, fromEnv) - Init(&gitconfigEmpty{}) } func testConfigInGitconfigAndEnvVar(t *testing.T) { - os.Setenv(envVarName, fromEnv) - Init(&gitconfigValid{}) + os.Setenv(envVarName, fromEnv) } func testConfigInFlag(t *testing.T) { + Init(&gitconfigValid{}) os.Setenv(envVarName, fromEnv) cmd := cobra.Command{} @@ -113,5 +114,4 @@ func testConfigInFlag(t *testing.T) { cmd.SetArgs([]string{"--" + KeyDefaultHost, fromFlag}) cmd.Execute() - Init(&gitconfigValid{}) } diff --git a/pkg/git/config.go b/pkg/git/config.go index 618a894..113e1f2 100644 --- a/pkg/git/config.go +++ b/pkg/git/config.go @@ -9,7 +9,7 @@ type ConfigGlobal struct{} // Get reads a value from global gitconfig file. Returns empty string when key is missing. func (c *ConfigGlobal) Get(key string) string { - out, err := run.Git("config", "--global").AndCaptureLine() + out, err := run.Git("config", "--global", key).AndCaptureLine() // In case of error return an empty string, the missing value will fall back to a default. if err != nil { return ""