From 8c3740c2c501af1e702a0b89d4284ae7fc8f0f73 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Fri, 13 Apr 2018 16:06:37 +0100 Subject: [PATCH] config: Improve the Provider matching to have a negated match #2140 This makes it easier to make classes of provider in the config. --- fs/config.go | 3 ++ fs/config/config.go | 73 +++++++++++++++++++++++++--------------- fs/config/config_test.go | 22 ++++++++++++ 3 files changed, 70 insertions(+), 28 deletions(-) diff --git a/fs/config.go b/fs/config.go index 4c7b57ddf..fb948cdf2 100644 --- a/fs/config.go +++ b/fs/config.go @@ -22,6 +22,9 @@ var ( // This is a function pointer to decouple the config // implementation from the fs CountError = func(err error) {} + + // ConfigProvider is the config key used for provider options + ConfigProvider = "provider" ) // ConfigInfo is filesystem config options diff --git a/fs/config/config.go b/fs/config/config.go index 3e295f81a..f2e2053b6 100644 --- a/fs/config/config.go +++ b/fs/config/config.go @@ -683,9 +683,39 @@ func RemoteConfig(name string) { } } +// matchProvider returns true if provider matches the providerConfig string. +// +// The providerConfig string can either be a list of providers to +// match, or if it starts with "!" it will be a list of providers not +// to match. +// +// If either providerConfig or provider is blank then it will return true +func matchProvider(providerConfig, provider string) bool { + if providerConfig == "" || provider == "" { + return true + } + negate := false + if strings.HasPrefix(providerConfig, "!") { + providerConfig = providerConfig[1:] + negate = true + } + providers := strings.Split(providerConfig, ",") + matched := false + for _, p := range providers { + if p == provider { + matched = true + break + } + } + if negate { + return !matched + } + return matched +} + // ChooseOption asks the user to choose an option func ChooseOption(o *fs.Option, name string) string { - var subProvider = getConfigData().MustValue(name, "Provider", "") + var subProvider = getConfigData().MustValue(name, fs.ConfigProvider, "") fmt.Println(o.Help) if o.IsPassword { actions := []string{"yYes type in my own password", "gGenerate random password"} @@ -727,14 +757,7 @@ func ChooseOption(o *fs.Option, name string) string { var values []string var help []string for _, example := range o.Examples { - if example.Provider != "" { - if strings.Contains(example.Provider, subProvider) { - values = append(values, example.Value) - help = append(help, example.Help) - } else { - continue - } - } else { + if matchProvider(example.Provider, subProvider) { values = append(values, example.Value) help = append(help, example.Help) } @@ -848,14 +871,10 @@ func NewRemoteName() (name string) { func NewRemote(name string) { newType := ChooseOption(fsOption(), name) getConfigData().SetValue(name, "type", newType) - fs := fs.MustFind(newType) - for _, option := range fs.Options { - var subProvider = getConfigData().MustValue(name, "Provider", "") - if option.Provider != "" { - if strings.Contains(option.Provider, subProvider) { - getConfigData().SetValue(name, option.Name, ChooseOption(&option, name)) - } - } else { + ri := fs.MustFind(newType) + for _, option := range ri.Options { + subProvider := getConfigData().MustValue(name, fs.ConfigProvider, "") + if matchProvider(option.Provider, subProvider) { getConfigData().SetValue(name, option.Name, ChooseOption(&option, name)) } } @@ -864,32 +883,30 @@ func NewRemote(name string) { SaveConfig() return } - EditRemote(fs, name) + EditRemote(ri, name) } // EditRemote gets the user to edit a remote -func EditRemote(fs *fs.RegInfo, name string) { +func EditRemote(ri *fs.RegInfo, name string) { ShowRemote(name) fmt.Printf("Edit remote\n") - var subProvider = "" + subProvider := getConfigData().MustValue(name, fs.ConfigProvider, "") for { - for _, option := range fs.Options { + for _, option := range ri.Options { key := option.Name value := FileGet(name, key) - if strings.Compare(key, "Provider") == 0 { - subProvider = value + if !matchProvider(option.Provider, subProvider) { continue } - if option.Provider != "" { - if !(strings.Contains(option.Provider, subProvider)) { - continue - } - } fmt.Printf("Value %q = %q\n", key, value) fmt.Printf("Edit? (y/n)>\n") if Confirm() { newValue := ChooseOption(&option, name) getConfigData().SetValue(name, key, newValue) + // Update subProvider if it changed + if key == fs.ConfigProvider { + subProvider = newValue + } } } if OkRemote(name) { diff --git a/fs/config/config_test.go b/fs/config/config_test.go index af858be16..902a04c17 100644 --- a/fs/config/config_test.go +++ b/fs/config/config_test.go @@ -1,6 +1,7 @@ package config import ( + "fmt" "io/ioutil" "os" "testing" @@ -205,3 +206,24 @@ func hashedKeyCompare(t *testing.T, a, b string, shouldMatch bool) { assert.NotEqual(t, k1, k2) } } + +func TestMatchProvider(t *testing.T) { + for _, test := range []struct { + config string + provider string + want bool + }{ + {"", "", true}, + {"one", "one", true}, + {"one,two", "two", true}, + {"one,two,three", "two", true}, + {"one", "on", false}, + {"one,two,three", "tw", false}, + {"!one,two,three", "two", false}, + {"!one,two,three", "four", true}, + } { + what := fmt.Sprintf("%q,%q", test.config, test.provider) + got := matchProvider(test.config, test.provider) + assert.Equal(t, test.want, got, what) + } +}