2023-05-01 06:59:34 +03:00
|
|
|
package cli
|
|
|
|
|
|
|
|
import (
|
2023-05-05 17:32:50 +03:00
|
|
|
"fmt"
|
2023-05-07 05:36:34 +03:00
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/samber/lo"
|
2023-11-20 04:06:36 +03:00
|
|
|
"github.com/spf13/cobra"
|
2023-05-05 17:32:50 +03:00
|
|
|
|
2023-05-01 06:59:34 +03:00
|
|
|
"github.com/neilotoole/sq/cli/flag"
|
2023-11-20 04:06:36 +03:00
|
|
|
"github.com/neilotoole/sq/cli/run"
|
2023-05-01 06:59:34 +03:00
|
|
|
"github.com/neilotoole/sq/libsq/core/errz"
|
|
|
|
"github.com/neilotoole/sq/libsq/core/lg/lga"
|
|
|
|
"github.com/neilotoole/sq/libsq/core/options"
|
2023-11-20 04:06:36 +03:00
|
|
|
"github.com/neilotoole/sq/libsq/core/stringz"
|
2023-05-01 06:59:34 +03:00
|
|
|
"github.com/neilotoole/sq/libsq/source"
|
|
|
|
)
|
|
|
|
|
|
|
|
func newConfigSetCmd() *cobra.Command {
|
|
|
|
cmd := &cobra.Command{
|
2023-05-07 05:36:34 +03:00
|
|
|
Use: "set OPTION VALUE",
|
2023-05-01 06:59:34 +03:00
|
|
|
RunE: execConfigSet,
|
2023-05-05 17:32:50 +03:00
|
|
|
Args: cobra.RangeArgs(1, 2),
|
2023-05-01 06:59:34 +03:00
|
|
|
ValidArgsFunction: completeConfigSet,
|
|
|
|
Short: "Set config value",
|
2023-05-07 05:36:34 +03:00
|
|
|
Long: `Set option value, for base config, or for a specified source.
|
|
|
|
To get help for an individual option, use "sq config set OPTION --help".
|
2023-05-22 18:08:14 +03:00
|
|
|
Use "sq config ls -v" to list available options.`,
|
2023-05-05 17:32:50 +03:00
|
|
|
Example: ` # Set base output format
|
2023-05-01 06:59:34 +03:00
|
|
|
$ sq config set format json
|
|
|
|
|
2023-05-05 17:32:50 +03:00
|
|
|
# Set base max DB connections
|
2023-05-01 06:59:34 +03:00
|
|
|
$ sq config set conn.max-open 10
|
|
|
|
|
|
|
|
# Set max DB connections for source @sakila
|
2023-05-05 17:32:50 +03:00
|
|
|
$ sq config set --src @sakila conn.max-open 50
|
|
|
|
|
|
|
|
# Delete an option (resets to default value)
|
2023-05-07 05:36:34 +03:00
|
|
|
$ sq config set -D conn.max-open
|
|
|
|
|
|
|
|
# Help for an individual option
|
|
|
|
$ sq config set conn.max-open --help`,
|
2023-05-01 06:59:34 +03:00
|
|
|
}
|
|
|
|
|
2023-11-21 00:42:38 +03:00
|
|
|
addTextFormatFlags(cmd)
|
2023-05-01 06:59:34 +03:00
|
|
|
cmd.Flags().BoolP(flag.JSON, flag.JSONShort, false, flag.JSONUsage)
|
2023-05-05 20:41:22 +03:00
|
|
|
cmd.Flags().BoolP(flag.Compact, flag.CompactShort, false, flag.CompactUsage)
|
2023-05-01 06:59:34 +03:00
|
|
|
cmd.Flags().BoolP(flag.YAML, flag.YAMLShort, false, flag.YAMLUsage)
|
|
|
|
|
|
|
|
cmd.Flags().String(flag.ConfigSrc, "", flag.ConfigSrcUsage)
|
|
|
|
panicOn(cmd.RegisterFlagCompletionFunc(flag.ConfigSrc, completeHandle(1)))
|
2023-05-05 17:32:50 +03:00
|
|
|
|
|
|
|
cmd.Flags().BoolP(flag.ConfigDelete, flag.ConfigDeleteShort, false, flag.ConfigDeleteUsage)
|
|
|
|
|
2023-05-07 05:36:34 +03:00
|
|
|
cmd.SetHelpFunc(helpConfigSet)
|
|
|
|
|
2023-05-01 06:59:34 +03:00
|
|
|
return cmd
|
|
|
|
}
|
|
|
|
|
|
|
|
func execConfigSet(cmd *cobra.Command, args []string) error {
|
2023-05-05 17:32:50 +03:00
|
|
|
log := logFrom(cmd)
|
2023-05-19 17:24:18 +03:00
|
|
|
ru, ctx := run.FromContext(cmd.Context()), cmd.Context()
|
2023-05-01 06:59:34 +03:00
|
|
|
|
2023-05-19 17:24:18 +03:00
|
|
|
o := ru.Config.Options
|
|
|
|
opt := ru.OptionsRegistry.Get(args[0])
|
2023-05-01 06:59:34 +03:00
|
|
|
if opt == nil {
|
|
|
|
return errz.Errorf("invalid config key: %s", args[0])
|
|
|
|
}
|
|
|
|
|
|
|
|
var src *source.Source
|
|
|
|
if cmdFlagChanged(cmd, flag.ConfigSrc) {
|
2023-07-09 04:34:53 +03:00
|
|
|
if !opt.HasTag(options.TagSource) {
|
|
|
|
return errz.Errorf("config option {%s} does not apply to source config", opt.Key())
|
|
|
|
}
|
|
|
|
|
2023-05-01 06:59:34 +03:00
|
|
|
handle, err := cmd.Flags().GetString(flag.ConfigSrc)
|
|
|
|
if err != nil {
|
|
|
|
return errz.Err(err)
|
|
|
|
}
|
|
|
|
|
2023-05-19 17:24:18 +03:00
|
|
|
src, err = ru.Config.Collection.Get(handle)
|
2023-05-01 06:59:34 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if src.Options == nil {
|
|
|
|
src.Options = options.Options{}
|
|
|
|
}
|
|
|
|
|
|
|
|
o = src.Options
|
|
|
|
}
|
|
|
|
|
2023-05-05 17:32:50 +03:00
|
|
|
if cmdFlagChanged(cmd, flag.ConfigDelete) {
|
|
|
|
if len(args) > 1 {
|
|
|
|
return errz.Errorf("accepts 1 arg when used with --%s flag", flag.ConfigDelete)
|
|
|
|
}
|
|
|
|
|
|
|
|
delete(o, opt.Key())
|
|
|
|
if src == nil {
|
|
|
|
log.Info("Unset base config value", lga.Key, opt.Key())
|
|
|
|
} else {
|
|
|
|
log.Info("Unset source config value", lga.Src, src, lga.Key, opt.Key())
|
|
|
|
}
|
|
|
|
|
2023-05-19 17:24:18 +03:00
|
|
|
if err := ru.ConfigStore.Save(ctx, ru.Config); err != nil {
|
2023-05-05 17:32:50 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2023-05-19 17:24:18 +03:00
|
|
|
return ru.Writers.Config.UnsetOption(opt)
|
2023-05-05 17:32:50 +03:00
|
|
|
}
|
|
|
|
|
2023-05-07 09:01:29 +03:00
|
|
|
if len(args) < 2 {
|
|
|
|
return errz.Errorf("accepts 2 args, received %d", len(args))
|
|
|
|
}
|
|
|
|
|
2023-05-01 06:59:34 +03:00
|
|
|
o2 := options.Options{}
|
|
|
|
o2[opt.Key()] = args[1]
|
|
|
|
var err error
|
|
|
|
|
|
|
|
if o2, err = opt.Process(o2); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
o[opt.Key()] = o2[opt.Key()]
|
2023-05-19 17:24:18 +03:00
|
|
|
if err = ru.ConfigStore.Save(ctx, ru.Config); err != nil {
|
2023-05-01 06:59:34 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2023-05-05 17:32:50 +03:00
|
|
|
if src == nil {
|
|
|
|
log.Info(
|
|
|
|
"Set base config value",
|
|
|
|
lga.Key, opt.Key(),
|
|
|
|
lga.Val, o[opt.Key()],
|
|
|
|
)
|
2023-05-01 06:59:34 +03:00
|
|
|
} else {
|
2023-05-05 17:32:50 +03:00
|
|
|
log.Info(
|
|
|
|
"Set source config value",
|
|
|
|
lga.Key, opt.Key(),
|
|
|
|
lga.Src, src,
|
|
|
|
lga.Val, o,
|
|
|
|
)
|
2023-05-01 06:59:34 +03:00
|
|
|
}
|
|
|
|
|
2023-05-19 17:24:18 +03:00
|
|
|
return ru.Writers.Config.SetOption(o, opt)
|
2023-05-01 06:59:34 +03:00
|
|
|
}
|
|
|
|
|
2023-05-19 17:24:18 +03:00
|
|
|
// completeConfigSet is the completion func for "config set".
|
2023-05-01 06:59:34 +03:00
|
|
|
func completeConfigSet(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
|
|
|
switch len(args) {
|
|
|
|
case 0:
|
|
|
|
return completeOptKey(cmd, args, toComplete)
|
2023-05-05 17:32:50 +03:00
|
|
|
|
2023-05-01 06:59:34 +03:00
|
|
|
case 1:
|
2023-05-05 17:32:50 +03:00
|
|
|
if cmdFlagChanged(cmd, flag.ConfigDelete) {
|
|
|
|
logFrom(cmd).Warn(fmt.Sprintf("No 2nd arg when using --%s flag", flag.ConfigDelete))
|
|
|
|
return nil, cobra.ShellCompDirectiveError
|
|
|
|
}
|
|
|
|
|
2023-05-01 06:59:34 +03:00
|
|
|
return completeOptValue(cmd, args, toComplete)
|
|
|
|
default:
|
|
|
|
// Maximum of two args
|
|
|
|
return nil, cobra.ShellCompDirectiveError
|
|
|
|
}
|
|
|
|
}
|
2023-05-07 05:36:34 +03:00
|
|
|
|
|
|
|
// helpConfigSet is a custom help function for "sq config set KEY".
|
|
|
|
func helpConfigSet(cmd *cobra.Command, arr []string) {
|
|
|
|
hlp := cmd.Parent().HelpFunc()
|
2023-05-19 17:24:18 +03:00
|
|
|
ru := run.FromContext(cmd.Context())
|
|
|
|
if ru == nil || ru.OptionsRegistry == nil || len(arr) < 4 {
|
2023-05-07 05:36:34 +03:00
|
|
|
hlp(cmd, arr)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Flags are not parsed yet. Do a poor man's parsing to
|
|
|
|
// eliminate noise.
|
|
|
|
a := lo.Reject(arr, func(item string, index int) bool {
|
|
|
|
if strings.HasPrefix(item, "-") {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
if index-1 > 0 {
|
|
|
|
if arr[index-1] == "--src" {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
})
|
|
|
|
|
|
|
|
key := a[len(a)-1]
|
2023-05-19 17:24:18 +03:00
|
|
|
opt := ru.OptionsRegistry.Get(key)
|
2023-05-07 05:36:34 +03:00
|
|
|
if opt == nil {
|
|
|
|
hlp(cmd, arr)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
const tpl = `Set config value.
|
|
|
|
|
|
|
|
Usage:
|
|
|
|
sq config set %s %v
|
|
|
|
|
|
|
|
%s
|
|
|
|
|
|
|
|
See docs for more: https://sq.io/docs/config
|
|
|
|
`
|
|
|
|
|
|
|
|
w := cmd.OutOrStdout()
|
2023-07-03 18:34:19 +03:00
|
|
|
|
|
|
|
defVal := fmt.Sprintf("%v", opt.DefaultAny())
|
|
|
|
fmt.Fprintf(w, tpl, key, stringz.ShellEscape(defVal), opt.Help())
|
2023-05-07 05:36:34 +03:00
|
|
|
}
|