blob: 34d1bf367129f246217a3806d658e693bb5810fd [file] [log] [blame]
sslobodrd046be82019-01-16 10:02:22 -05001// Copyright © 2013 Steve Francia <spf@spf13.com>.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14// Package cobra is a commander providing a simple interface to create powerful modern CLI interfaces.
15// In addition to providing an interface, Cobra simultaneously provides a controller to organize your application code.
16package cobra
17
18import (
19 "bytes"
20 "fmt"
21 "io"
22 "os"
23 "path/filepath"
24 "sort"
25 "strings"
26
27 flag "github.com/spf13/pflag"
28)
29
30// FParseErrWhitelist configures Flag parse errors to be ignored
31type FParseErrWhitelist flag.ParseErrorsWhitelist
32
33// Command is just that, a command for your application.
34// E.g. 'go run ...' - 'run' is the command. Cobra requires
35// you to define the usage and description as part of your command
36// definition to ensure usability.
37type Command struct {
38 // Use is the one-line usage message.
39 Use string
40
41 // Aliases is an array of aliases that can be used instead of the first word in Use.
42 Aliases []string
43
44 // SuggestFor is an array of command names for which this command will be suggested -
45 // similar to aliases but only suggests.
46 SuggestFor []string
47
48 // Short is the short description shown in the 'help' output.
49 Short string
50
51 // Long is the long message shown in the 'help <this-command>' output.
52 Long string
53
54 // Example is examples of how to use the command.
55 Example string
56
57 // ValidArgs is list of all valid non-flag arguments that are accepted in bash completions
58 ValidArgs []string
59
60 // Expected arguments
61 Args PositionalArgs
62
63 // ArgAliases is List of aliases for ValidArgs.
64 // These are not suggested to the user in the bash completion,
65 // but accepted if entered manually.
66 ArgAliases []string
67
68 // BashCompletionFunction is custom functions used by the bash autocompletion generator.
69 BashCompletionFunction string
70
71 // Deprecated defines, if this command is deprecated and should print this string when used.
72 Deprecated string
73
74 // Hidden defines, if this command is hidden and should NOT show up in the list of available commands.
75 Hidden bool
76
77 // Annotations are key/value pairs that can be used by applications to identify or
78 // group commands.
79 Annotations map[string]string
80
81 // Version defines the version for this command. If this value is non-empty and the command does not
82 // define a "version" flag, a "version" boolean flag will be added to the command and, if specified,
83 // will print content of the "Version" variable.
84 Version string
85
86 // The *Run functions are executed in the following order:
87 // * PersistentPreRun()
88 // * PreRun()
89 // * Run()
90 // * PostRun()
91 // * PersistentPostRun()
92 // All functions get the same args, the arguments after the command name.
93 //
94 // PersistentPreRun: children of this command will inherit and execute.
95 PersistentPreRun func(cmd *Command, args []string)
96 // PersistentPreRunE: PersistentPreRun but returns an error.
97 PersistentPreRunE func(cmd *Command, args []string) error
98 // PreRun: children of this command will not inherit.
99 PreRun func(cmd *Command, args []string)
100 // PreRunE: PreRun but returns an error.
101 PreRunE func(cmd *Command, args []string) error
102 // Run: Typically the actual work function. Most commands will only implement this.
103 Run func(cmd *Command, args []string)
104 // RunE: Run but returns an error.
105 RunE func(cmd *Command, args []string) error
106 // PostRun: run after the Run command.
107 PostRun func(cmd *Command, args []string)
108 // PostRunE: PostRun but returns an error.
109 PostRunE func(cmd *Command, args []string) error
110 // PersistentPostRun: children of this command will inherit and execute after PostRun.
111 PersistentPostRun func(cmd *Command, args []string)
112 // PersistentPostRunE: PersistentPostRun but returns an error.
113 PersistentPostRunE func(cmd *Command, args []string) error
114
115 // SilenceErrors is an option to quiet errors down stream.
116 SilenceErrors bool
117
118 // SilenceUsage is an option to silence usage when an error occurs.
119 SilenceUsage bool
120
121 // DisableFlagParsing disables the flag parsing.
122 // If this is true all flags will be passed to the command as arguments.
123 DisableFlagParsing bool
124
125 // DisableAutoGenTag defines, if gen tag ("Auto generated by spf13/cobra...")
126 // will be printed by generating docs for this command.
127 DisableAutoGenTag bool
128
129 // DisableFlagsInUseLine will disable the addition of [flags] to the usage
130 // line of a command when printing help or generating docs
131 DisableFlagsInUseLine bool
132
133 // DisableSuggestions disables the suggestions based on Levenshtein distance
134 // that go along with 'unknown command' messages.
135 DisableSuggestions bool
136 // SuggestionsMinimumDistance defines minimum levenshtein distance to display suggestions.
137 // Must be > 0.
138 SuggestionsMinimumDistance int
139
140 // TraverseChildren parses flags on all parents before executing child command.
141 TraverseChildren bool
142
143 //FParseErrWhitelist flag parse errors to be ignored
144 FParseErrWhitelist FParseErrWhitelist
145
146 // commands is the list of commands supported by this program.
147 commands []*Command
148 // parent is a parent command for this command.
149 parent *Command
150 // Max lengths of commands' string lengths for use in padding.
151 commandsMaxUseLen int
152 commandsMaxCommandPathLen int
153 commandsMaxNameLen int
154 // commandsAreSorted defines, if command slice are sorted or not.
155 commandsAreSorted bool
156 // commandCalledAs is the name or alias value used to call this command.
157 commandCalledAs struct {
158 name string
159 called bool
160 }
161
162 // args is actual args parsed from flags.
163 args []string
164 // flagErrorBuf contains all error messages from pflag.
165 flagErrorBuf *bytes.Buffer
166 // flags is full set of flags.
167 flags *flag.FlagSet
168 // pflags contains persistent flags.
169 pflags *flag.FlagSet
170 // lflags contains local flags.
171 lflags *flag.FlagSet
172 // iflags contains inherited flags.
173 iflags *flag.FlagSet
174 // parentsPflags is all persistent flags of cmd's parents.
175 parentsPflags *flag.FlagSet
176 // globNormFunc is the global normalization function
177 // that we can use on every pflag set and children commands
178 globNormFunc func(f *flag.FlagSet, name string) flag.NormalizedName
179
180 // output is an output writer defined by user.
181 output io.Writer
182 // usageFunc is usage func defined by user.
183 usageFunc func(*Command) error
184 // usageTemplate is usage template defined by user.
185 usageTemplate string
186 // flagErrorFunc is func defined by user and it's called when the parsing of
187 // flags returns an error.
188 flagErrorFunc func(*Command, error) error
189 // helpTemplate is help template defined by user.
190 helpTemplate string
191 // helpFunc is help func defined by user.
192 helpFunc func(*Command, []string)
193 // helpCommand is command with usage 'help'. If it's not defined by user,
194 // cobra uses default help command.
195 helpCommand *Command
196 // versionTemplate is the version template defined by user.
197 versionTemplate string
198}
199
200// SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden
201// particularly useful when testing.
202func (c *Command) SetArgs(a []string) {
203 c.args = a
204}
205
206// SetOutput sets the destination for usage and error messages.
207// If output is nil, os.Stderr is used.
208func (c *Command) SetOutput(output io.Writer) {
209 c.output = output
210}
211
212// SetUsageFunc sets usage function. Usage can be defined by application.
213func (c *Command) SetUsageFunc(f func(*Command) error) {
214 c.usageFunc = f
215}
216
217// SetUsageTemplate sets usage template. Can be defined by Application.
218func (c *Command) SetUsageTemplate(s string) {
219 c.usageTemplate = s
220}
221
222// SetFlagErrorFunc sets a function to generate an error when flag parsing
223// fails.
224func (c *Command) SetFlagErrorFunc(f func(*Command, error) error) {
225 c.flagErrorFunc = f
226}
227
228// SetHelpFunc sets help function. Can be defined by Application.
229func (c *Command) SetHelpFunc(f func(*Command, []string)) {
230 c.helpFunc = f
231}
232
233// SetHelpCommand sets help command.
234func (c *Command) SetHelpCommand(cmd *Command) {
235 c.helpCommand = cmd
236}
237
238// SetHelpTemplate sets help template to be used. Application can use it to set custom template.
239func (c *Command) SetHelpTemplate(s string) {
240 c.helpTemplate = s
241}
242
243// SetVersionTemplate sets version template to be used. Application can use it to set custom template.
244func (c *Command) SetVersionTemplate(s string) {
245 c.versionTemplate = s
246}
247
248// SetGlobalNormalizationFunc sets a normalization function to all flag sets and also to child commands.
249// The user should not have a cyclic dependency on commands.
250func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string) flag.NormalizedName) {
251 c.Flags().SetNormalizeFunc(n)
252 c.PersistentFlags().SetNormalizeFunc(n)
253 c.globNormFunc = n
254
255 for _, command := range c.commands {
256 command.SetGlobalNormalizationFunc(n)
257 }
258}
259
260// OutOrStdout returns output to stdout.
261func (c *Command) OutOrStdout() io.Writer {
262 return c.getOut(os.Stdout)
263}
264
265// OutOrStderr returns output to stderr
266func (c *Command) OutOrStderr() io.Writer {
267 return c.getOut(os.Stderr)
268}
269
270func (c *Command) getOut(def io.Writer) io.Writer {
271 if c.output != nil {
272 return c.output
273 }
274 if c.HasParent() {
275 return c.parent.getOut(def)
276 }
277 return def
278}
279
280// UsageFunc returns either the function set by SetUsageFunc for this command
281// or a parent, or it returns a default usage function.
282func (c *Command) UsageFunc() (f func(*Command) error) {
283 if c.usageFunc != nil {
284 return c.usageFunc
285 }
286 if c.HasParent() {
287 return c.Parent().UsageFunc()
288 }
289 return func(c *Command) error {
290 c.mergePersistentFlags()
291 err := tmpl(c.OutOrStderr(), c.UsageTemplate(), c)
292 if err != nil {
293 c.Println(err)
294 }
295 return err
296 }
297}
298
299// Usage puts out the usage for the command.
300// Used when a user provides invalid input.
301// Can be defined by user by overriding UsageFunc.
302func (c *Command) Usage() error {
303 return c.UsageFunc()(c)
304}
305
306// HelpFunc returns either the function set by SetHelpFunc for this command
307// or a parent, or it returns a function with default help behavior.
308func (c *Command) HelpFunc() func(*Command, []string) {
309 if c.helpFunc != nil {
310 return c.helpFunc
311 }
312 if c.HasParent() {
313 return c.Parent().HelpFunc()
314 }
315 return func(c *Command, a []string) {
316 c.mergePersistentFlags()
317 err := tmpl(c.OutOrStdout(), c.HelpTemplate(), c)
318 if err != nil {
319 c.Println(err)
320 }
321 }
322}
323
324// Help puts out the help for the command.
325// Used when a user calls help [command].
326// Can be defined by user by overriding HelpFunc.
327func (c *Command) Help() error {
328 c.HelpFunc()(c, []string{})
329 return nil
330}
331
332// UsageString return usage string.
333func (c *Command) UsageString() string {
334 tmpOutput := c.output
335 bb := new(bytes.Buffer)
336 c.SetOutput(bb)
337 c.Usage()
338 c.output = tmpOutput
339 return bb.String()
340}
341
342// FlagErrorFunc returns either the function set by SetFlagErrorFunc for this
343// command or a parent, or it returns a function which returns the original
344// error.
345func (c *Command) FlagErrorFunc() (f func(*Command, error) error) {
346 if c.flagErrorFunc != nil {
347 return c.flagErrorFunc
348 }
349
350 if c.HasParent() {
351 return c.parent.FlagErrorFunc()
352 }
353 return func(c *Command, err error) error {
354 return err
355 }
356}
357
358var minUsagePadding = 25
359
360// UsagePadding return padding for the usage.
361func (c *Command) UsagePadding() int {
362 if c.parent == nil || minUsagePadding > c.parent.commandsMaxUseLen {
363 return minUsagePadding
364 }
365 return c.parent.commandsMaxUseLen
366}
367
368var minCommandPathPadding = 11
369
370// CommandPathPadding return padding for the command path.
371func (c *Command) CommandPathPadding() int {
372 if c.parent == nil || minCommandPathPadding > c.parent.commandsMaxCommandPathLen {
373 return minCommandPathPadding
374 }
375 return c.parent.commandsMaxCommandPathLen
376}
377
378var minNamePadding = 11
379
380// NamePadding returns padding for the name.
381func (c *Command) NamePadding() int {
382 if c.parent == nil || minNamePadding > c.parent.commandsMaxNameLen {
383 return minNamePadding
384 }
385 return c.parent.commandsMaxNameLen
386}
387
388// UsageTemplate returns usage template for the command.
389func (c *Command) UsageTemplate() string {
390 if c.usageTemplate != "" {
391 return c.usageTemplate
392 }
393
394 if c.HasParent() {
395 return c.parent.UsageTemplate()
396 }
397 return `Usage:{{if .Runnable}}
398 {{.UseLine}}{{end}}{{if .HasAvailableSubCommands}}
399 {{.CommandPath}} [command]{{end}}{{if gt (len .Aliases) 0}}
400
401Aliases:
402 {{.NameAndAliases}}{{end}}{{if .HasExample}}
403
404Examples:
405{{.Example}}{{end}}{{if .HasAvailableSubCommands}}
406
407Available Commands:{{range .Commands}}{{if (or .IsAvailableCommand (eq .Name "help"))}}
408 {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}
409
410Flags:
411{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}}
412
413Global Flags:
414{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasHelpSubCommands}}
415
416Additional help topics:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}}
417 {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableSubCommands}}
418
419Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}}
420`
421}
422
423// HelpTemplate return help template for the command.
424func (c *Command) HelpTemplate() string {
425 if c.helpTemplate != "" {
426 return c.helpTemplate
427 }
428
429 if c.HasParent() {
430 return c.parent.HelpTemplate()
431 }
432 return `{{with (or .Long .Short)}}{{. | trimTrailingWhitespaces}}
433
434{{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`
435}
436
437// VersionTemplate return version template for the command.
438func (c *Command) VersionTemplate() string {
439 if c.versionTemplate != "" {
440 return c.versionTemplate
441 }
442
443 if c.HasParent() {
444 return c.parent.VersionTemplate()
445 }
446 return `{{with .Name}}{{printf "%s " .}}{{end}}{{printf "version %s" .Version}}
447`
448}
449
450func hasNoOptDefVal(name string, fs *flag.FlagSet) bool {
451 flag := fs.Lookup(name)
452 if flag == nil {
453 return false
454 }
455 return flag.NoOptDefVal != ""
456}
457
458func shortHasNoOptDefVal(name string, fs *flag.FlagSet) bool {
459 if len(name) == 0 {
460 return false
461 }
462
463 flag := fs.ShorthandLookup(name[:1])
464 if flag == nil {
465 return false
466 }
467 return flag.NoOptDefVal != ""
468}
469
470func stripFlags(args []string, c *Command) []string {
471 if len(args) == 0 {
472 return args
473 }
474 c.mergePersistentFlags()
475
476 commands := []string{}
477 flags := c.Flags()
478
479Loop:
480 for len(args) > 0 {
481 s := args[0]
482 args = args[1:]
483 switch {
484 case s == "--":
485 // "--" terminates the flags
486 break Loop
487 case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags):
488 // If '--flag arg' then
489 // delete arg from args.
490 fallthrough // (do the same as below)
491 case strings.HasPrefix(s, "-") && !strings.Contains(s, "=") && len(s) == 2 && !shortHasNoOptDefVal(s[1:], flags):
492 // If '-f arg' then
493 // delete 'arg' from args or break the loop if len(args) <= 1.
494 if len(args) <= 1 {
495 break Loop
496 } else {
497 args = args[1:]
498 continue
499 }
500 case s != "" && !strings.HasPrefix(s, "-"):
501 commands = append(commands, s)
502 }
503 }
504
505 return commands
506}
507
508// argsMinusFirstX removes only the first x from args. Otherwise, commands that look like
509// openshift admin policy add-role-to-user admin my-user, lose the admin argument (arg[4]).
510func argsMinusFirstX(args []string, x string) []string {
511 for i, y := range args {
512 if x == y {
513 ret := []string{}
514 ret = append(ret, args[:i]...)
515 ret = append(ret, args[i+1:]...)
516 return ret
517 }
518 }
519 return args
520}
521
522func isFlagArg(arg string) bool {
523 return ((len(arg) >= 3 && arg[1] == '-') ||
524 (len(arg) >= 2 && arg[0] == '-' && arg[1] != '-'))
525}
526
527// Find the target command given the args and command tree
528// Meant to be run on the highest node. Only searches down.
529func (c *Command) Find(args []string) (*Command, []string, error) {
530 var innerfind func(*Command, []string) (*Command, []string)
531
532 innerfind = func(c *Command, innerArgs []string) (*Command, []string) {
533 argsWOflags := stripFlags(innerArgs, c)
534 if len(argsWOflags) == 0 {
535 return c, innerArgs
536 }
537 nextSubCmd := argsWOflags[0]
538
539 cmd := c.findNext(nextSubCmd)
540 if cmd != nil {
541 return innerfind(cmd, argsMinusFirstX(innerArgs, nextSubCmd))
542 }
543 return c, innerArgs
544 }
545
546 commandFound, a := innerfind(c, args)
547 if commandFound.Args == nil {
548 return commandFound, a, legacyArgs(commandFound, stripFlags(a, commandFound))
549 }
550 return commandFound, a, nil
551}
552
553func (c *Command) findSuggestions(arg string) string {
554 if c.DisableSuggestions {
555 return ""
556 }
557 if c.SuggestionsMinimumDistance <= 0 {
558 c.SuggestionsMinimumDistance = 2
559 }
560 suggestionsString := ""
561 if suggestions := c.SuggestionsFor(arg); len(suggestions) > 0 {
562 suggestionsString += "\n\nDid you mean this?\n"
563 for _, s := range suggestions {
564 suggestionsString += fmt.Sprintf("\t%v\n", s)
565 }
566 }
567 return suggestionsString
568}
569
570func (c *Command) findNext(next string) *Command {
571 matches := make([]*Command, 0)
572 for _, cmd := range c.commands {
573 if cmd.Name() == next || cmd.HasAlias(next) {
574 cmd.commandCalledAs.name = next
575 return cmd
576 }
577 if EnablePrefixMatching && cmd.hasNameOrAliasPrefix(next) {
578 matches = append(matches, cmd)
579 }
580 }
581
582 if len(matches) == 1 {
583 return matches[0]
584 }
585
586 return nil
587}
588
589// Traverse the command tree to find the command, and parse args for
590// each parent.
591func (c *Command) Traverse(args []string) (*Command, []string, error) {
592 flags := []string{}
593 inFlag := false
594
595 for i, arg := range args {
596 switch {
597 // A long flag with a space separated value
598 case strings.HasPrefix(arg, "--") && !strings.Contains(arg, "="):
599 // TODO: this isn't quite right, we should really check ahead for 'true' or 'false'
600 inFlag = !hasNoOptDefVal(arg[2:], c.Flags())
601 flags = append(flags, arg)
602 continue
603 // A short flag with a space separated value
604 case strings.HasPrefix(arg, "-") && !strings.Contains(arg, "=") && len(arg) == 2 && !shortHasNoOptDefVal(arg[1:], c.Flags()):
605 inFlag = true
606 flags = append(flags, arg)
607 continue
608 // The value for a flag
609 case inFlag:
610 inFlag = false
611 flags = append(flags, arg)
612 continue
613 // A flag without a value, or with an `=` separated value
614 case isFlagArg(arg):
615 flags = append(flags, arg)
616 continue
617 }
618
619 cmd := c.findNext(arg)
620 if cmd == nil {
621 return c, args, nil
622 }
623
624 if err := c.ParseFlags(flags); err != nil {
625 return nil, args, err
626 }
627 return cmd.Traverse(args[i+1:])
628 }
629 return c, args, nil
630}
631
632// SuggestionsFor provides suggestions for the typedName.
633func (c *Command) SuggestionsFor(typedName string) []string {
634 suggestions := []string{}
635 for _, cmd := range c.commands {
636 if cmd.IsAvailableCommand() {
637 levenshteinDistance := ld(typedName, cmd.Name(), true)
638 suggestByLevenshtein := levenshteinDistance <= c.SuggestionsMinimumDistance
639 suggestByPrefix := strings.HasPrefix(strings.ToLower(cmd.Name()), strings.ToLower(typedName))
640 if suggestByLevenshtein || suggestByPrefix {
641 suggestions = append(suggestions, cmd.Name())
642 }
643 for _, explicitSuggestion := range cmd.SuggestFor {
644 if strings.EqualFold(typedName, explicitSuggestion) {
645 suggestions = append(suggestions, cmd.Name())
646 }
647 }
648 }
649 }
650 return suggestions
651}
652
653// VisitParents visits all parents of the command and invokes fn on each parent.
654func (c *Command) VisitParents(fn func(*Command)) {
655 if c.HasParent() {
656 fn(c.Parent())
657 c.Parent().VisitParents(fn)
658 }
659}
660
661// Root finds root command.
662func (c *Command) Root() *Command {
663 if c.HasParent() {
664 return c.Parent().Root()
665 }
666 return c
667}
668
669// ArgsLenAtDash will return the length of c.Flags().Args at the moment
670// when a -- was found during args parsing.
671func (c *Command) ArgsLenAtDash() int {
672 return c.Flags().ArgsLenAtDash()
673}
674
675func (c *Command) execute(a []string) (err error) {
676 if c == nil {
677 return fmt.Errorf("Called Execute() on a nil Command")
678 }
679
680 if len(c.Deprecated) > 0 {
681 c.Printf("Command %q is deprecated, %s\n", c.Name(), c.Deprecated)
682 }
683
684 // initialize help and version flag at the last point possible to allow for user
685 // overriding
686 c.InitDefaultHelpFlag()
687 c.InitDefaultVersionFlag()
688
689 err = c.ParseFlags(a)
690 if err != nil {
691 return c.FlagErrorFunc()(c, err)
692 }
693
694 // If help is called, regardless of other flags, return we want help.
695 // Also say we need help if the command isn't runnable.
696 helpVal, err := c.Flags().GetBool("help")
697 if err != nil {
698 // should be impossible to get here as we always declare a help
699 // flag in InitDefaultHelpFlag()
700 c.Println("\"help\" flag declared as non-bool. Please correct your code")
701 return err
702 }
703
704 if helpVal {
705 return flag.ErrHelp
706 }
707
708 // for back-compat, only add version flag behavior if version is defined
709 if c.Version != "" {
710 versionVal, err := c.Flags().GetBool("version")
711 if err != nil {
712 c.Println("\"version\" flag declared as non-bool. Please correct your code")
713 return err
714 }
715 if versionVal {
716 err := tmpl(c.OutOrStdout(), c.VersionTemplate(), c)
717 if err != nil {
718 c.Println(err)
719 }
720 return err
721 }
722 }
723
724 if !c.Runnable() {
725 return flag.ErrHelp
726 }
727
728 c.preRun()
729
730 argWoFlags := c.Flags().Args()
731 if c.DisableFlagParsing {
732 argWoFlags = a
733 }
734
735 if err := c.ValidateArgs(argWoFlags); err != nil {
736 return err
737 }
738
739 for p := c; p != nil; p = p.Parent() {
740 if p.PersistentPreRunE != nil {
741 if err := p.PersistentPreRunE(c, argWoFlags); err != nil {
742 return err
743 }
744 break
745 } else if p.PersistentPreRun != nil {
746 p.PersistentPreRun(c, argWoFlags)
747 break
748 }
749 }
750 if c.PreRunE != nil {
751 if err := c.PreRunE(c, argWoFlags); err != nil {
752 return err
753 }
754 } else if c.PreRun != nil {
755 c.PreRun(c, argWoFlags)
756 }
757
758 if err := c.validateRequiredFlags(); err != nil {
759 return err
760 }
761 if c.RunE != nil {
762 if err := c.RunE(c, argWoFlags); err != nil {
763 return err
764 }
765 } else {
766 c.Run(c, argWoFlags)
767 }
768 if c.PostRunE != nil {
769 if err := c.PostRunE(c, argWoFlags); err != nil {
770 return err
771 }
772 } else if c.PostRun != nil {
773 c.PostRun(c, argWoFlags)
774 }
775 for p := c; p != nil; p = p.Parent() {
776 if p.PersistentPostRunE != nil {
777 if err := p.PersistentPostRunE(c, argWoFlags); err != nil {
778 return err
779 }
780 break
781 } else if p.PersistentPostRun != nil {
782 p.PersistentPostRun(c, argWoFlags)
783 break
784 }
785 }
786
787 return nil
788}
789
790func (c *Command) preRun() {
791 for _, x := range initializers {
792 x()
793 }
794}
795
796// Execute uses the args (os.Args[1:] by default)
797// and run through the command tree finding appropriate matches
798// for commands and then corresponding flags.
799func (c *Command) Execute() error {
800 _, err := c.ExecuteC()
801 return err
802}
803
804// ExecuteC executes the command.
805func (c *Command) ExecuteC() (cmd *Command, err error) {
806 // Regardless of what command execute is called on, run on Root only
807 if c.HasParent() {
808 return c.Root().ExecuteC()
809 }
810
811 // windows hook
812 if preExecHookFn != nil {
813 preExecHookFn(c)
814 }
815
816 // initialize help as the last point possible to allow for user
817 // overriding
818 c.InitDefaultHelpCmd()
819
820 var args []string
821
822 // Workaround FAIL with "go test -v" or "cobra.test -test.v", see #155
823 if c.args == nil && filepath.Base(os.Args[0]) != "cobra.test" {
824 args = os.Args[1:]
825 } else {
826 args = c.args
827 }
828
829 var flags []string
830 if c.TraverseChildren {
831 cmd, flags, err = c.Traverse(args)
832 } else {
833 cmd, flags, err = c.Find(args)
834 }
835 if err != nil {
836 // If found parse to a subcommand and then failed, talk about the subcommand
837 if cmd != nil {
838 c = cmd
839 }
840 if !c.SilenceErrors {
841 c.Println("Error:", err.Error())
842 c.Printf("Run '%v --help' for usage.\n", c.CommandPath())
843 }
844 return c, err
845 }
846
847 cmd.commandCalledAs.called = true
848 if cmd.commandCalledAs.name == "" {
849 cmd.commandCalledAs.name = cmd.Name()
850 }
851
852 err = cmd.execute(flags)
853 if err != nil {
854 // Always show help if requested, even if SilenceErrors is in
855 // effect
856 if err == flag.ErrHelp {
857 cmd.HelpFunc()(cmd, args)
858 return cmd, nil
859 }
860
861 // If root command has SilentErrors flagged,
862 // all subcommands should respect it
863 if !cmd.SilenceErrors && !c.SilenceErrors {
864 c.Println("Error:", err.Error())
865 }
866
867 // If root command has SilentUsage flagged,
868 // all subcommands should respect it
869 if !cmd.SilenceUsage && !c.SilenceUsage {
870 c.Println(cmd.UsageString())
871 }
872 }
873 return cmd, err
874}
875
876func (c *Command) ValidateArgs(args []string) error {
877 if c.Args == nil {
878 return nil
879 }
880 return c.Args(c, args)
881}
882
883func (c *Command) validateRequiredFlags() error {
884 flags := c.Flags()
885 missingFlagNames := []string{}
886 flags.VisitAll(func(pflag *flag.Flag) {
887 requiredAnnotation, found := pflag.Annotations[BashCompOneRequiredFlag]
888 if !found {
889 return
890 }
891 if (requiredAnnotation[0] == "true") && !pflag.Changed {
892 missingFlagNames = append(missingFlagNames, pflag.Name)
893 }
894 })
895
896 if len(missingFlagNames) > 0 {
897 return fmt.Errorf(`required flag(s) "%s" not set`, strings.Join(missingFlagNames, `", "`))
898 }
899 return nil
900}
901
902// InitDefaultHelpFlag adds default help flag to c.
903// It is called automatically by executing the c or by calling help and usage.
904// If c already has help flag, it will do nothing.
905func (c *Command) InitDefaultHelpFlag() {
906 c.mergePersistentFlags()
907 if c.Flags().Lookup("help") == nil {
908 usage := "help for "
909 if c.Name() == "" {
910 usage += "this command"
911 } else {
912 usage += c.Name()
913 }
914 c.Flags().BoolP("help", "h", false, usage)
915 }
916}
917
918// InitDefaultVersionFlag adds default version flag to c.
919// It is called automatically by executing the c.
920// If c already has a version flag, it will do nothing.
921// If c.Version is empty, it will do nothing.
922func (c *Command) InitDefaultVersionFlag() {
923 if c.Version == "" {
924 return
925 }
926
927 c.mergePersistentFlags()
928 if c.Flags().Lookup("version") == nil {
929 usage := "version for "
930 if c.Name() == "" {
931 usage += "this command"
932 } else {
933 usage += c.Name()
934 }
935 c.Flags().Bool("version", false, usage)
936 }
937}
938
939// InitDefaultHelpCmd adds default help command to c.
940// It is called automatically by executing the c or by calling help and usage.
941// If c already has help command or c has no subcommands, it will do nothing.
942func (c *Command) InitDefaultHelpCmd() {
943 if !c.HasSubCommands() {
944 return
945 }
946
947 if c.helpCommand == nil {
948 c.helpCommand = &Command{
949 Use: "help [command]",
950 Short: "Help about any command",
951 Long: `Help provides help for any command in the application.
952Simply type ` + c.Name() + ` help [path to command] for full details.`,
953
954 Run: func(c *Command, args []string) {
955 cmd, _, e := c.Root().Find(args)
956 if cmd == nil || e != nil {
957 c.Printf("Unknown help topic %#q\n", args)
958 c.Root().Usage()
959 } else {
960 cmd.InitDefaultHelpFlag() // make possible 'help' flag to be shown
961 cmd.Help()
962 }
963 },
964 }
965 }
966 c.RemoveCommand(c.helpCommand)
967 c.AddCommand(c.helpCommand)
968}
969
970// ResetCommands delete parent, subcommand and help command from c.
971func (c *Command) ResetCommands() {
972 c.parent = nil
973 c.commands = nil
974 c.helpCommand = nil
975 c.parentsPflags = nil
976}
977
978// Sorts commands by their names.
979type commandSorterByName []*Command
980
981func (c commandSorterByName) Len() int { return len(c) }
982func (c commandSorterByName) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
983func (c commandSorterByName) Less(i, j int) bool { return c[i].Name() < c[j].Name() }
984
985// Commands returns a sorted slice of child commands.
986func (c *Command) Commands() []*Command {
987 // do not sort commands if it already sorted or sorting was disabled
988 if EnableCommandSorting && !c.commandsAreSorted {
989 sort.Sort(commandSorterByName(c.commands))
990 c.commandsAreSorted = true
991 }
992 return c.commands
993}
994
995// AddCommand adds one or more commands to this parent command.
996func (c *Command) AddCommand(cmds ...*Command) {
997 for i, x := range cmds {
998 if cmds[i] == c {
999 panic("Command can't be a child of itself")
1000 }
1001 cmds[i].parent = c
1002 // update max lengths
1003 usageLen := len(x.Use)
1004 if usageLen > c.commandsMaxUseLen {
1005 c.commandsMaxUseLen = usageLen
1006 }
1007 commandPathLen := len(x.CommandPath())
1008 if commandPathLen > c.commandsMaxCommandPathLen {
1009 c.commandsMaxCommandPathLen = commandPathLen
1010 }
1011 nameLen := len(x.Name())
1012 if nameLen > c.commandsMaxNameLen {
1013 c.commandsMaxNameLen = nameLen
1014 }
1015 // If global normalization function exists, update all children
1016 if c.globNormFunc != nil {
1017 x.SetGlobalNormalizationFunc(c.globNormFunc)
1018 }
1019 c.commands = append(c.commands, x)
1020 c.commandsAreSorted = false
1021 }
1022}
1023
1024// RemoveCommand removes one or more commands from a parent command.
1025func (c *Command) RemoveCommand(cmds ...*Command) {
1026 commands := []*Command{}
1027main:
1028 for _, command := range c.commands {
1029 for _, cmd := range cmds {
1030 if command == cmd {
1031 command.parent = nil
1032 continue main
1033 }
1034 }
1035 commands = append(commands, command)
1036 }
1037 c.commands = commands
1038 // recompute all lengths
1039 c.commandsMaxUseLen = 0
1040 c.commandsMaxCommandPathLen = 0
1041 c.commandsMaxNameLen = 0
1042 for _, command := range c.commands {
1043 usageLen := len(command.Use)
1044 if usageLen > c.commandsMaxUseLen {
1045 c.commandsMaxUseLen = usageLen
1046 }
1047 commandPathLen := len(command.CommandPath())
1048 if commandPathLen > c.commandsMaxCommandPathLen {
1049 c.commandsMaxCommandPathLen = commandPathLen
1050 }
1051 nameLen := len(command.Name())
1052 if nameLen > c.commandsMaxNameLen {
1053 c.commandsMaxNameLen = nameLen
1054 }
1055 }
1056}
1057
1058// Print is a convenience method to Print to the defined output, fallback to Stderr if not set.
1059func (c *Command) Print(i ...interface{}) {
1060 fmt.Fprint(c.OutOrStderr(), i...)
1061}
1062
1063// Println is a convenience method to Println to the defined output, fallback to Stderr if not set.
1064func (c *Command) Println(i ...interface{}) {
1065 c.Print(fmt.Sprintln(i...))
1066}
1067
1068// Printf is a convenience method to Printf to the defined output, fallback to Stderr if not set.
1069func (c *Command) Printf(format string, i ...interface{}) {
1070 c.Print(fmt.Sprintf(format, i...))
1071}
1072
1073// CommandPath returns the full path to this command.
1074func (c *Command) CommandPath() string {
1075 if c.HasParent() {
1076 return c.Parent().CommandPath() + " " + c.Name()
1077 }
1078 return c.Name()
1079}
1080
1081// UseLine puts out the full usage for a given command (including parents).
1082func (c *Command) UseLine() string {
1083 var useline string
1084 if c.HasParent() {
1085 useline = c.parent.CommandPath() + " " + c.Use
1086 } else {
1087 useline = c.Use
1088 }
1089 if c.DisableFlagsInUseLine {
1090 return useline
1091 }
1092 if c.HasAvailableFlags() && !strings.Contains(useline, "[flags]") {
1093 useline += " [flags]"
1094 }
1095 return useline
1096}
1097
1098// DebugFlags used to determine which flags have been assigned to which commands
1099// and which persist.
1100func (c *Command) DebugFlags() {
1101 c.Println("DebugFlags called on", c.Name())
1102 var debugflags func(*Command)
1103
1104 debugflags = func(x *Command) {
1105 if x.HasFlags() || x.HasPersistentFlags() {
1106 c.Println(x.Name())
1107 }
1108 if x.HasFlags() {
1109 x.flags.VisitAll(func(f *flag.Flag) {
1110 if x.HasPersistentFlags() && x.persistentFlag(f.Name) != nil {
1111 c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [LP]")
1112 } else {
1113 c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [L]")
1114 }
1115 })
1116 }
1117 if x.HasPersistentFlags() {
1118 x.pflags.VisitAll(func(f *flag.Flag) {
1119 if x.HasFlags() {
1120 if x.flags.Lookup(f.Name) == nil {
1121 c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [P]")
1122 }
1123 } else {
1124 c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [P]")
1125 }
1126 })
1127 }
1128 c.Println(x.flagErrorBuf)
1129 if x.HasSubCommands() {
1130 for _, y := range x.commands {
1131 debugflags(y)
1132 }
1133 }
1134 }
1135
1136 debugflags(c)
1137}
1138
1139// Name returns the command's name: the first word in the use line.
1140func (c *Command) Name() string {
1141 name := c.Use
1142 i := strings.Index(name, " ")
1143 if i >= 0 {
1144 name = name[:i]
1145 }
1146 return name
1147}
1148
1149// HasAlias determines if a given string is an alias of the command.
1150func (c *Command) HasAlias(s string) bool {
1151 for _, a := range c.Aliases {
1152 if a == s {
1153 return true
1154 }
1155 }
1156 return false
1157}
1158
1159// CalledAs returns the command name or alias that was used to invoke
1160// this command or an empty string if the command has not been called.
1161func (c *Command) CalledAs() string {
1162 if c.commandCalledAs.called {
1163 return c.commandCalledAs.name
1164 }
1165 return ""
1166}
1167
1168// hasNameOrAliasPrefix returns true if the Name or any of aliases start
1169// with prefix
1170func (c *Command) hasNameOrAliasPrefix(prefix string) bool {
1171 if strings.HasPrefix(c.Name(), prefix) {
1172 c.commandCalledAs.name = c.Name()
1173 return true
1174 }
1175 for _, alias := range c.Aliases {
1176 if strings.HasPrefix(alias, prefix) {
1177 c.commandCalledAs.name = alias
1178 return true
1179 }
1180 }
1181 return false
1182}
1183
1184// NameAndAliases returns a list of the command name and all aliases
1185func (c *Command) NameAndAliases() string {
1186 return strings.Join(append([]string{c.Name()}, c.Aliases...), ", ")
1187}
1188
1189// HasExample determines if the command has example.
1190func (c *Command) HasExample() bool {
1191 return len(c.Example) > 0
1192}
1193
1194// Runnable determines if the command is itself runnable.
1195func (c *Command) Runnable() bool {
1196 return c.Run != nil || c.RunE != nil
1197}
1198
1199// HasSubCommands determines if the command has children commands.
1200func (c *Command) HasSubCommands() bool {
1201 return len(c.commands) > 0
1202}
1203
1204// IsAvailableCommand determines if a command is available as a non-help command
1205// (this includes all non deprecated/hidden commands).
1206func (c *Command) IsAvailableCommand() bool {
1207 if len(c.Deprecated) != 0 || c.Hidden {
1208 return false
1209 }
1210
1211 if c.HasParent() && c.Parent().helpCommand == c {
1212 return false
1213 }
1214
1215 if c.Runnable() || c.HasAvailableSubCommands() {
1216 return true
1217 }
1218
1219 return false
1220}
1221
1222// IsAdditionalHelpTopicCommand determines if a command is an additional
1223// help topic command; additional help topic command is determined by the
1224// fact that it is NOT runnable/hidden/deprecated, and has no sub commands that
1225// are runnable/hidden/deprecated.
1226// Concrete example: https://github.com/spf13/cobra/issues/393#issuecomment-282741924.
1227func (c *Command) IsAdditionalHelpTopicCommand() bool {
1228 // if a command is runnable, deprecated, or hidden it is not a 'help' command
1229 if c.Runnable() || len(c.Deprecated) != 0 || c.Hidden {
1230 return false
1231 }
1232
1233 // if any non-help sub commands are found, the command is not a 'help' command
1234 for _, sub := range c.commands {
1235 if !sub.IsAdditionalHelpTopicCommand() {
1236 return false
1237 }
1238 }
1239
1240 // the command either has no sub commands, or no non-help sub commands
1241 return true
1242}
1243
1244// HasHelpSubCommands determines if a command has any available 'help' sub commands
1245// that need to be shown in the usage/help default template under 'additional help
1246// topics'.
1247func (c *Command) HasHelpSubCommands() bool {
1248 // return true on the first found available 'help' sub command
1249 for _, sub := range c.commands {
1250 if sub.IsAdditionalHelpTopicCommand() {
1251 return true
1252 }
1253 }
1254
1255 // the command either has no sub commands, or no available 'help' sub commands
1256 return false
1257}
1258
1259// HasAvailableSubCommands determines if a command has available sub commands that
1260// need to be shown in the usage/help default template under 'available commands'.
1261func (c *Command) HasAvailableSubCommands() bool {
1262 // return true on the first found available (non deprecated/help/hidden)
1263 // sub command
1264 for _, sub := range c.commands {
1265 if sub.IsAvailableCommand() {
1266 return true
1267 }
1268 }
1269
1270 // the command either has no sub commands, or no available (non deprecated/help/hidden)
1271 // sub commands
1272 return false
1273}
1274
1275// HasParent determines if the command is a child command.
1276func (c *Command) HasParent() bool {
1277 return c.parent != nil
1278}
1279
1280// GlobalNormalizationFunc returns the global normalization function or nil if it doesn't exist.
1281func (c *Command) GlobalNormalizationFunc() func(f *flag.FlagSet, name string) flag.NormalizedName {
1282 return c.globNormFunc
1283}
1284
1285// Flags returns the complete FlagSet that applies
1286// to this command (local and persistent declared here and by all parents).
1287func (c *Command) Flags() *flag.FlagSet {
1288 if c.flags == nil {
1289 c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
1290 if c.flagErrorBuf == nil {
1291 c.flagErrorBuf = new(bytes.Buffer)
1292 }
1293 c.flags.SetOutput(c.flagErrorBuf)
1294 }
1295
1296 return c.flags
1297}
1298
1299// LocalNonPersistentFlags are flags specific to this command which will NOT persist to subcommands.
1300func (c *Command) LocalNonPersistentFlags() *flag.FlagSet {
1301 persistentFlags := c.PersistentFlags()
1302
1303 out := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
1304 c.LocalFlags().VisitAll(func(f *flag.Flag) {
1305 if persistentFlags.Lookup(f.Name) == nil {
1306 out.AddFlag(f)
1307 }
1308 })
1309 return out
1310}
1311
1312// LocalFlags returns the local FlagSet specifically set in the current command.
1313func (c *Command) LocalFlags() *flag.FlagSet {
1314 c.mergePersistentFlags()
1315
1316 if c.lflags == nil {
1317 c.lflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
1318 if c.flagErrorBuf == nil {
1319 c.flagErrorBuf = new(bytes.Buffer)
1320 }
1321 c.lflags.SetOutput(c.flagErrorBuf)
1322 }
1323 c.lflags.SortFlags = c.Flags().SortFlags
1324 if c.globNormFunc != nil {
1325 c.lflags.SetNormalizeFunc(c.globNormFunc)
1326 }
1327
1328 addToLocal := func(f *flag.Flag) {
1329 if c.lflags.Lookup(f.Name) == nil && c.parentsPflags.Lookup(f.Name) == nil {
1330 c.lflags.AddFlag(f)
1331 }
1332 }
1333 c.Flags().VisitAll(addToLocal)
1334 c.PersistentFlags().VisitAll(addToLocal)
1335 return c.lflags
1336}
1337
1338// InheritedFlags returns all flags which were inherited from parents commands.
1339func (c *Command) InheritedFlags() *flag.FlagSet {
1340 c.mergePersistentFlags()
1341
1342 if c.iflags == nil {
1343 c.iflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
1344 if c.flagErrorBuf == nil {
1345 c.flagErrorBuf = new(bytes.Buffer)
1346 }
1347 c.iflags.SetOutput(c.flagErrorBuf)
1348 }
1349
1350 local := c.LocalFlags()
1351 if c.globNormFunc != nil {
1352 c.iflags.SetNormalizeFunc(c.globNormFunc)
1353 }
1354
1355 c.parentsPflags.VisitAll(func(f *flag.Flag) {
1356 if c.iflags.Lookup(f.Name) == nil && local.Lookup(f.Name) == nil {
1357 c.iflags.AddFlag(f)
1358 }
1359 })
1360 return c.iflags
1361}
1362
1363// NonInheritedFlags returns all flags which were not inherited from parent commands.
1364func (c *Command) NonInheritedFlags() *flag.FlagSet {
1365 return c.LocalFlags()
1366}
1367
1368// PersistentFlags returns the persistent FlagSet specifically set in the current command.
1369func (c *Command) PersistentFlags() *flag.FlagSet {
1370 if c.pflags == nil {
1371 c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
1372 if c.flagErrorBuf == nil {
1373 c.flagErrorBuf = new(bytes.Buffer)
1374 }
1375 c.pflags.SetOutput(c.flagErrorBuf)
1376 }
1377 return c.pflags
1378}
1379
1380// ResetFlags deletes all flags from command.
1381func (c *Command) ResetFlags() {
1382 c.flagErrorBuf = new(bytes.Buffer)
1383 c.flagErrorBuf.Reset()
1384 c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
1385 c.flags.SetOutput(c.flagErrorBuf)
1386 c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
1387 c.pflags.SetOutput(c.flagErrorBuf)
1388
1389 c.lflags = nil
1390 c.iflags = nil
1391 c.parentsPflags = nil
1392}
1393
1394// HasFlags checks if the command contains any flags (local plus persistent from the entire structure).
1395func (c *Command) HasFlags() bool {
1396 return c.Flags().HasFlags()
1397}
1398
1399// HasPersistentFlags checks if the command contains persistent flags.
1400func (c *Command) HasPersistentFlags() bool {
1401 return c.PersistentFlags().HasFlags()
1402}
1403
1404// HasLocalFlags checks if the command has flags specifically declared locally.
1405func (c *Command) HasLocalFlags() bool {
1406 return c.LocalFlags().HasFlags()
1407}
1408
1409// HasInheritedFlags checks if the command has flags inherited from its parent command.
1410func (c *Command) HasInheritedFlags() bool {
1411 return c.InheritedFlags().HasFlags()
1412}
1413
1414// HasAvailableFlags checks if the command contains any flags (local plus persistent from the entire
1415// structure) which are not hidden or deprecated.
1416func (c *Command) HasAvailableFlags() bool {
1417 return c.Flags().HasAvailableFlags()
1418}
1419
1420// HasAvailablePersistentFlags checks if the command contains persistent flags which are not hidden or deprecated.
1421func (c *Command) HasAvailablePersistentFlags() bool {
1422 return c.PersistentFlags().HasAvailableFlags()
1423}
1424
1425// HasAvailableLocalFlags checks if the command has flags specifically declared locally which are not hidden
1426// or deprecated.
1427func (c *Command) HasAvailableLocalFlags() bool {
1428 return c.LocalFlags().HasAvailableFlags()
1429}
1430
1431// HasAvailableInheritedFlags checks if the command has flags inherited from its parent command which are
1432// not hidden or deprecated.
1433func (c *Command) HasAvailableInheritedFlags() bool {
1434 return c.InheritedFlags().HasAvailableFlags()
1435}
1436
1437// Flag climbs up the command tree looking for matching flag.
1438func (c *Command) Flag(name string) (flag *flag.Flag) {
1439 flag = c.Flags().Lookup(name)
1440
1441 if flag == nil {
1442 flag = c.persistentFlag(name)
1443 }
1444
1445 return
1446}
1447
1448// Recursively find matching persistent flag.
1449func (c *Command) persistentFlag(name string) (flag *flag.Flag) {
1450 if c.HasPersistentFlags() {
1451 flag = c.PersistentFlags().Lookup(name)
1452 }
1453
1454 if flag == nil {
1455 c.updateParentsPflags()
1456 flag = c.parentsPflags.Lookup(name)
1457 }
1458 return
1459}
1460
1461// ParseFlags parses persistent flag tree and local flags.
1462func (c *Command) ParseFlags(args []string) error {
1463 if c.DisableFlagParsing {
1464 return nil
1465 }
1466
1467 if c.flagErrorBuf == nil {
1468 c.flagErrorBuf = new(bytes.Buffer)
1469 }
1470 beforeErrorBufLen := c.flagErrorBuf.Len()
1471 c.mergePersistentFlags()
1472
1473 //do it here after merging all flags and just before parse
1474 c.Flags().ParseErrorsWhitelist = flag.ParseErrorsWhitelist(c.FParseErrWhitelist)
1475
1476 err := c.Flags().Parse(args)
1477 // Print warnings if they occurred (e.g. deprecated flag messages).
1478 if c.flagErrorBuf.Len()-beforeErrorBufLen > 0 && err == nil {
1479 c.Print(c.flagErrorBuf.String())
1480 }
1481
1482 return err
1483}
1484
1485// Parent returns a commands parent command.
1486func (c *Command) Parent() *Command {
1487 return c.parent
1488}
1489
1490// mergePersistentFlags merges c.PersistentFlags() to c.Flags()
1491// and adds missing persistent flags of all parents.
1492func (c *Command) mergePersistentFlags() {
1493 c.updateParentsPflags()
1494 c.Flags().AddFlagSet(c.PersistentFlags())
1495 c.Flags().AddFlagSet(c.parentsPflags)
1496}
1497
1498// updateParentsPflags updates c.parentsPflags by adding
1499// new persistent flags of all parents.
1500// If c.parentsPflags == nil, it makes new.
1501func (c *Command) updateParentsPflags() {
1502 if c.parentsPflags == nil {
1503 c.parentsPflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
1504 c.parentsPflags.SetOutput(c.flagErrorBuf)
1505 c.parentsPflags.SortFlags = false
1506 }
1507
1508 if c.globNormFunc != nil {
1509 c.parentsPflags.SetNormalizeFunc(c.globNormFunc)
1510 }
1511
1512 c.Root().PersistentFlags().AddFlagSet(flag.CommandLine)
1513
1514 c.VisitParents(func(parent *Command) {
1515 c.parentsPflags.AddFlagSet(parent.PersistentFlags())
1516 })
1517}