Merge pull request #12753 from eparis/rebase-pflag

Update spf13/pflag to fix StringSlice bug
pull/6/head
Marek Grabowski 2015-08-17 10:48:25 +02:00
commit ff1d3885b4
8 changed files with 213 additions and 16 deletions

4
Godeps/Godeps.json generated
View File

@ -488,8 +488,8 @@
},
{
"ImportPath": "github.com/spf13/pflag",
"Comment": "v0.0.1-73-g534019b",
"Rev": "534019bcaea096fc0f0641afa2aed1e80cbb0ccc"
"Comment": "v0.0.1-81-g4869ec2",
"Rev": "4869ec2ae0628354eaac5bf88fccf9a7265ae475"
},
{
"ImportPath": "github.com/stretchr/objx",

View File

@ -51,7 +51,7 @@ func (v *triStateValue) String() string {
return fmt.Sprintf("%v", bool(*v == triStateTrue))
}
// The type of the flag as requred by the pflag.Value interface
// The type of the flag as required by the pflag.Value interface
func (v *triStateValue) Type() string {
return "version"
}

View File

@ -330,6 +330,15 @@ func (f *FlagSet) SetAnnotation(name, key string, values []string) error {
return nil
}
func (f *FlagSet) Changed(name string) bool {
flag := f.Lookup(name)
// If a flag doesn't exist, it wasn't changed....
if flag == nil {
return false
}
return flag.Changed
}
// Set sets the value of the named command-line flag.
func Set(name, value string) error {
return CommandLine.Set(name, value)

View File

@ -381,6 +381,34 @@ func TestFlagSetParse(t *testing.T) {
testParse(NewFlagSet("test", ContinueOnError), t)
}
func TestChangedHelper(t *testing.T) {
f := NewFlagSet("changedtest", ContinueOnError)
_ = f.Bool("changed", false, "changed bool")
_ = f.Bool("settrue", true, "true to true")
_ = f.Bool("setfalse", false, "false to false")
_ = f.Bool("unchanged", false, "unchanged bool")
args := []string{"--changed", "--settrue", "--setfalse=false"}
if err := f.Parse(args); err != nil {
t.Error("f.Parse() = false after Parse")
}
if !f.Changed("changed") {
t.Errorf("--changed wasn't changed!")
}
if !f.Changed("settrue") {
t.Errorf("--settrue wasn't changed!")
}
if !f.Changed("setfalse") {
t.Errorf("--setfalse wasn't changed!")
}
if f.Changed("unchanged") {
t.Errorf("--unchanged was changed!")
}
if f.Changed("invalid") {
t.Errorf("--invalid was changed!")
}
}
func replaceSeparators(name string, from []string, to string) string {
result := name
for _, sep := range from {

View File

@ -7,11 +7,16 @@ import (
)
// -- intSlice Value
type intSliceValue []int
type intSliceValue struct {
value *[]int
changed bool
}
func newIntSliceValue(val []int, p *[]int) *intSliceValue {
*p = val
return (*intSliceValue)(p)
isv := new(intSliceValue)
isv.value = p
*isv.value = val
return isv
}
func (s *intSliceValue) Set(val string) error {
@ -25,7 +30,12 @@ func (s *intSliceValue) Set(val string) error {
}
}
*s = append(*s, out...)
if !s.changed {
*s.value = out
} else {
*s.value = append(*s.value, out...)
}
s.changed = true
return nil
}
@ -34,8 +44,8 @@ func (s *intSliceValue) Type() string {
}
func (s *intSliceValue) String() string {
out := make([]string, len(*s))
for i, d := range *s {
out := make([]string, len(*s.value))
for i, d := range *s.value {
out[i] = fmt.Sprintf("%d", d)
}
return "[" + strings.Join(out, ",") + "]"

View File

@ -17,6 +17,12 @@ func setUpISFlagSet(isp *[]int) *FlagSet {
return f
}
func setUpISFlagSetWithDefault(isp *[]int) *FlagSet {
f := NewFlagSet("test", ContinueOnError)
f.IntSliceVar(isp, "is", []int{0, 1}, "Command seperated list!")
return f
}
func TestEmptyIS(t *testing.T) {
var is []int
f := setUpISFlagSet(&is)
@ -27,7 +33,7 @@ func TestEmptyIS(t *testing.T) {
getIS, err := f.GetIntSlice("is")
if err != nil {
t.Fatal("got an error from GetStringSlice():", err)
t.Fatal("got an error from GetIntSlice():", err)
}
if len(getIS) != 0 {
t.Fatalf("got is %v with len=%d but expected length=0", getIS, len(getIS))
@ -65,6 +71,76 @@ func TestIS(t *testing.T) {
}
}
func TestISDefault(t *testing.T) {
var is []int
f := setUpISFlagSetWithDefault(&is)
vals := []string{"0", "1"}
err := f.Parse([]string{})
if err != nil {
t.Fatal("expected no error; got", err)
}
for i, v := range is {
d, err := strconv.Atoi(vals[i])
if err != nil {
t.Fatalf("got error: %v", err)
}
if d != v {
t.Fatalf("expected is[%d] to be %s but got: %s", i, d, v)
}
}
getIS, err := f.GetIntSlice("is")
if err != nil {
t.Fatal("got an error from GetIntSlice():", err)
}
for i, v := range getIS {
d, err := strconv.Atoi(vals[i])
if err != nil {
t.Fatal("got an error from GetIntSlice():", err)
}
if d != v {
t.Fatalf("expected is[%d] to be %s from GetIntSlice but got: %s", i, d, v)
}
}
}
func TestISWithDefault(t *testing.T) {
var is []int
f := setUpISFlagSetWithDefault(&is)
vals := []string{"1", "2"}
arg := fmt.Sprintf("--is=%s", strings.Join(vals, ","))
err := f.Parse([]string{arg})
if err != nil {
t.Fatal("expected no error; got", err)
}
for i, v := range is {
d, err := strconv.Atoi(vals[i])
if err != nil {
t.Fatalf("got error: %v", err)
}
if d != v {
t.Fatalf("expected is[%d] to be %s but got: %s", i, d, v)
}
}
getIS, err := f.GetIntSlice("is")
if err != nil {
t.Fatal("got an error from GetIntSlice():", err)
}
for i, v := range getIS {
d, err := strconv.Atoi(vals[i])
if err != nil {
t.Fatalf("got error: %v", err)
}
if d != v {
t.Fatalf("expected is[%d] to be %s from GetIntSlice but got: %s", i, d, v)
}
}
}
func TestISCalledTwice(t *testing.T) {
var is []int
f := setUpISFlagSet(&is)
@ -80,7 +156,7 @@ func TestISCalledTwice(t *testing.T) {
}
for i, v := range is {
if expected[i] != v {
t.Fatalf("expected ss[%d] to be %s but got: %s", i, expected[i], v)
t.Fatalf("expected is[%d] to be %s but got: %s", i, expected[i], v)
}
}
}

View File

@ -1,27 +1,41 @@
package pflag
import (
"fmt"
"strings"
)
var _ = fmt.Fprint
// -- stringSlice Value
type stringSliceValue []string
type stringSliceValue struct {
value *[]string
changed bool
}
func newStringSliceValue(val []string, p *[]string) *stringSliceValue {
*p = val
return (*stringSliceValue)(p)
ssv := new(stringSliceValue)
ssv.value = p
*ssv.value = val
return ssv
}
func (s *stringSliceValue) Set(val string) error {
v := strings.Split(val, ",")
*s = append(*s, v...)
if !s.changed {
*s.value = v
} else {
*s.value = append(*s.value, v...)
}
s.changed = true
return nil
}
func (s *stringSliceValue) Type() string {
return "stringSlice"
}
func (s *stringSliceValue) String() string { return "[" + strings.Join(*s, ",") + "]" }
func (s *stringSliceValue) String() string { return "[" + strings.Join(*s.value, ",") + "]" }
func stringSliceConv(sval string) (interface{}, error) {
sval = strings.Trim(sval, "[]")

View File

@ -16,6 +16,12 @@ func setUpSSFlagSet(ssp *[]string) *FlagSet {
return f
}
func setUpSSFlagSetWithDefault(ssp *[]string) *FlagSet {
f := NewFlagSet("test", ContinueOnError)
f.StringSliceVar(ssp, "ss", []string{"default", "values"}, "Command seperated list!")
return f
}
func TestEmptySS(t *testing.T) {
var ss []string
f := setUpSSFlagSet(&ss)
@ -60,6 +66,60 @@ func TestSS(t *testing.T) {
}
}
func TestSSDefault(t *testing.T) {
var ss []string
f := setUpSSFlagSetWithDefault(&ss)
vals := []string{"default", "values"}
err := f.Parse([]string{})
if err != nil {
t.Fatal("expected no error; got", err)
}
for i, v := range ss {
if vals[i] != v {
t.Fatalf("expected ss[%d] to be %s but got: %s", i, vals[i], v)
}
}
getSS, err := f.GetStringSlice("ss")
if err != nil {
t.Fatal("got an error from GetStringSlice():", err)
}
for i, v := range getSS {
if vals[i] != v {
t.Fatalf("expected ss[%d] to be %s from GetStringSlice but got: %s", i, vals[i], v)
}
}
}
func TestSSWithDefault(t *testing.T) {
var ss []string
f := setUpSSFlagSetWithDefault(&ss)
vals := []string{"one", "two", "4", "3"}
arg := fmt.Sprintf("--ss=%s", strings.Join(vals, ","))
err := f.Parse([]string{arg})
if err != nil {
t.Fatal("expected no error; got", err)
}
for i, v := range ss {
if vals[i] != v {
t.Fatalf("expected ss[%d] to be %s but got: %s", i, vals[i], v)
}
}
getSS, err := f.GetStringSlice("ss")
if err != nil {
t.Fatal("got an error from GetStringSlice():", err)
}
for i, v := range getSS {
if vals[i] != v {
t.Fatalf("expected ss[%d] to be %s from GetStringSlice but got: %s", i, vals[i], v)
}
}
}
func TestSSCalledTwice(t *testing.T) {
var ss []string
f := setUpSSFlagSet(&ss)