@@ -21,6 +21,7 @@ import (
21
21
"reflect"
22
22
"time"
23
23
24
+ "github.com/sirupsen/logrus"
24
25
"github.com/spf13/cobra"
25
26
"github.com/spf13/pflag"
26
27
@@ -517,8 +518,16 @@ func (fl *Flag) flag(cmdName string) *pflag.Flag {
517
518
if methodName == "" {
518
519
methodName = methodNameByType (reflect .ValueOf (fl .Value ))
519
520
}
521
+ isVar := methodName == "Var"
522
+ // pflags' Var*() methods do not take a default value but instead
523
+ // assume the value is already set to its default value. So we
524
+ // explicitly set the default value here to ensure help text is correct.
525
+ if isVar {
526
+ setDefaultValues (fl .Value , fl , cmdName )
527
+ }
528
+
520
529
inputs := []interface {}{fl .Value , fl .Name }
521
- if methodName != "Var" {
530
+ if ! isVar {
522
531
if d , found := fl .DefValuePerCommand [cmdName ]; found {
523
532
inputs = append (inputs , d )
524
533
} else {
@@ -528,8 +537,8 @@ func (fl *Flag) flag(cmdName string) *pflag.Flag {
528
537
inputs = append (inputs , fl .Usage )
529
538
530
539
fs := pflag .NewFlagSet (fl .Name , pflag .ContinueOnError )
531
-
532
540
reflect .ValueOf (fs ).MethodByName (methodName ).Call (reflectValueOf (inputs ))
541
+
533
542
f := fs .Lookup (fl .Name )
534
543
if len (fl .NoOptDefVal ) > 0 {
535
544
// f.NoOptDefVal may be set depending on value type
@@ -540,37 +549,35 @@ func (fl *Flag) flag(cmdName string) *pflag.Flag {
540
549
return f
541
550
}
542
551
543
- func reflectValueOf (values []interface {}) []reflect.Value {
544
- var results []reflect.Value
545
- for _ , v := range values {
546
- results = append (results , reflect .ValueOf (v ))
547
- }
548
- return results
549
- }
550
-
551
552
func ResetFlagDefaults (cmd * cobra.Command , flags []* Flag ) {
552
553
// Update default values.
553
554
for _ , fl := range flags {
554
555
flag := cmd .Flag (fl .Name )
555
556
if ! flag .Changed {
556
- defValue := fl .DefValue
557
- if fl .DefValuePerCommand != nil {
558
- if d , present := fl .DefValuePerCommand [cmd .Use ]; present {
559
- defValue = d
560
- }
561
- }
562
- if sv , ok := flag .Value .(pflag.SliceValue ); ok {
563
- reflect .ValueOf (sv ).MethodByName ("Replace" ).Call (reflectValueOf ([]interface {}{defValue }))
564
- } else {
565
- flag .Value .Set (fmt .Sprintf ("%v" , defValue ))
566
- }
557
+ setDefaultValues (flag .Value , fl , cmd .Name ())
567
558
}
568
559
if fl .IsEnum {
569
560
instrumentation .AddFlag (flag )
570
561
}
571
562
}
572
563
}
573
564
565
+ // setDefaultValues sets the default value (or values) for the given flag definition.
566
+ // This function handles pflag's SliceValue and Value interfaces.
567
+ func setDefaultValues (v interface {}, fl * Flag , cmdName string ) {
568
+ d , found := fl .DefValuePerCommand [cmdName ]
569
+ if ! found {
570
+ d = fl .DefValue
571
+ }
572
+ if sv , ok := v .(pflag.SliceValue ); ok {
573
+ sv .Replace (asStringSlice (d ))
574
+ } else if val , ok := v .(pflag.Value ); ok {
575
+ val .Set (fmt .Sprintf ("%v" , d ))
576
+ } else {
577
+ logrus .Fatalf ("%s --%s: unhandled value type: %v (%T)" , cmdName , fl .Name , v , v )
578
+ }
579
+ }
580
+
574
581
// AddFlags adds to the command the common flags that are annotated with the command name.
575
582
func AddFlags (cmd * cobra.Command ) {
576
583
var flagsForCommand []* Flag
@@ -613,3 +620,29 @@ func hasCmdAnnotation(cmdName string, annotations []string) bool {
613
620
}
614
621
return false
615
622
}
623
+
624
+ func reflectValueOf (values []interface {}) []reflect.Value {
625
+ var results []reflect.Value
626
+ for _ , v := range values {
627
+ results = append (results , reflect .ValueOf (v ))
628
+ }
629
+ return results
630
+ }
631
+
632
+ func asStringSlice (v interface {}) []string {
633
+ vt := reflect .TypeOf (v )
634
+ if vt == reflect .TypeOf ([]string {}) {
635
+ return v .([]string )
636
+ }
637
+ switch vt .Kind () {
638
+ case reflect .Array , reflect .Slice :
639
+ value := reflect .ValueOf (v )
640
+ var slice []string
641
+ for i := 0 ; i < value .Len (); i ++ {
642
+ slice = append (slice , fmt .Sprintf ("%v" , value .Index (i )))
643
+ }
644
+ return slice
645
+ default :
646
+ return []string {fmt .Sprintf ("%v" , v )}
647
+ }
648
+ }
0 commit comments