github.com/ungtb10d/cli/v2@v2.0.0-20221110210412-98537dd9d6a1/pkg/cmd/config/set/set.go (about) 1 package set 2 3 import ( 4 "errors" 5 "fmt" 6 "strings" 7 8 "github.com/MakeNowJust/heredoc" 9 "github.com/ungtb10d/cli/v2/internal/config" 10 "github.com/ungtb10d/cli/v2/pkg/cmdutil" 11 "github.com/ungtb10d/cli/v2/pkg/iostreams" 12 "github.com/spf13/cobra" 13 ) 14 15 type SetOptions struct { 16 IO *iostreams.IOStreams 17 Config config.Config 18 19 Key string 20 Value string 21 Hostname string 22 } 23 24 func NewCmdConfigSet(f *cmdutil.Factory, runF func(*SetOptions) error) *cobra.Command { 25 opts := &SetOptions{ 26 IO: f.IOStreams, 27 } 28 29 cmd := &cobra.Command{ 30 Use: "set <key> <value>", 31 Short: "Update configuration with a value for the given key", 32 Example: heredoc.Doc(` 33 $ gh config set editor vim 34 $ gh config set editor "code --wait" 35 $ gh config set git_protocol ssh --host github.com 36 $ gh config set prompt disabled 37 `), 38 Args: cobra.ExactArgs(2), 39 RunE: func(cmd *cobra.Command, args []string) error { 40 config, err := f.Config() 41 if err != nil { 42 return err 43 } 44 opts.Config = config 45 opts.Key = args[0] 46 opts.Value = args[1] 47 48 if runF != nil { 49 return runF(opts) 50 } 51 52 return setRun(opts) 53 }, 54 } 55 56 cmd.Flags().StringVarP(&opts.Hostname, "host", "h", "", "Set per-host setting") 57 58 return cmd 59 } 60 61 func setRun(opts *SetOptions) error { 62 err := ValidateKey(opts.Key) 63 if err != nil { 64 warningIcon := opts.IO.ColorScheme().WarningIcon() 65 fmt.Fprintf(opts.IO.ErrOut, "%s warning: '%s' is not a known configuration key\n", warningIcon, opts.Key) 66 } 67 68 err = ValidateValue(opts.Key, opts.Value) 69 if err != nil { 70 var invalidValue InvalidValueError 71 if errors.As(err, &invalidValue) { 72 var values []string 73 for _, v := range invalidValue.ValidValues { 74 values = append(values, fmt.Sprintf("'%s'", v)) 75 } 76 return fmt.Errorf("failed to set %q to %q: valid values are %v", opts.Key, opts.Value, strings.Join(values, ", ")) 77 } 78 } 79 80 opts.Config.Set(opts.Hostname, opts.Key, opts.Value) 81 82 err = opts.Config.Write() 83 if err != nil { 84 return fmt.Errorf("failed to write config to disk: %w", err) 85 } 86 return nil 87 } 88 89 func ValidateKey(key string) error { 90 for _, configKey := range config.ConfigOptions() { 91 if key == configKey.Key { 92 return nil 93 } 94 } 95 96 return fmt.Errorf("invalid key") 97 } 98 99 type InvalidValueError struct { 100 ValidValues []string 101 } 102 103 func (e InvalidValueError) Error() string { 104 return "invalid value" 105 } 106 107 func ValidateValue(key, value string) error { 108 var validValues []string 109 110 for _, v := range config.ConfigOptions() { 111 if v.Key == key { 112 validValues = v.AllowedValues 113 break 114 } 115 } 116 117 if validValues == nil { 118 return nil 119 } 120 121 for _, v := range validValues { 122 if v == value { 123 return nil 124 } 125 } 126 127 return InvalidValueError{ValidValues: validValues} 128 }