diff --git a/go/cmd/dolt/commands/config.go b/go/cmd/dolt/commands/config.go index 7ecb1338a25..192d54dae09 100644 --- a/go/cmd/dolt/commands/config.go +++ b/go/cmd/dolt/commands/config.go @@ -207,7 +207,13 @@ func addOperation(dEnv *env.DoltEnv, setCfgTypes *set.StrSet, args []string, usa updates := make(map[string]string) for i := 0; i < len(args); i += 2 { - updates[strings.ToLower(args[i])] = args[i+1] + option := strings.ToLower(args[i]) + value := args[i+1] + if _, ok := config.ConfigOptions[option]; !ok && !strings.HasPrefix(option, env.SqlServerGlobalsPrefix) { + cli.Println("error: invalid config option, use dolt config --help to check valid configuration variables") + return 1 + } + updates[option] = value } var cfgType string diff --git a/go/cmd/dolt/commands/config_test.go b/go/cmd/dolt/commands/config_test.go index b36abc3c4ac..03c97428fc2 100644 --- a/go/cmd/dolt/commands/config_test.go +++ b/go/cmd/dolt/commands/config_test.go @@ -51,25 +51,25 @@ func TestConfigAdd(t *testing.T) { Name: "local", CfgSet: localCfg, Scope: env.LocalConfig, - Args: []string{"title", "senior dufus"}, + Args: []string{"user.name", "senior dufus"}, }, { Name: "global", CfgSet: globalCfg, Scope: env.GlobalConfig, - Args: []string{"title", "senior dufus"}, + Args: []string{"user.name", "senior dufus"}, }, { Name: "default", CfgSet: &set.StrSet{}, Scope: env.LocalConfig, - Args: []string{"title", "senior dufus"}, + Args: []string{"user.name", "senior dufus"}, }, { Name: "multi error", CfgSet: multiCfg, Scope: env.LocalConfig, - Args: []string{"title", "senior dufus"}, + Args: []string{"user.name", "senior dufus"}, Code: 1, }, { @@ -83,7 +83,7 @@ func TestConfigAdd(t *testing.T) { Name: "odd args", CfgSet: multiCfg, Scope: env.LocalConfig, - Args: []string{"title"}, + Args: []string{"user.name"}, Code: 1, }, } @@ -97,7 +97,7 @@ func TestConfigAdd(t *testing.T) { assert.Equal(t, tt.Code, resCode) } else if cfg, ok := dEnv.Config.GetConfig(tt.Scope); ok { - resVal := cfg.GetStringOrDefault("title", "") + resVal := cfg.GetStringOrDefault("user.name", "") assert.Equal(t, "senior dufus", resVal) } else { t.Error("comparison config not found") @@ -280,12 +280,12 @@ func TestConfig(t *testing.T) { // test setting global config with --add configCmd := ConfigCmd{} - ret := configCmd.Exec(ctx, "dolt config", []string{"-global", "--add", "name", "bheni"}, dEnv, nil) - ret += configCmd.Exec(ctx, "dolt config", []string{"-global", "--add", "title", "dufus"}, dEnv, nil) + ret := configCmd.Exec(ctx, "dolt config", []string{"-global", "--add", "user.name", "bheni"}, dEnv, nil) + ret += configCmd.Exec(ctx, "dolt config", []string{"-global", "--add", "user.email", "dufus@example.com"}, dEnv, nil) expectedGlobal := map[string]string{ - "name": "bheni", - "title": "dufus", + "user.name": "bheni", + "user.email": "dufus@example.com", } if ret != 0 { @@ -295,11 +295,11 @@ func TestConfig(t *testing.T) { } // test setting global config with --set - ret = configCmd.Exec(ctx, "dolt config", []string{"-global", "--set", "name", "steph"}, dEnv, nil) + ret = configCmd.Exec(ctx, "dolt config", []string{"-global", "--set", "user.name", "steph"}, dEnv, nil) expectedGlobal = map[string]string{ - "name": "steph", - "title": "dufus", + "user.name": "steph", + "user.email": "dufus@example.com", } if ret != 0 { @@ -309,40 +309,40 @@ func TestConfig(t *testing.T) { } // test setting local config with --add - ret = configCmd.Exec(ctx, "dolt config", []string{"-local", "--add", "title", "senior dufus"}, dEnv, nil) + ret = configCmd.Exec(ctx, "dolt config", []string{"-local", "--add", "user.name", "senior dufus"}, dEnv, nil) expectedLocal := map[string]string{ - "title": "senior dufus", + "user.name": "senior dufus", } if ret != 0 { t.Error("Failed to set local config") } else if cfg, ok := dEnv.Config.GetConfig(env.LocalConfig); !ok || !config.Equals(cfg, expectedLocal) { t.Error("config -add did not yield expected local results") - } else if val, err := cfg.GetString("title"); err != nil || val != "senior dufus" { - t.Error("Unexpected value of \"title\" retrieved from the config hierarchy") + } else if val, err := cfg.GetString("user.name"); err != nil || val != "senior dufus" { + t.Error("Unexpected value of \"user.name\" retrieved from the config hierarchy") } // test setting local config with --set - ret = configCmd.Exec(ctx, "dolt config", []string{"-local", "--set", "name", "steph"}, dEnv, nil) + ret = configCmd.Exec(ctx, "dolt config", []string{"-local", "--set", "user.email", "dufus@example.com"}, dEnv, nil) expectedLocal = map[string]string{ - "name": "steph", - "title": "senior dufus", + "user.name": "senior dufus", + "user.email": "dufus@example.com", } if ret != 0 { t.Error("Failed to set local config") } else if cfg, ok := dEnv.Config.GetConfig(env.LocalConfig); !ok || !config.Equals(cfg, expectedLocal) { t.Error("config -set did not yield expected local results") - } else if val, err := cfg.GetString("name"); err != nil || val != "steph" { - t.Error("Unexpected value of \"name\" retrieved from the config hierarchy") + } else if val, err := cfg.GetString("user.email"); err != nil || val != "dufus@example.com" { + t.Error("Unexpected value of \"user.email\" retrieved from the config hierarchy") } - ret = configCmd.Exec(ctx, "dolt config", []string{"-global", "--unset", "name"}, dEnv, nil) + ret = configCmd.Exec(ctx, "dolt config", []string{"-global", "--unset", "user.name"}, dEnv, nil) expectedGlobal = map[string]string{ - "title": "dufus", + "user.email": "dufus@example.com", } if ret != 0 { @@ -351,7 +351,7 @@ func TestConfig(t *testing.T) { t.Error("config -add did not yield expected global results") } - expectedGlobal = map[string]string{"title": "dufus"} + expectedGlobal = map[string]string{"user.email": "dufus@example.com"} globalProperties := map[string]string{} ret = listOperation(dEnv, globalCfg, []string{}, func() {}, func(k string, v string) { globalProperties[k] = v @@ -363,7 +363,7 @@ func TestConfig(t *testing.T) { t.Error("listOperation did not yield expected global results") } - expectedLocal = map[string]string{"name": "steph", "title": "senior dufus"} + expectedLocal = map[string]string{"user.name": "senior dufus", "user.email": "dufus@example.com"} localProperties := map[string]string{} ret = listOperation(dEnv, localCfg, []string{}, func() {}, func(k string, v string) { localProperties[k] = v @@ -375,8 +375,8 @@ func TestConfig(t *testing.T) { t.Error("listOperation did not yield expected local results") } - ret = getOperation(dEnv, globalCfg, []string{"title"}, func(k string, v *string) { - if v == nil || *v != "dufus" { + ret = getOperation(dEnv, globalCfg, []string{"user.email"}, func(k string, v *string) { + if v == nil || *v != "dufus@example.com" { t.Error("Failed to get expected value for title.") } }) @@ -385,9 +385,9 @@ func TestConfig(t *testing.T) { t.Error("get operation failed") } - ret = getOperation(dEnv, globalCfg, []string{"name"}, func(k string, v *string) { + ret = getOperation(dEnv, globalCfg, []string{"user.name"}, func(k string, v *string) { if v != nil { - t.Error("Failed to get expected value for \"name\" which should not be set in the config.") + t.Error("Failed to get expected value for \"user.name\" which should not be set in the config.") } }) diff --git a/go/cmd/dolt/dolt.go b/go/cmd/dolt/dolt.go index cbe28b8b07d..cfbe2e52004 100644 --- a/go/cmd/dolt/dolt.go +++ b/go/cmd/dolt/dolt.go @@ -26,6 +26,7 @@ import ( "os/exec" "path/filepath" "strconv" + "strings" "time" "github.com/dolthub/go-mysql-server/sql" @@ -461,6 +462,26 @@ func runMain() int { return 1 } + globalConfig.Iter(func(name, val string) (stop bool) { + option := strings.ToLower(name) + if _, ok := config.ConfigOptions[option]; !ok && !strings.HasPrefix(option, env.SqlServerGlobalsPrefix) { + cli.Println(color.YellowString("Warning: Unknown global config option '%s'. Use `dolt config --global --unset %s` to remove.", name, name)) + } + return false + }) + + // try verifying contents of local config + localConfig, ok := dEnv.Config.GetConfig(env.LocalConfig) + if ok { + localConfig.Iter(func(name, val string) (stop bool) { + option := strings.ToLower(name) + if _, ok := config.ConfigOptions[option]; !ok && !strings.HasPrefix(option, env.SqlServerGlobalsPrefix) { + cli.Println(color.YellowString("Warning: Unknown local config option '%s'. Use `dolt config --local --unset %s` to remove.", name, name)) + } + return false + }) + } + apr, remainingArgs, subcommandName, err := parseGlobalArgsAndSubCommandName(globalConfig, args) if err == argparser.ErrHelp { doltCommand.PrintUsage("dolt") diff --git a/go/libraries/utils/config/keys.go b/go/libraries/utils/config/keys.go index 57f80654c61..42d4ba2aba7 100755 --- a/go/libraries/utils/config/keys.go +++ b/go/libraries/utils/config/keys.go @@ -14,6 +14,24 @@ package config +var ConfigOptions = map[string]struct{}{ + UserEmailKey: {}, + UserNameKey: {}, + UserCreds: {}, + DoltEditor: {}, + InitBranchName: {}, + RemotesApiHostKey: {}, + RemotesApiHostPortKey: {}, + AddCredsUrlKey: {}, + DoltLabInsecureKey: {}, + MetricsDisabled: {}, + MetricsHost: {}, + MetricsPort: {}, + MetricsInsecure: {}, + PushAutoSetupRemote: {}, + ProfileKey: {}, +} + const UserEmailKey = "user.email" const UserNameKey = "user.name" @@ -41,3 +59,5 @@ const MetricsPort = "metrics.port" const MetricsInsecure = "metrics.insecure" const PushAutoSetupRemote = "push.autosetupremote" + +const ProfileKey = "profile" diff --git a/integration-tests/bats/config-home.bats b/integration-tests/bats/config-home.bats index bce68fc5974..eb9ac2b2de1 100644 --- a/integration-tests/bats/config-home.bats +++ b/integration-tests/bats/config-home.bats @@ -37,41 +37,41 @@ teardown() { HOME="$BATS_TMPDIR/config-test$$/homeA" HOME=$HOME dolt config --global --add metrics.disabled true > /dev/null 2>&1 - HOME=$HOME run dolt config --global --add test testA + HOME=$HOME run dolt config --global --add user.name "Your Name" [ "$status" -eq 0 ] [[ "$output" =~ "Config successfully updated" ]] || false HOME=$HOME run dolt config --list [ "$status" -eq 0 ] - [[ "$output" =~ "test = testA" ]] || false - HOME=$HOME run dolt config --get test + [[ "$output" =~ "user.name = Your Name" ]] || false + HOME=$HOME run dolt config --get user.name [ "$status" -eq 0 ] - [ "$output" = "testA" ] + [ "$output" = "Your Name" ] mkdir "$BATS_TMPDIR/config-test$$/homeB" HOME="$BATS_TMPDIR/config-test$$/homeB" HOME=$HOME dolt config --global --add metrics.disabled true > /dev/null 2>&1 - HOME=$HOME run dolt config --global --add test testB + HOME=$HOME run dolt config --global --add core.editor foo [ "$status" -eq 0 ] [[ "$output" =~ "Config successfully updated" ]] || false HOME=$HOME run dolt config --list [ "$status" -eq 0 ] - [[ "$output" =~ "test = testB" ]] || false - [[ ! "$output" =~ "test = testA" ]] || false - HOME=$HOME run dolt config --get test + [[ "$output" =~ "core.editor = foo" ]] || false + [[ ! "$output" =~ "user.name = Your Name" ]] || false + HOME=$HOME run dolt config --get core.editor [ "$status" -eq 0 ] - [ "$output" = "testB" ] + [ "$output" = "foo" ] HOME="$BATS_TMPDIR/config-test$$/homeA" - HOME=$HOME run dolt config --global --add test testA + HOME=$HOME run dolt config --global --add user.email "you@example.com" [ "$status" -eq 0 ] [[ "$output" =~ "Config successfully updated" ]] || false HOME=$HOME run dolt config --list [ "$status" -eq 0 ] - [[ "$output" =~ "test = testA" ]] || false - [[ ! "$output" =~ "test = testB" ]] || false - HOME=$HOME run dolt config --get test + [[ "$output" =~ "user.email = you@example.com" ]] || false + [[ ! "$output" =~ "core.editor = foo" ]] || false + HOME=$HOME run dolt config --get user.email [ "$status" -eq 0 ] - [ "$output" = "testA" ] + [ "$output" = "you@example.com" ] } diff --git a/integration-tests/bats/config.bats b/integration-tests/bats/config.bats index 32a65866266..1ff9e28e66b 100644 --- a/integration-tests/bats/config.bats +++ b/integration-tests/bats/config.bats @@ -31,18 +31,59 @@ teardown() { [[ "$output" =~ "$email" ]] || false } +@test "config: cannot set nonsense variables" { + run dolt config --add foo bar + [ "$status" -eq 1 ] + [[ "$output" =~ "error: invalid config option" ]] || false + + run dolt config --set foo bar + [ "$status" -eq 1 ] + [[ "$output" =~ "error: invalid config option" ]] || false +} + +@test "config: can unset nonsense variables" { + dolt config --global --add user.name steph # need to create config_global.json first + echo '{"foo":"bar"}' > $DOLT_ROOT_PATH/.dolt/config_global.json + run dolt config --global --list + [ "$status" -eq 0 ] + [[ "$output" =~ "foo = bar" ]] || false + + run dolt config --global --unset foo + [ "$status" -eq 0 ] + [[ "$output" =~ "Config successfully updated" ]] || false +} + +@test "config: warning on cli commands if config has nonsense variables" { + dolt config --global --add user.name steph # need to create config_global.json first + echo '{"global":"foo"}' > $DOLT_ROOT_PATH/.dolt/config_global.json + run dolt version + [ "$status" -eq 0 ] + [[ "$output" =~ "Warning: Unknown global config option 'global'. Use \`dolt config --global --unset global\` to remove." ]] || false + + dolt config --global --add user.email "you@example.com" + dolt config --global --add user.name "Your Name" + dolt init + + dolt config --local --add user.name steph # need to create config.json first + echo '{"local":"bar"}' > .dolt/config.json + run dolt config --list + [ "$status" -eq 0 ] + [[ "$output" =~ "Warning: Unknown global config option 'global'. Use \`dolt config --global --unset global\` to remove." ]] || false + [[ "$output" =~ "Warning: Unknown local config option 'local'. Use \`dolt config --local --unset local\` to remove." ]] || false +} + @test "config: set a global config variable" { - run dolt config --global --add test test + run dolt config --global --add user.name steph [ "$status" -eq 0 ] # Need to make this a regex because of the coloring [[ "$output" =~ "Config successfully updated" ]] || false run dolt config --list [ "$status" -eq 0 ] - [ "$output" = "test = test" ] - run dolt config --get test + [ "$output" = "user.name = steph" ] + run dolt config --get user.name [ "$status" -eq 0 ] - [ "$output" = "test" ] - run dolt config --global --add test + [ "$output" = "steph" ] + run dolt config --global --add user.email [ "$status" -eq 1 ] [[ "$output" =~ "wrong number of arguments" ]] || false run dolt config --global --add @@ -51,26 +92,26 @@ teardown() { } @test "config: delete a config variable" { - dolt config --global --add test test - run dolt config --global --unset test + dolt config --global --add user.name steph + run dolt config --global --unset user.name [ "$status" -eq 0 ] [[ "$output" =~ "Config successfully updated" ]] || false run dolt config --list [ "$status" -eq 0 ] [ "$output" = "" ] - run dolt config --get test + run dolt config --get user.name [ "$status" -eq 1 ] [ "$output" = "" ] } @test "config: set and delete multiple config variables" { - dolt config --global --add test1 test1 - dolt config --global --add test2 test2 - dolt config --global --add test3 test3 + dolt config --global --add user.name steph + dolt config --global --add user.email steph@dolthub.com + dolt config --global --add metrics.disabled true run dolt config --list [ "$status" -eq 0 ] [ "${#lines[@]}" -eq 3 ] - run dolt config --global --unset test1 test2 test3 + run dolt config --global --unset user.name user.email metrics.disabled [ "$status" -eq 0 ] [[ "$output" =~ "Config successfully updated" ]] || false run dolt config --list @@ -93,65 +134,65 @@ teardown() { dolt config --global --set user.name "tester" dolt config --global --set user.email "tester@liquidata.co" dolt init - run dolt config --local --set testlocal testlocal + run dolt config --local --set metrics.disabled true [ "$status" -eq 0 ] [[ "$output" =~ "Config successfully updated" ]] || false [ -f .dolt/config.json ] run dolt config --list [ "$status" -eq 0 ] [ "${#lines[@]}" -eq 3 ] - [[ "$output" =~ "testlocal = testlocal" ]] || false - run dolt config --get testlocal + [[ "$output" =~ "metrics.disabled = true" ]] || false + run dolt config --get metrics.disabled [ "$status" -eq 0 ] - [ "$output" = "testlocal" ] + [ "$output" = "true" ] } @test "config: set a local config variable" { dolt config --global --add user.name "bats tester" dolt config --global --add user.email "bats-tester@liquidata.co" dolt init - run dolt config --local --add testlocal testlocal + run dolt config --local --add metrics.disabled true [ "$status" -eq 0 ] [[ "$output" =~ "Config successfully updated" ]] || false [ -f .dolt/config.json ] run dolt config --list [ "$status" -eq 0 ] [ "${#lines[@]}" -eq 3 ] - [[ "$output" =~ "testlocal = testlocal" ]] || false - run dolt config --get testlocal + [[ "$output" =~ "metrics.disabled = true" ]] || false + run dolt config --get metrics.disabled [ "$status" -eq 0 ] - [ "$output" = "testlocal" ] + [ "$output" = "true" ] } @test "config: override a global config variable with a local config variable" { dolt config --global --add user.name "bats tester" dolt config --global --add user.email "bats-tester@liquidata.co" dolt init - dolt config --global --add test global - dolt config --local --add test local - run dolt config --local --get test + dolt config --global --add core.editor globalEditor + dolt config --local --add core.editor localEditor + run dolt config --local --get core.editor [ "$status" -eq 0 ] - [ "$output" = "local" ] + [ "$output" = "localEditor" ] # will list both global and local values in list output run dolt config --list [ "$status" -eq 0 ] - [[ "$output" =~ "test = local" ]] || false - [[ "$output" =~ "test = global" ]] || false + [[ "$output" =~ "core.editor = localEditor" ]] || false + [[ "$output" =~ "core.editor = globalEditor" ]] || false # will get the local value explicitly - run dolt config --get --local test + run dolt config --get --local core.editor [ "$status" -eq 0 ] - [[ "$output" =~ "local" ]] || false - [[ ! "$output" =~ "global" ]] || false + [[ "$output" =~ "localEditor" ]] || false + [[ ! "$output" =~ "globalEditor" ]] || false # will get the global value explicitly - run dolt config --get --global test + run dolt config --get --global core.editor [ "$status" -eq 0 ] - [[ "$output" =~ "global" ]] || false - [[ ! "$output" =~ "local" ]] || false + [[ "$output" =~ "globalEditor" ]] || false + [[ ! "$output" =~ "localEditor" ]] || false # will get the local value implicitly - run dolt config --get test + run dolt config --get core.editor [ "$status" -eq 0 ] - [[ "$output" =~ "local" ]] || false - [[ ! "$output" =~ "global" ]] || false + [[ "$output" =~ "localEditor" ]] || false + [[ ! "$output" =~ "globalEditor" ]] || false } @test "config: Commit to repo w/ ---author and without config vars sets" {