1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package cobra
18
19 import (
20 "bytes"
21 "context"
22 "errors"
23 "fmt"
24 "io"
25 "os"
26 "path/filepath"
27 "sort"
28 "strings"
29
30 flag "github.com/spf13/pflag"
31 )
32
33 const (
34 FlagSetByCobraAnnotation = "cobra_annotation_flag_set_by_cobra"
35 CommandDisplayNameAnnotation = "cobra_annotation_command_display_name"
36 )
37
38
39 type FParseErrWhitelist flag.ParseErrorsWhitelist
40
41
42 type Group struct {
43 ID string
44 Title string
45 }
46
47
48
49
50
51 type Command struct {
52
53
54
55
56
57
58
59
60
61 Use string
62
63
64 Aliases []string
65
66
67
68 SuggestFor []string
69
70
71 Short string
72
73
74 GroupID string
75
76
77 Long string
78
79
80 Example string
81
82
83 ValidArgs []string
84
85
86
87 ValidArgsFunction func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective)
88
89
90 Args PositionalArgs
91
92
93
94
95 ArgAliases []string
96
97
98
99 BashCompletionFunction string
100
101
102 Deprecated string
103
104
105
106 Annotations map[string]string
107
108
109
110
111
112 Version string
113
114
115
116
117
118
119
120
121
122
123
124
125 PersistentPreRun func(cmd *Command, args []string)
126
127 PersistentPreRunE func(cmd *Command, args []string) error
128
129 PreRun func(cmd *Command, args []string)
130
131 PreRunE func(cmd *Command, args []string) error
132
133 Run func(cmd *Command, args []string)
134
135 RunE func(cmd *Command, args []string) error
136
137 PostRun func(cmd *Command, args []string)
138
139 PostRunE func(cmd *Command, args []string) error
140
141 PersistentPostRun func(cmd *Command, args []string)
142
143 PersistentPostRunE func(cmd *Command, args []string) error
144
145
146 commandgroups []*Group
147
148
149 args []string
150
151 flagErrorBuf *bytes.Buffer
152
153 flags *flag.FlagSet
154
155 pflags *flag.FlagSet
156
157 lflags *flag.FlagSet
158
159 iflags *flag.FlagSet
160
161 parentsPflags *flag.FlagSet
162
163
164 globNormFunc func(f *flag.FlagSet, name string) flag.NormalizedName
165
166
167 usageFunc func(*Command) error
168
169 usageTemplate string
170
171
172 flagErrorFunc func(*Command, error) error
173
174 helpTemplate string
175
176 helpFunc func(*Command, []string)
177
178
179 helpCommand *Command
180
181 helpCommandGroupID string
182
183
184 completionCommandGroupID string
185
186
187 versionTemplate string
188
189
190 errPrefix string
191
192
193 inReader io.Reader
194
195 outWriter io.Writer
196
197 errWriter io.Writer
198
199
200 FParseErrWhitelist FParseErrWhitelist
201
202
203 CompletionOptions CompletionOptions
204
205
206 commandsAreSorted bool
207
208 commandCalledAs struct {
209 name string
210 called bool
211 }
212
213 ctx context.Context
214
215
216 commands []*Command
217
218 parent *Command
219
220 commandsMaxUseLen int
221 commandsMaxCommandPathLen int
222 commandsMaxNameLen int
223
224
225 TraverseChildren bool
226
227
228 Hidden bool
229
230
231 SilenceErrors bool
232
233
234 SilenceUsage bool
235
236
237
238 DisableFlagParsing bool
239
240
241
242 DisableAutoGenTag bool
243
244
245
246 DisableFlagsInUseLine bool
247
248
249
250 DisableSuggestions bool
251
252
253
254 SuggestionsMinimumDistance int
255 }
256
257
258
259
260
261
262
263
264 func (c *Command) Context() context.Context {
265 return c.ctx
266 }
267
268
269
270 func (c *Command) SetContext(ctx context.Context) {
271 c.ctx = ctx
272 }
273
274
275
276 func (c *Command) SetArgs(a []string) {
277 c.args = a
278 }
279
280
281
282
283 func (c *Command) SetOutput(output io.Writer) {
284 c.outWriter = output
285 c.errWriter = output
286 }
287
288
289
290 func (c *Command) SetOut(newOut io.Writer) {
291 c.outWriter = newOut
292 }
293
294
295
296 func (c *Command) SetErr(newErr io.Writer) {
297 c.errWriter = newErr
298 }
299
300
301
302 func (c *Command) SetIn(newIn io.Reader) {
303 c.inReader = newIn
304 }
305
306
307 func (c *Command) SetUsageFunc(f func(*Command) error) {
308 c.usageFunc = f
309 }
310
311
312 func (c *Command) SetUsageTemplate(s string) {
313 c.usageTemplate = s
314 }
315
316
317
318 func (c *Command) SetFlagErrorFunc(f func(*Command, error) error) {
319 c.flagErrorFunc = f
320 }
321
322
323 func (c *Command) SetHelpFunc(f func(*Command, []string)) {
324 c.helpFunc = f
325 }
326
327
328 func (c *Command) SetHelpCommand(cmd *Command) {
329 c.helpCommand = cmd
330 }
331
332
333 func (c *Command) SetHelpCommandGroupID(groupID string) {
334 if c.helpCommand != nil {
335 c.helpCommand.GroupID = groupID
336 }
337
338 c.helpCommandGroupID = groupID
339 }
340
341
342 func (c *Command) SetCompletionCommandGroupID(groupID string) {
343
344 c.Root().completionCommandGroupID = groupID
345 }
346
347
348 func (c *Command) SetHelpTemplate(s string) {
349 c.helpTemplate = s
350 }
351
352
353 func (c *Command) SetVersionTemplate(s string) {
354 c.versionTemplate = s
355 }
356
357
358 func (c *Command) SetErrPrefix(s string) {
359 c.errPrefix = s
360 }
361
362
363
364 func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string) flag.NormalizedName) {
365 c.Flags().SetNormalizeFunc(n)
366 c.PersistentFlags().SetNormalizeFunc(n)
367 c.globNormFunc = n
368
369 for _, command := range c.commands {
370 command.SetGlobalNormalizationFunc(n)
371 }
372 }
373
374
375 func (c *Command) OutOrStdout() io.Writer {
376 return c.getOut(os.Stdout)
377 }
378
379
380 func (c *Command) OutOrStderr() io.Writer {
381 return c.getOut(os.Stderr)
382 }
383
384
385 func (c *Command) ErrOrStderr() io.Writer {
386 return c.getErr(os.Stderr)
387 }
388
389
390 func (c *Command) InOrStdin() io.Reader {
391 return c.getIn(os.Stdin)
392 }
393
394 func (c *Command) getOut(def io.Writer) io.Writer {
395 if c.outWriter != nil {
396 return c.outWriter
397 }
398 if c.HasParent() {
399 return c.parent.getOut(def)
400 }
401 return def
402 }
403
404 func (c *Command) getErr(def io.Writer) io.Writer {
405 if c.errWriter != nil {
406 return c.errWriter
407 }
408 if c.HasParent() {
409 return c.parent.getErr(def)
410 }
411 return def
412 }
413
414 func (c *Command) getIn(def io.Reader) io.Reader {
415 if c.inReader != nil {
416 return c.inReader
417 }
418 if c.HasParent() {
419 return c.parent.getIn(def)
420 }
421 return def
422 }
423
424
425
426 func (c *Command) UsageFunc() (f func(*Command) error) {
427 if c.usageFunc != nil {
428 return c.usageFunc
429 }
430 if c.HasParent() {
431 return c.Parent().UsageFunc()
432 }
433 return func(c *Command) error {
434 c.mergePersistentFlags()
435 err := tmpl(c.OutOrStderr(), c.UsageTemplate(), c)
436 if err != nil {
437 c.PrintErrln(err)
438 }
439 return err
440 }
441 }
442
443
444
445
446 func (c *Command) Usage() error {
447 return c.UsageFunc()(c)
448 }
449
450
451
452 func (c *Command) HelpFunc() func(*Command, []string) {
453 if c.helpFunc != nil {
454 return c.helpFunc
455 }
456 if c.HasParent() {
457 return c.Parent().HelpFunc()
458 }
459 return func(c *Command, a []string) {
460 c.mergePersistentFlags()
461
462
463 err := tmpl(c.OutOrStdout(), c.HelpTemplate(), c)
464 if err != nil {
465 c.PrintErrln(err)
466 }
467 }
468 }
469
470
471
472
473 func (c *Command) Help() error {
474 c.HelpFunc()(c, []string{})
475 return nil
476 }
477
478
479 func (c *Command) UsageString() string {
480
481 tmpOutput := c.outWriter
482 tmpErr := c.errWriter
483
484 bb := new(bytes.Buffer)
485 c.outWriter = bb
486 c.errWriter = bb
487
488 CheckErr(c.Usage())
489
490
491 c.outWriter = tmpOutput
492 c.errWriter = tmpErr
493
494 return bb.String()
495 }
496
497
498
499
500 func (c *Command) FlagErrorFunc() (f func(*Command, error) error) {
501 if c.flagErrorFunc != nil {
502 return c.flagErrorFunc
503 }
504
505 if c.HasParent() {
506 return c.parent.FlagErrorFunc()
507 }
508 return func(c *Command, err error) error {
509 return err
510 }
511 }
512
513 var minUsagePadding = 25
514
515
516 func (c *Command) UsagePadding() int {
517 if c.parent == nil || minUsagePadding > c.parent.commandsMaxUseLen {
518 return minUsagePadding
519 }
520 return c.parent.commandsMaxUseLen
521 }
522
523 var minCommandPathPadding = 11
524
525
526 func (c *Command) CommandPathPadding() int {
527 if c.parent == nil || minCommandPathPadding > c.parent.commandsMaxCommandPathLen {
528 return minCommandPathPadding
529 }
530 return c.parent.commandsMaxCommandPathLen
531 }
532
533 var minNamePadding = 11
534
535
536 func (c *Command) NamePadding() int {
537 if c.parent == nil || minNamePadding > c.parent.commandsMaxNameLen {
538 return minNamePadding
539 }
540 return c.parent.commandsMaxNameLen
541 }
542
543
544 func (c *Command) UsageTemplate() string {
545 if c.usageTemplate != "" {
546 return c.usageTemplate
547 }
548
549 if c.HasParent() {
550 return c.parent.UsageTemplate()
551 }
552 return `Usage:{{if .Runnable}}
553 {{.UseLine}}{{end}}{{if .HasAvailableSubCommands}}
554 {{.CommandPath}} [command]{{end}}{{if gt (len .Aliases) 0}}
555
556 Aliases:
557 {{.NameAndAliases}}{{end}}{{if .HasExample}}
558
559 Examples:
560 {{.Example}}{{end}}{{if .HasAvailableSubCommands}}{{$cmds := .Commands}}{{if eq (len .Groups) 0}}
561
562 Available Commands:{{range $cmds}}{{if (or .IsAvailableCommand (eq .Name "help"))}}
563 {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{else}}{{range $group := .Groups}}
564
565 {{.Title}}{{range $cmds}}{{if (and (eq .GroupID $group.ID) (or .IsAvailableCommand (eq .Name "help")))}}
566 {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if not .AllChildCommandsHaveGroup}}
567
568 Additional Commands:{{range $cmds}}{{if (and (eq .GroupID "") (or .IsAvailableCommand (eq .Name "help")))}}
569 {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}
570
571 Flags:
572 {{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}}
573
574 Global Flags:
575 {{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasHelpSubCommands}}
576
577 Additional help topics:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}}
578 {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableSubCommands}}
579
580 Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}}
581 `
582 }
583
584
585 func (c *Command) HelpTemplate() string {
586 if c.helpTemplate != "" {
587 return c.helpTemplate
588 }
589
590 if c.HasParent() {
591 return c.parent.HelpTemplate()
592 }
593 return `{{with (or .Long .Short)}}{{. | trimTrailingWhitespaces}}
594
595 {{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`
596 }
597
598
599 func (c *Command) VersionTemplate() string {
600 if c.versionTemplate != "" {
601 return c.versionTemplate
602 }
603
604 if c.HasParent() {
605 return c.parent.VersionTemplate()
606 }
607 return `{{with .Name}}{{printf "%s " .}}{{end}}{{printf "version %s" .Version}}
608 `
609 }
610
611
612 func (c *Command) ErrPrefix() string {
613 if c.errPrefix != "" {
614 return c.errPrefix
615 }
616
617 if c.HasParent() {
618 return c.parent.ErrPrefix()
619 }
620 return "Error:"
621 }
622
623 func hasNoOptDefVal(name string, fs *flag.FlagSet) bool {
624 flag := fs.Lookup(name)
625 if flag == nil {
626 return false
627 }
628 return flag.NoOptDefVal != ""
629 }
630
631 func shortHasNoOptDefVal(name string, fs *flag.FlagSet) bool {
632 if len(name) == 0 {
633 return false
634 }
635
636 flag := fs.ShorthandLookup(name[:1])
637 if flag == nil {
638 return false
639 }
640 return flag.NoOptDefVal != ""
641 }
642
643 func stripFlags(args []string, c *Command) []string {
644 if len(args) == 0 {
645 return args
646 }
647 c.mergePersistentFlags()
648
649 commands := []string{}
650 flags := c.Flags()
651
652 Loop:
653 for len(args) > 0 {
654 s := args[0]
655 args = args[1:]
656 switch {
657 case s == "--":
658
659 break Loop
660 case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags):
661
662
663 fallthrough
664 case strings.HasPrefix(s, "-") && !strings.Contains(s, "=") && len(s) == 2 && !shortHasNoOptDefVal(s[1:], flags):
665
666
667 if len(args) <= 1 {
668 break Loop
669 } else {
670 args = args[1:]
671 continue
672 }
673 case s != "" && !strings.HasPrefix(s, "-"):
674 commands = append(commands, s)
675 }
676 }
677
678 return commands
679 }
680
681
682
683
684 func (c *Command) argsMinusFirstX(args []string, x string) []string {
685 if len(args) == 0 {
686 return args
687 }
688 c.mergePersistentFlags()
689 flags := c.Flags()
690
691 Loop:
692 for pos := 0; pos < len(args); pos++ {
693 s := args[pos]
694 switch {
695 case s == "--":
696
697 break Loop
698 case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags):
699 fallthrough
700 case strings.HasPrefix(s, "-") && !strings.Contains(s, "=") && len(s) == 2 && !shortHasNoOptDefVal(s[1:], flags):
701
702
703 pos++
704 continue
705 case !strings.HasPrefix(s, "-"):
706
707
708 if s == x {
709 ret := []string{}
710 ret = append(ret, args[:pos]...)
711 ret = append(ret, args[pos+1:]...)
712 return ret
713 }
714 }
715 }
716 return args
717 }
718
719 func isFlagArg(arg string) bool {
720 return ((len(arg) >= 3 && arg[0:2] == "--") ||
721 (len(arg) >= 2 && arg[0] == '-' && arg[1] != '-'))
722 }
723
724
725
726 func (c *Command) Find(args []string) (*Command, []string, error) {
727 var innerfind func(*Command, []string) (*Command, []string)
728
729 innerfind = func(c *Command, innerArgs []string) (*Command, []string) {
730 argsWOflags := stripFlags(innerArgs, c)
731 if len(argsWOflags) == 0 {
732 return c, innerArgs
733 }
734 nextSubCmd := argsWOflags[0]
735
736 cmd := c.findNext(nextSubCmd)
737 if cmd != nil {
738 return innerfind(cmd, c.argsMinusFirstX(innerArgs, nextSubCmd))
739 }
740 return c, innerArgs
741 }
742
743 commandFound, a := innerfind(c, args)
744 if commandFound.Args == nil {
745 return commandFound, a, legacyArgs(commandFound, stripFlags(a, commandFound))
746 }
747 return commandFound, a, nil
748 }
749
750 func (c *Command) findSuggestions(arg string) string {
751 if c.DisableSuggestions {
752 return ""
753 }
754 if c.SuggestionsMinimumDistance <= 0 {
755 c.SuggestionsMinimumDistance = 2
756 }
757 suggestionsString := ""
758 if suggestions := c.SuggestionsFor(arg); len(suggestions) > 0 {
759 suggestionsString += "\n\nDid you mean this?\n"
760 for _, s := range suggestions {
761 suggestionsString += fmt.Sprintf("\t%v\n", s)
762 }
763 }
764 return suggestionsString
765 }
766
767 func (c *Command) findNext(next string) *Command {
768 matches := make([]*Command, 0)
769 for _, cmd := range c.commands {
770 if commandNameMatches(cmd.Name(), next) || cmd.HasAlias(next) {
771 cmd.commandCalledAs.name = next
772 return cmd
773 }
774 if EnablePrefixMatching && cmd.hasNameOrAliasPrefix(next) {
775 matches = append(matches, cmd)
776 }
777 }
778
779 if len(matches) == 1 {
780
781
782 return matches[0]
783 }
784
785 return nil
786 }
787
788
789
790 func (c *Command) Traverse(args []string) (*Command, []string, error) {
791 flags := []string{}
792 inFlag := false
793
794 for i, arg := range args {
795 switch {
796
797 case strings.HasPrefix(arg, "--") && !strings.Contains(arg, "="):
798
799 inFlag = !hasNoOptDefVal(arg[2:], c.Flags())
800 flags = append(flags, arg)
801 continue
802
803 case strings.HasPrefix(arg, "-") && !strings.Contains(arg, "=") && len(arg) == 2 && !shortHasNoOptDefVal(arg[1:], c.Flags()):
804 inFlag = true
805 flags = append(flags, arg)
806 continue
807
808 case inFlag:
809 inFlag = false
810 flags = append(flags, arg)
811 continue
812
813 case isFlagArg(arg):
814 flags = append(flags, arg)
815 continue
816 }
817
818 cmd := c.findNext(arg)
819 if cmd == nil {
820 return c, args, nil
821 }
822
823 if err := c.ParseFlags(flags); err != nil {
824 return nil, args, err
825 }
826 return cmd.Traverse(args[i+1:])
827 }
828 return c, args, nil
829 }
830
831
832 func (c *Command) SuggestionsFor(typedName string) []string {
833 suggestions := []string{}
834 for _, cmd := range c.commands {
835 if cmd.IsAvailableCommand() {
836 levenshteinDistance := ld(typedName, cmd.Name(), true)
837 suggestByLevenshtein := levenshteinDistance <= c.SuggestionsMinimumDistance
838 suggestByPrefix := strings.HasPrefix(strings.ToLower(cmd.Name()), strings.ToLower(typedName))
839 if suggestByLevenshtein || suggestByPrefix {
840 suggestions = append(suggestions, cmd.Name())
841 }
842 for _, explicitSuggestion := range cmd.SuggestFor {
843 if strings.EqualFold(typedName, explicitSuggestion) {
844 suggestions = append(suggestions, cmd.Name())
845 }
846 }
847 }
848 }
849 return suggestions
850 }
851
852
853 func (c *Command) VisitParents(fn func(*Command)) {
854 if c.HasParent() {
855 fn(c.Parent())
856 c.Parent().VisitParents(fn)
857 }
858 }
859
860
861 func (c *Command) Root() *Command {
862 if c.HasParent() {
863 return c.Parent().Root()
864 }
865 return c
866 }
867
868
869
870 func (c *Command) ArgsLenAtDash() int {
871 return c.Flags().ArgsLenAtDash()
872 }
873
874 func (c *Command) execute(a []string) (err error) {
875 if c == nil {
876 return fmt.Errorf("Called Execute() on a nil Command")
877 }
878
879 if len(c.Deprecated) > 0 {
880 c.Printf("Command %q is deprecated, %s\n", c.Name(), c.Deprecated)
881 }
882
883
884
885 c.InitDefaultHelpFlag()
886 c.InitDefaultVersionFlag()
887
888 err = c.ParseFlags(a)
889 if err != nil {
890 return c.FlagErrorFunc()(c, err)
891 }
892
893
894
895 helpVal, err := c.Flags().GetBool("help")
896 if err != nil {
897
898
899 c.Println("\"help\" flag declared as non-bool. Please correct your code")
900 return err
901 }
902
903 if helpVal {
904 return flag.ErrHelp
905 }
906
907
908 if c.Version != "" {
909 versionVal, err := c.Flags().GetBool("version")
910 if err != nil {
911 c.Println("\"version\" flag declared as non-bool. Please correct your code")
912 return err
913 }
914 if versionVal {
915 err := tmpl(c.OutOrStdout(), c.VersionTemplate(), c)
916 if err != nil {
917 c.Println(err)
918 }
919 return err
920 }
921 }
922
923 if !c.Runnable() {
924 return flag.ErrHelp
925 }
926
927 c.preRun()
928
929 defer c.postRun()
930
931 argWoFlags := c.Flags().Args()
932 if c.DisableFlagParsing {
933 argWoFlags = a
934 }
935
936 if err := c.ValidateArgs(argWoFlags); err != nil {
937 return err
938 }
939
940 parents := make([]*Command, 0, 5)
941 for p := c; p != nil; p = p.Parent() {
942 if EnableTraverseRunHooks {
943
944
945
946 parents = append([]*Command{p}, parents...)
947 } else {
948
949 parents = append(parents, p)
950 }
951 }
952 for _, p := range parents {
953 if p.PersistentPreRunE != nil {
954 if err := p.PersistentPreRunE(c, argWoFlags); err != nil {
955 return err
956 }
957 if !EnableTraverseRunHooks {
958 break
959 }
960 } else if p.PersistentPreRun != nil {
961 p.PersistentPreRun(c, argWoFlags)
962 if !EnableTraverseRunHooks {
963 break
964 }
965 }
966 }
967 if c.PreRunE != nil {
968 if err := c.PreRunE(c, argWoFlags); err != nil {
969 return err
970 }
971 } else if c.PreRun != nil {
972 c.PreRun(c, argWoFlags)
973 }
974
975 if err := c.ValidateRequiredFlags(); err != nil {
976 return err
977 }
978 if err := c.ValidateFlagGroups(); err != nil {
979 return err
980 }
981
982 if c.RunE != nil {
983 if err := c.RunE(c, argWoFlags); err != nil {
984 return err
985 }
986 } else {
987 c.Run(c, argWoFlags)
988 }
989 if c.PostRunE != nil {
990 if err := c.PostRunE(c, argWoFlags); err != nil {
991 return err
992 }
993 } else if c.PostRun != nil {
994 c.PostRun(c, argWoFlags)
995 }
996 for p := c; p != nil; p = p.Parent() {
997 if p.PersistentPostRunE != nil {
998 if err := p.PersistentPostRunE(c, argWoFlags); err != nil {
999 return err
1000 }
1001 if !EnableTraverseRunHooks {
1002 break
1003 }
1004 } else if p.PersistentPostRun != nil {
1005 p.PersistentPostRun(c, argWoFlags)
1006 if !EnableTraverseRunHooks {
1007 break
1008 }
1009 }
1010 }
1011
1012 return nil
1013 }
1014
1015 func (c *Command) preRun() {
1016 for _, x := range initializers {
1017 x()
1018 }
1019 }
1020
1021 func (c *Command) postRun() {
1022 for _, x := range finalizers {
1023 x()
1024 }
1025 }
1026
1027
1028
1029
1030 func (c *Command) ExecuteContext(ctx context.Context) error {
1031 c.ctx = ctx
1032 return c.Execute()
1033 }
1034
1035
1036
1037
1038 func (c *Command) Execute() error {
1039 _, err := c.ExecuteC()
1040 return err
1041 }
1042
1043
1044
1045
1046 func (c *Command) ExecuteContextC(ctx context.Context) (*Command, error) {
1047 c.ctx = ctx
1048 return c.ExecuteC()
1049 }
1050
1051
1052 func (c *Command) ExecuteC() (cmd *Command, err error) {
1053 if c.ctx == nil {
1054 c.ctx = context.Background()
1055 }
1056
1057
1058 if c.HasParent() {
1059 return c.Root().ExecuteC()
1060 }
1061
1062
1063 if preExecHookFn != nil {
1064 preExecHookFn(c)
1065 }
1066
1067
1068 c.InitDefaultHelpCmd()
1069
1070 c.InitDefaultCompletionCmd()
1071
1072
1073
1074 c.checkCommandGroups()
1075
1076 args := c.args
1077
1078
1079 if c.args == nil && filepath.Base(os.Args[0]) != "cobra.test" {
1080 args = os.Args[1:]
1081 }
1082
1083
1084 c.initCompleteCmd(args)
1085
1086 var flags []string
1087 if c.TraverseChildren {
1088 cmd, flags, err = c.Traverse(args)
1089 } else {
1090 cmd, flags, err = c.Find(args)
1091 }
1092 if err != nil {
1093
1094 if cmd != nil {
1095 c = cmd
1096 }
1097 if !c.SilenceErrors {
1098 c.PrintErrln(c.ErrPrefix(), err.Error())
1099 c.PrintErrf("Run '%v --help' for usage.\n", c.CommandPath())
1100 }
1101 return c, err
1102 }
1103
1104 cmd.commandCalledAs.called = true
1105 if cmd.commandCalledAs.name == "" {
1106 cmd.commandCalledAs.name = cmd.Name()
1107 }
1108
1109
1110
1111 if cmd.ctx == nil {
1112 cmd.ctx = c.ctx
1113 }
1114
1115 err = cmd.execute(flags)
1116 if err != nil {
1117
1118
1119 if errors.Is(err, flag.ErrHelp) {
1120 cmd.HelpFunc()(cmd, args)
1121 return cmd, nil
1122 }
1123
1124
1125
1126 if !cmd.SilenceErrors && !c.SilenceErrors {
1127 c.PrintErrln(cmd.ErrPrefix(), err.Error())
1128 }
1129
1130
1131
1132 if !cmd.SilenceUsage && !c.SilenceUsage {
1133 c.Println(cmd.UsageString())
1134 }
1135 }
1136 return cmd, err
1137 }
1138
1139 func (c *Command) ValidateArgs(args []string) error {
1140 if c.Args == nil {
1141 return ArbitraryArgs(c, args)
1142 }
1143 return c.Args(c, args)
1144 }
1145
1146
1147 func (c *Command) ValidateRequiredFlags() error {
1148 if c.DisableFlagParsing {
1149 return nil
1150 }
1151
1152 flags := c.Flags()
1153 missingFlagNames := []string{}
1154 flags.VisitAll(func(pflag *flag.Flag) {
1155 requiredAnnotation, found := pflag.Annotations[BashCompOneRequiredFlag]
1156 if !found {
1157 return
1158 }
1159 if (requiredAnnotation[0] == "true") && !pflag.Changed {
1160 missingFlagNames = append(missingFlagNames, pflag.Name)
1161 }
1162 })
1163
1164 if len(missingFlagNames) > 0 {
1165 return fmt.Errorf(`required flag(s) "%s" not set`, strings.Join(missingFlagNames, `", "`))
1166 }
1167 return nil
1168 }
1169
1170
1171
1172 func (c *Command) checkCommandGroups() {
1173 for _, sub := range c.commands {
1174
1175 if sub.GroupID != "" && !c.ContainsGroup(sub.GroupID) {
1176 panic(fmt.Sprintf("group id '%s' is not defined for subcommand '%s'", sub.GroupID, sub.CommandPath()))
1177 }
1178
1179 sub.checkCommandGroups()
1180 }
1181 }
1182
1183
1184
1185
1186 func (c *Command) InitDefaultHelpFlag() {
1187 c.mergePersistentFlags()
1188 if c.Flags().Lookup("help") == nil {
1189 usage := "help for "
1190 if c.Name() == "" {
1191 usage += "this command"
1192 } else {
1193 usage += c.Name()
1194 }
1195 c.Flags().BoolP("help", "h", false, usage)
1196 _ = c.Flags().SetAnnotation("help", FlagSetByCobraAnnotation, []string{"true"})
1197 }
1198 }
1199
1200
1201
1202
1203
1204 func (c *Command) InitDefaultVersionFlag() {
1205 if c.Version == "" {
1206 return
1207 }
1208
1209 c.mergePersistentFlags()
1210 if c.Flags().Lookup("version") == nil {
1211 usage := "version for "
1212 if c.Name() == "" {
1213 usage += "this command"
1214 } else {
1215 usage += c.Name()
1216 }
1217 if c.Flags().ShorthandLookup("v") == nil {
1218 c.Flags().BoolP("version", "v", false, usage)
1219 } else {
1220 c.Flags().Bool("version", false, usage)
1221 }
1222 _ = c.Flags().SetAnnotation("version", FlagSetByCobraAnnotation, []string{"true"})
1223 }
1224 }
1225
1226
1227
1228
1229 func (c *Command) InitDefaultHelpCmd() {
1230 if !c.HasSubCommands() {
1231 return
1232 }
1233
1234 if c.helpCommand == nil {
1235 c.helpCommand = &Command{
1236 Use: "help [command]",
1237 Short: "Help about any command",
1238 Long: `Help provides help for any command in the application.
1239 Simply type ` + c.Name() + ` help [path to command] for full details.`,
1240 ValidArgsFunction: func(c *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
1241 var completions []string
1242 cmd, _, e := c.Root().Find(args)
1243 if e != nil {
1244 return nil, ShellCompDirectiveNoFileComp
1245 }
1246 if cmd == nil {
1247
1248 cmd = c.Root()
1249 }
1250 for _, subCmd := range cmd.Commands() {
1251 if subCmd.IsAvailableCommand() || subCmd == cmd.helpCommand {
1252 if strings.HasPrefix(subCmd.Name(), toComplete) {
1253 completions = append(completions, fmt.Sprintf("%s\t%s", subCmd.Name(), subCmd.Short))
1254 }
1255 }
1256 }
1257 return completions, ShellCompDirectiveNoFileComp
1258 },
1259 Run: func(c *Command, args []string) {
1260 cmd, _, e := c.Root().Find(args)
1261 if cmd == nil || e != nil {
1262 c.Printf("Unknown help topic %#q\n", args)
1263 CheckErr(c.Root().Usage())
1264 } else {
1265 cmd.InitDefaultHelpFlag()
1266 cmd.InitDefaultVersionFlag()
1267 CheckErr(cmd.Help())
1268 }
1269 },
1270 GroupID: c.helpCommandGroupID,
1271 }
1272 }
1273 c.RemoveCommand(c.helpCommand)
1274 c.AddCommand(c.helpCommand)
1275 }
1276
1277
1278 func (c *Command) ResetCommands() {
1279 c.parent = nil
1280 c.commands = nil
1281 c.helpCommand = nil
1282 c.parentsPflags = nil
1283 }
1284
1285
1286 type commandSorterByName []*Command
1287
1288 func (c commandSorterByName) Len() int { return len(c) }
1289 func (c commandSorterByName) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
1290 func (c commandSorterByName) Less(i, j int) bool { return c[i].Name() < c[j].Name() }
1291
1292
1293 func (c *Command) Commands() []*Command {
1294
1295 if EnableCommandSorting && !c.commandsAreSorted {
1296 sort.Sort(commandSorterByName(c.commands))
1297 c.commandsAreSorted = true
1298 }
1299 return c.commands
1300 }
1301
1302
1303 func (c *Command) AddCommand(cmds ...*Command) {
1304 for i, x := range cmds {
1305 if cmds[i] == c {
1306 panic("Command can't be a child of itself")
1307 }
1308 cmds[i].parent = c
1309
1310 usageLen := len(x.Use)
1311 if usageLen > c.commandsMaxUseLen {
1312 c.commandsMaxUseLen = usageLen
1313 }
1314 commandPathLen := len(x.CommandPath())
1315 if commandPathLen > c.commandsMaxCommandPathLen {
1316 c.commandsMaxCommandPathLen = commandPathLen
1317 }
1318 nameLen := len(x.Name())
1319 if nameLen > c.commandsMaxNameLen {
1320 c.commandsMaxNameLen = nameLen
1321 }
1322
1323 if c.globNormFunc != nil {
1324 x.SetGlobalNormalizationFunc(c.globNormFunc)
1325 }
1326 c.commands = append(c.commands, x)
1327 c.commandsAreSorted = false
1328 }
1329 }
1330
1331
1332 func (c *Command) Groups() []*Group {
1333 return c.commandgroups
1334 }
1335
1336
1337 func (c *Command) AllChildCommandsHaveGroup() bool {
1338 for _, sub := range c.commands {
1339 if (sub.IsAvailableCommand() || sub == c.helpCommand) && sub.GroupID == "" {
1340 return false
1341 }
1342 }
1343 return true
1344 }
1345
1346
1347 func (c *Command) ContainsGroup(groupID string) bool {
1348 for _, x := range c.commandgroups {
1349 if x.ID == groupID {
1350 return true
1351 }
1352 }
1353 return false
1354 }
1355
1356
1357 func (c *Command) AddGroup(groups ...*Group) {
1358 c.commandgroups = append(c.commandgroups, groups...)
1359 }
1360
1361
1362 func (c *Command) RemoveCommand(cmds ...*Command) {
1363 commands := []*Command{}
1364 main:
1365 for _, command := range c.commands {
1366 for _, cmd := range cmds {
1367 if command == cmd {
1368 command.parent = nil
1369 continue main
1370 }
1371 }
1372 commands = append(commands, command)
1373 }
1374 c.commands = commands
1375
1376 c.commandsMaxUseLen = 0
1377 c.commandsMaxCommandPathLen = 0
1378 c.commandsMaxNameLen = 0
1379 for _, command := range c.commands {
1380 usageLen := len(command.Use)
1381 if usageLen > c.commandsMaxUseLen {
1382 c.commandsMaxUseLen = usageLen
1383 }
1384 commandPathLen := len(command.CommandPath())
1385 if commandPathLen > c.commandsMaxCommandPathLen {
1386 c.commandsMaxCommandPathLen = commandPathLen
1387 }
1388 nameLen := len(command.Name())
1389 if nameLen > c.commandsMaxNameLen {
1390 c.commandsMaxNameLen = nameLen
1391 }
1392 }
1393 }
1394
1395
1396 func (c *Command) Print(i ...interface{}) {
1397 fmt.Fprint(c.OutOrStderr(), i...)
1398 }
1399
1400
1401 func (c *Command) Println(i ...interface{}) {
1402 c.Print(fmt.Sprintln(i...))
1403 }
1404
1405
1406 func (c *Command) Printf(format string, i ...interface{}) {
1407 c.Print(fmt.Sprintf(format, i...))
1408 }
1409
1410
1411 func (c *Command) PrintErr(i ...interface{}) {
1412 fmt.Fprint(c.ErrOrStderr(), i...)
1413 }
1414
1415
1416 func (c *Command) PrintErrln(i ...interface{}) {
1417 c.PrintErr(fmt.Sprintln(i...))
1418 }
1419
1420
1421 func (c *Command) PrintErrf(format string, i ...interface{}) {
1422 c.PrintErr(fmt.Sprintf(format, i...))
1423 }
1424
1425
1426 func (c *Command) CommandPath() string {
1427 if c.HasParent() {
1428 return c.Parent().CommandPath() + " " + c.Name()
1429 }
1430 if displayName, ok := c.Annotations[CommandDisplayNameAnnotation]; ok {
1431 return displayName
1432 }
1433 return c.Name()
1434 }
1435
1436
1437 func (c *Command) UseLine() string {
1438 var useline string
1439 if c.HasParent() {
1440 useline = c.parent.CommandPath() + " " + c.Use
1441 } else {
1442 useline = c.Use
1443 }
1444 if c.DisableFlagsInUseLine {
1445 return useline
1446 }
1447 if c.HasAvailableFlags() && !strings.Contains(useline, "[flags]") {
1448 useline += " [flags]"
1449 }
1450 return useline
1451 }
1452
1453
1454
1455
1456 func (c *Command) DebugFlags() {
1457 c.Println("DebugFlags called on", c.Name())
1458 var debugflags func(*Command)
1459
1460 debugflags = func(x *Command) {
1461 if x.HasFlags() || x.HasPersistentFlags() {
1462 c.Println(x.Name())
1463 }
1464 if x.HasFlags() {
1465 x.flags.VisitAll(func(f *flag.Flag) {
1466 if x.HasPersistentFlags() && x.persistentFlag(f.Name) != nil {
1467 c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [LP]")
1468 } else {
1469 c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [L]")
1470 }
1471 })
1472 }
1473 if x.HasPersistentFlags() {
1474 x.pflags.VisitAll(func(f *flag.Flag) {
1475 if x.HasFlags() {
1476 if x.flags.Lookup(f.Name) == nil {
1477 c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [P]")
1478 }
1479 } else {
1480 c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [P]")
1481 }
1482 })
1483 }
1484 c.Println(x.flagErrorBuf)
1485 if x.HasSubCommands() {
1486 for _, y := range x.commands {
1487 debugflags(y)
1488 }
1489 }
1490 }
1491
1492 debugflags(c)
1493 }
1494
1495
1496 func (c *Command) Name() string {
1497 name := c.Use
1498 i := strings.Index(name, " ")
1499 if i >= 0 {
1500 name = name[:i]
1501 }
1502 return name
1503 }
1504
1505
1506 func (c *Command) HasAlias(s string) bool {
1507 for _, a := range c.Aliases {
1508 if commandNameMatches(a, s) {
1509 return true
1510 }
1511 }
1512 return false
1513 }
1514
1515
1516
1517 func (c *Command) CalledAs() string {
1518 if c.commandCalledAs.called {
1519 return c.commandCalledAs.name
1520 }
1521 return ""
1522 }
1523
1524
1525
1526 func (c *Command) hasNameOrAliasPrefix(prefix string) bool {
1527 if strings.HasPrefix(c.Name(), prefix) {
1528 c.commandCalledAs.name = c.Name()
1529 return true
1530 }
1531 for _, alias := range c.Aliases {
1532 if strings.HasPrefix(alias, prefix) {
1533 c.commandCalledAs.name = alias
1534 return true
1535 }
1536 }
1537 return false
1538 }
1539
1540
1541 func (c *Command) NameAndAliases() string {
1542 return strings.Join(append([]string{c.Name()}, c.Aliases...), ", ")
1543 }
1544
1545
1546 func (c *Command) HasExample() bool {
1547 return len(c.Example) > 0
1548 }
1549
1550
1551 func (c *Command) Runnable() bool {
1552 return c.Run != nil || c.RunE != nil
1553 }
1554
1555
1556 func (c *Command) HasSubCommands() bool {
1557 return len(c.commands) > 0
1558 }
1559
1560
1561
1562 func (c *Command) IsAvailableCommand() bool {
1563 if len(c.Deprecated) != 0 || c.Hidden {
1564 return false
1565 }
1566
1567 if c.HasParent() && c.Parent().helpCommand == c {
1568 return false
1569 }
1570
1571 if c.Runnable() || c.HasAvailableSubCommands() {
1572 return true
1573 }
1574
1575 return false
1576 }
1577
1578
1579
1580
1581
1582
1583 func (c *Command) IsAdditionalHelpTopicCommand() bool {
1584
1585 if c.Runnable() || len(c.Deprecated) != 0 || c.Hidden {
1586 return false
1587 }
1588
1589
1590 for _, sub := range c.commands {
1591 if !sub.IsAdditionalHelpTopicCommand() {
1592 return false
1593 }
1594 }
1595
1596
1597 return true
1598 }
1599
1600
1601
1602
1603 func (c *Command) HasHelpSubCommands() bool {
1604
1605 for _, sub := range c.commands {
1606 if sub.IsAdditionalHelpTopicCommand() {
1607 return true
1608 }
1609 }
1610
1611
1612 return false
1613 }
1614
1615
1616
1617 func (c *Command) HasAvailableSubCommands() bool {
1618
1619
1620 for _, sub := range c.commands {
1621 if sub.IsAvailableCommand() {
1622 return true
1623 }
1624 }
1625
1626
1627
1628 return false
1629 }
1630
1631
1632 func (c *Command) HasParent() bool {
1633 return c.parent != nil
1634 }
1635
1636
1637 func (c *Command) GlobalNormalizationFunc() func(f *flag.FlagSet, name string) flag.NormalizedName {
1638 return c.globNormFunc
1639 }
1640
1641
1642
1643 func (c *Command) Flags() *flag.FlagSet {
1644 if c.flags == nil {
1645 c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
1646 if c.flagErrorBuf == nil {
1647 c.flagErrorBuf = new(bytes.Buffer)
1648 }
1649 c.flags.SetOutput(c.flagErrorBuf)
1650 }
1651
1652 return c.flags
1653 }
1654
1655
1656 func (c *Command) LocalNonPersistentFlags() *flag.FlagSet {
1657 persistentFlags := c.PersistentFlags()
1658
1659 out := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
1660 c.LocalFlags().VisitAll(func(f *flag.Flag) {
1661 if persistentFlags.Lookup(f.Name) == nil {
1662 out.AddFlag(f)
1663 }
1664 })
1665 return out
1666 }
1667
1668
1669 func (c *Command) LocalFlags() *flag.FlagSet {
1670 c.mergePersistentFlags()
1671
1672 if c.lflags == nil {
1673 c.lflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
1674 if c.flagErrorBuf == nil {
1675 c.flagErrorBuf = new(bytes.Buffer)
1676 }
1677 c.lflags.SetOutput(c.flagErrorBuf)
1678 }
1679 c.lflags.SortFlags = c.Flags().SortFlags
1680 if c.globNormFunc != nil {
1681 c.lflags.SetNormalizeFunc(c.globNormFunc)
1682 }
1683
1684 addToLocal := func(f *flag.Flag) {
1685
1686 if c.lflags.Lookup(f.Name) == nil && f != c.parentsPflags.Lookup(f.Name) {
1687 c.lflags.AddFlag(f)
1688 }
1689 }
1690 c.Flags().VisitAll(addToLocal)
1691 c.PersistentFlags().VisitAll(addToLocal)
1692 return c.lflags
1693 }
1694
1695
1696 func (c *Command) InheritedFlags() *flag.FlagSet {
1697 c.mergePersistentFlags()
1698
1699 if c.iflags == nil {
1700 c.iflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
1701 if c.flagErrorBuf == nil {
1702 c.flagErrorBuf = new(bytes.Buffer)
1703 }
1704 c.iflags.SetOutput(c.flagErrorBuf)
1705 }
1706
1707 local := c.LocalFlags()
1708 if c.globNormFunc != nil {
1709 c.iflags.SetNormalizeFunc(c.globNormFunc)
1710 }
1711
1712 c.parentsPflags.VisitAll(func(f *flag.Flag) {
1713 if c.iflags.Lookup(f.Name) == nil && local.Lookup(f.Name) == nil {
1714 c.iflags.AddFlag(f)
1715 }
1716 })
1717 return c.iflags
1718 }
1719
1720
1721 func (c *Command) NonInheritedFlags() *flag.FlagSet {
1722 return c.LocalFlags()
1723 }
1724
1725
1726 func (c *Command) PersistentFlags() *flag.FlagSet {
1727 if c.pflags == nil {
1728 c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
1729 if c.flagErrorBuf == nil {
1730 c.flagErrorBuf = new(bytes.Buffer)
1731 }
1732 c.pflags.SetOutput(c.flagErrorBuf)
1733 }
1734 return c.pflags
1735 }
1736
1737
1738 func (c *Command) ResetFlags() {
1739 c.flagErrorBuf = new(bytes.Buffer)
1740 c.flagErrorBuf.Reset()
1741 c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
1742 c.flags.SetOutput(c.flagErrorBuf)
1743 c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
1744 c.pflags.SetOutput(c.flagErrorBuf)
1745
1746 c.lflags = nil
1747 c.iflags = nil
1748 c.parentsPflags = nil
1749 }
1750
1751
1752 func (c *Command) HasFlags() bool {
1753 return c.Flags().HasFlags()
1754 }
1755
1756
1757 func (c *Command) HasPersistentFlags() bool {
1758 return c.PersistentFlags().HasFlags()
1759 }
1760
1761
1762 func (c *Command) HasLocalFlags() bool {
1763 return c.LocalFlags().HasFlags()
1764 }
1765
1766
1767 func (c *Command) HasInheritedFlags() bool {
1768 return c.InheritedFlags().HasFlags()
1769 }
1770
1771
1772
1773 func (c *Command) HasAvailableFlags() bool {
1774 return c.Flags().HasAvailableFlags()
1775 }
1776
1777
1778 func (c *Command) HasAvailablePersistentFlags() bool {
1779 return c.PersistentFlags().HasAvailableFlags()
1780 }
1781
1782
1783
1784 func (c *Command) HasAvailableLocalFlags() bool {
1785 return c.LocalFlags().HasAvailableFlags()
1786 }
1787
1788
1789
1790 func (c *Command) HasAvailableInheritedFlags() bool {
1791 return c.InheritedFlags().HasAvailableFlags()
1792 }
1793
1794
1795 func (c *Command) Flag(name string) (flag *flag.Flag) {
1796 flag = c.Flags().Lookup(name)
1797
1798 if flag == nil {
1799 flag = c.persistentFlag(name)
1800 }
1801
1802 return
1803 }
1804
1805
1806 func (c *Command) persistentFlag(name string) (flag *flag.Flag) {
1807 if c.HasPersistentFlags() {
1808 flag = c.PersistentFlags().Lookup(name)
1809 }
1810
1811 if flag == nil {
1812 c.updateParentsPflags()
1813 flag = c.parentsPflags.Lookup(name)
1814 }
1815 return
1816 }
1817
1818
1819 func (c *Command) ParseFlags(args []string) error {
1820 if c.DisableFlagParsing {
1821 return nil
1822 }
1823
1824 if c.flagErrorBuf == nil {
1825 c.flagErrorBuf = new(bytes.Buffer)
1826 }
1827 beforeErrorBufLen := c.flagErrorBuf.Len()
1828 c.mergePersistentFlags()
1829
1830
1831 c.Flags().ParseErrorsWhitelist = flag.ParseErrorsWhitelist(c.FParseErrWhitelist)
1832
1833 err := c.Flags().Parse(args)
1834
1835 if c.flagErrorBuf.Len()-beforeErrorBufLen > 0 && err == nil {
1836 c.Print(c.flagErrorBuf.String())
1837 }
1838
1839 return err
1840 }
1841
1842
1843 func (c *Command) Parent() *Command {
1844 return c.parent
1845 }
1846
1847
1848
1849 func (c *Command) mergePersistentFlags() {
1850 c.updateParentsPflags()
1851 c.Flags().AddFlagSet(c.PersistentFlags())
1852 c.Flags().AddFlagSet(c.parentsPflags)
1853 }
1854
1855
1856
1857
1858 func (c *Command) updateParentsPflags() {
1859 if c.parentsPflags == nil {
1860 c.parentsPflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
1861 c.parentsPflags.SetOutput(c.flagErrorBuf)
1862 c.parentsPflags.SortFlags = false
1863 }
1864
1865 if c.globNormFunc != nil {
1866 c.parentsPflags.SetNormalizeFunc(c.globNormFunc)
1867 }
1868
1869 c.Root().PersistentFlags().AddFlagSet(flag.CommandLine)
1870
1871 c.VisitParents(func(parent *Command) {
1872 c.parentsPflags.AddFlagSet(parent.PersistentFlags())
1873 })
1874 }
1875
1876
1877
1878
1879 func commandNameMatches(s string, t string) bool {
1880 if EnableCaseInsensitive {
1881 return strings.EqualFold(s, t)
1882 }
1883
1884 return s == t
1885 }
1886
View as plain text