-
Notifications
You must be signed in to change notification settings - Fork 13
/
cmd_config_set.go
213 lines (170 loc) · 5.02 KB
/
cmd_config_set.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
package cli
import (
"fmt"
"strings"
"github.com/samber/lo"
"github.com/spf13/cobra"
"github.com/neilotoole/sq/cli/flag"
"github.com/neilotoole/sq/cli/run"
"github.com/neilotoole/sq/libsq/core/errz"
"github.com/neilotoole/sq/libsq/core/lg"
"github.com/neilotoole/sq/libsq/core/lg/lga"
"github.com/neilotoole/sq/libsq/core/options"
"github.com/neilotoole/sq/libsq/core/stringz"
"github.com/neilotoole/sq/libsq/source"
)
func newConfigSetCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "set OPTION VALUE",
RunE: execConfigSet,
Args: cobra.RangeArgs(1, 2),
ValidArgsFunction: completeConfigSet,
Short: "Set config value",
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".
Use "sq config ls -v" to list available options.`,
Example: ` # Set base output format
$ sq config set format json
# Set base max DB connections
$ sq config set conn.max-open 10
# Set max DB connections for source @sakila
$ sq config set --src @sakila conn.max-open 50
# Delete an option (resets to default value)
$ sq config set -D conn.max-open
# Help for an individual option
$ sq config set conn.max-open --help`,
}
cmdMarkRequiresConfigLock(cmd)
addTextFormatFlags(cmd)
cmd.Flags().BoolP(flag.JSON, flag.JSONShort, false, flag.JSONUsage)
addOptionFlag(cmd.Flags(), OptCompact)
cmd.Flags().BoolP(flag.YAML, flag.YAMLShort, false, flag.YAMLUsage)
cmd.Flags().String(flag.ConfigSrc, "", flag.ConfigSrcUsage)
panicOn(cmd.RegisterFlagCompletionFunc(flag.ConfigSrc, completeHandle(1, true)))
cmd.Flags().BoolP(flag.ConfigDelete, flag.ConfigDeleteShort, false, flag.ConfigDeleteUsage)
cmd.SetHelpFunc(helpConfigSet)
return cmd
}
func execConfigSet(cmd *cobra.Command, args []string) error {
log := lg.From(cmd)
ru, ctx := run.FromContext(cmd.Context()), cmd.Context()
o := ru.Config.Options
opt := ru.OptionsRegistry.Get(args[0])
if opt == nil {
return errz.Errorf("invalid config key: %s", args[0])
}
var src *source.Source
if cmdFlagChanged(cmd, flag.ConfigSrc) {
if !opt.HasTag(options.TagSource) {
return errz.Errorf("config option {%s} does not apply to source config", opt.Key())
}
handle, err := cmd.Flags().GetString(flag.ConfigSrc)
if err != nil {
return errz.Err(err)
}
src, err = ru.Config.Collection.Get(handle)
if err != nil {
return err
}
if src.Options == nil {
src.Options = options.Options{}
}
o = src.Options
}
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())
}
if err := ru.ConfigStore.Save(ctx, ru.Config); err != nil {
return err
}
return ru.Writers.Config.UnsetOption(opt)
}
if len(args) < 2 {
return errz.Errorf("accepts 2 args, received %d", len(args))
}
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()]
if err = ru.ConfigStore.Save(ctx, ru.Config); err != nil {
return err
}
if src == nil {
log.Info(
"Set base config value",
lga.Key, opt.Key(),
lga.Val, o[opt.Key()],
)
} else {
log.Info(
"Set source config value",
lga.Key, opt.Key(),
lga.Src, src,
lga.Val, o,
)
}
return ru.Writers.Config.SetOption(o, opt)
}
// completeConfigSet is the completion func for "config set".
func completeConfigSet(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
switch len(args) {
case 0:
return completeOptKey(cmd, args, toComplete)
case 1:
if cmdFlagChanged(cmd, flag.ConfigDelete) {
lg.From(cmd).Warn(fmt.Sprintf("No 2nd arg when using --%s flag", flag.ConfigDelete))
return nil, cobra.ShellCompDirectiveError
}
return completeOptValue(cmd, args, toComplete)
default:
// Maximum of two args
return nil, cobra.ShellCompDirectiveError
}
}
// helpConfigSet is a custom help function for "sq config set KEY".
func helpConfigSet(cmd *cobra.Command, arr []string) {
hlp := cmd.Parent().HelpFunc()
ru := run.FromContext(cmd.Context())
if ru == nil || ru.OptionsRegistry == nil || len(arr) < 4 {
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]
opt := ru.OptionsRegistry.Get(key)
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()
defVal := fmt.Sprintf("%v", opt.DefaultAny())
fmt.Fprintf(w, tpl, key, stringz.ShellEscape(defVal), opt.Help())
}