Browse Source

Add mflag package locally to libnetwork

Since docker/docker removed mflag package and libnetwork relies on it
create a copy of mflag package in libnetwork project.

Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
Jana Radhakrishnan 8 years ago
parent
commit
f5516d817d

+ 1 - 1
libnetwork/client/client.go

@@ -8,7 +8,7 @@ import (
 	"reflect"
 	"strings"
 
-	flag "github.com/docker/docker/pkg/mflag"
+	flag "github.com/docker/libnetwork/client/mflag"
 )
 
 // CallFunc provides environment specific call utility to invoke backend functions from UI

+ 27 - 0
libnetwork/client/mflag/LICENSE

@@ -0,0 +1,27 @@
+Copyright (c) 2014-2016 The Docker & Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 40 - 0
libnetwork/client/mflag/README.md

@@ -0,0 +1,40 @@
+Package mflag (aka multiple-flag) implements command-line flag parsing.  
+It's an **hacky** fork of the [official golang package](http://golang.org/pkg/flag/)
+
+It adds:
+
+* both short and long flag version  
+`./example -s red` `./example --string blue`
+
+* multiple names for the same option  
+```
+$>./example -h
+Usage of example:
+  -s, --string="": a simple string
+```
+
+___
+It is very flexible on purpose, so you can do things like:  
+```
+$>./example -h
+Usage of example:
+  -s, -string, --string="": a simple string
+```
+
+Or:  
+```
+$>./example -h
+Usage of example:
+  -oldflag, --newflag="": a simple string
+```
+
+You can also hide some flags from the usage, so if we want only `--newflag`:  
+```
+$>./example -h
+Usage of example:
+  --newflag="": a simple string
+$>./example -oldflag str
+str
+```
+
+See [example.go](example/example.go) for more details.

+ 36 - 0
libnetwork/client/mflag/example/example.go

@@ -0,0 +1,36 @@
+package main
+
+import (
+	"fmt"
+
+	flag "github.com/docker/libnetwork/client/mflag"
+)
+
+var (
+	i        int
+	str      string
+	b, b2, h bool
+)
+
+func init() {
+	flag.Bool([]string{"#hp", "#-halp"}, false, "display the halp")
+	flag.BoolVar(&b, []string{"b", "#bal", "#bol", "-bal"}, false, "a simple bool")
+	flag.BoolVar(&b, []string{"g", "#gil"}, false, "a simple bool")
+	flag.BoolVar(&b2, []string{"#-bool"}, false, "a simple bool")
+	flag.IntVar(&i, []string{"-integer", "-number"}, -1, "a simple integer")
+	flag.StringVar(&str, []string{"s", "#hidden", "-string"}, "", "a simple string") //-s -hidden and --string will work, but -hidden won't be in the usage
+	flag.BoolVar(&h, []string{"h", "#help", "-help"}, false, "display the help")
+	flag.StringVar(&str, []string{"mode"}, "mode1", "set the mode\nmode1: use the mode1\nmode2: use the mode2\nmode3: use the mode3")
+	flag.Parse()
+}
+func main() {
+	if h {
+		flag.PrintDefaults()
+	} else {
+		fmt.Printf("s/#hidden/-string: %s\n", str)
+		fmt.Printf("b: %t\n", b)
+		fmt.Printf("-bool: %t\n", b2)
+		fmt.Printf("s/#hidden/-string(via lookup): %s\n", flag.Lookup("s").Value.String())
+		fmt.Printf("ARGS: %v\n", flag.Args())
+	}
+}

+ 1280 - 0
libnetwork/client/mflag/flag.go

@@ -0,0 +1,1280 @@
+// Copyright 2014-2016 The Docker & Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//	Package mflag implements command-line flag parsing.
+//
+//	Usage:
+//
+//	Define flags using flag.String(), Bool(), Int(), etc.
+//
+//	This declares an integer flag, -f or --flagname, stored in the pointer ip, with type *int.
+//		import "flag /github.com/docker/libnetwork/client/mflag"
+//		var ip = flag.Int([]string{"f", "-flagname"}, 1234, "help message for flagname")
+//	If you like, you can bind the flag to a variable using the Var() functions.
+//		var flagvar int
+//		func init() {
+//			// -flaghidden will work, but will be hidden from the usage
+//			flag.IntVar(&flagvar, []string{"f", "#flaghidden", "-flagname"}, 1234, "help message for flagname")
+//		}
+//	Or you can create custom flags that satisfy the Value interface (with
+//	pointer receivers) and couple them to flag parsing by
+//		flag.Var(&flagVal, []string{"name"}, "help message for flagname")
+//	For such flags, the default value is just the initial value of the variable.
+//
+//	You can also add "deprecated" flags, they are still usable, but are not shown
+//	in the usage and will display a warning when you try to use them. `#` before
+//	an option means this option is deprecated, if there is an following option
+//	without `#` ahead, then that's the replacement, if not, it will just be removed:
+//		var ip = flag.Int([]string{"#f", "#flagname", "-flagname"}, 1234, "help message for flagname")
+//	this will display: `Warning: '-f' is deprecated, it will be replaced by '--flagname' soon. See usage.` or
+//	this will display: `Warning: '-flagname' is deprecated, it will be replaced by '--flagname' soon. See usage.`
+//		var ip = flag.Int([]string{"f", "#flagname"}, 1234, "help message for flagname")
+//	will display: `Warning: '-flagname' is deprecated, it will be removed soon. See usage.`
+//	so you can only use `-f`.
+//
+//	You can also group one letter flags, bif you declare
+//		var v = flag.Bool([]string{"v", "-verbose"}, false, "help message for verbose")
+//		var s = flag.Bool([]string{"s", "-slow"}, false, "help message for slow")
+//	you will be able to use the -vs or -sv
+//
+//	After all flags are defined, call
+//		flag.Parse()
+//	to parse the command line into the defined flags.
+//
+//	Flags may then be used directly. If you're using the flags themselves,
+//	they are all pointers; if you bind to variables, they're values.
+//		fmt.Println("ip has value ", *ip)
+//		fmt.Println("flagvar has value ", flagvar)
+//
+//	After parsing, the arguments after the flag are available as the
+//	slice flag.Args() or individually as flag.Arg(i).
+//	The arguments are indexed from 0 through flag.NArg()-1.
+//
+//	Command line flag syntax:
+//		-flag
+//		-flag=x
+//		-flag="x"
+//		-flag='x'
+//		-flag x  // non-boolean flags only
+//	One or two minus signs may be used; they are equivalent.
+//	The last form is not permitted for boolean flags because the
+//	meaning of the command
+//		cmd -x *
+//	will change if there is a file called 0, false, etc.  You must
+//	use the -flag=false form to turn off a boolean flag.
+//
+//	Flag parsing stops just before the first non-flag argument
+//	("-" is a non-flag argument) or after the terminator "--".
+//
+//	Integer flags accept 1234, 0664, 0x1234 and may be negative.
+//	Boolean flags may be 1, 0, t, f, true, false, TRUE, FALSE, True, False.
+//	Duration flags accept any input valid for time.ParseDuration.
+//
+//	The default set of command-line flags is controlled by
+//	top-level functions.  The FlagSet type allows one to define
+//	independent sets of flags, such as to implement subcommands
+//	in a command-line interface. The methods of FlagSet are
+//	analogous to the top-level functions for the command-line
+//	flag set.
+
+package mflag
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"os"
+	"runtime"
+	"sort"
+	"strconv"
+	"strings"
+	"text/tabwriter"
+	"time"
+
+	"github.com/docker/docker/pkg/homedir"
+)
+
+// ErrHelp is the error returned if the flag -help is invoked but no such flag is defined.
+var ErrHelp = errors.New("flag: help requested")
+
+// ErrRetry is the error returned if you need to try letter by letter
+var ErrRetry = errors.New("flag: retry")
+
+// -- bool Value
+type boolValue bool
+
+func newBoolValue(val bool, p *bool) *boolValue {
+	*p = val
+	return (*boolValue)(p)
+}
+
+func (b *boolValue) Set(s string) error {
+	v, err := strconv.ParseBool(s)
+	*b = boolValue(v)
+	return err
+}
+
+func (b *boolValue) Get() interface{} { return bool(*b) }
+
+func (b *boolValue) String() string { return fmt.Sprintf("%v", *b) }
+
+func (b *boolValue) IsBoolFlag() bool { return true }
+
+// optional interface to indicate boolean flags that can be
+// supplied without "=value" text
+type boolFlag interface {
+	Value
+	IsBoolFlag() bool
+}
+
+// -- int Value
+type intValue int
+
+func newIntValue(val int, p *int) *intValue {
+	*p = val
+	return (*intValue)(p)
+}
+
+func (i *intValue) Set(s string) error {
+	v, err := strconv.ParseInt(s, 0, 64)
+	*i = intValue(v)
+	return err
+}
+
+func (i *intValue) Get() interface{} { return int(*i) }
+
+func (i *intValue) String() string { return fmt.Sprintf("%v", *i) }
+
+// -- int64 Value
+type int64Value int64
+
+func newInt64Value(val int64, p *int64) *int64Value {
+	*p = val
+	return (*int64Value)(p)
+}
+
+func (i *int64Value) Set(s string) error {
+	v, err := strconv.ParseInt(s, 0, 64)
+	*i = int64Value(v)
+	return err
+}
+
+func (i *int64Value) Get() interface{} { return int64(*i) }
+
+func (i *int64Value) String() string { return fmt.Sprintf("%v", *i) }
+
+// -- uint Value
+type uintValue uint
+
+func newUintValue(val uint, p *uint) *uintValue {
+	*p = val
+	return (*uintValue)(p)
+}
+
+func (i *uintValue) Set(s string) error {
+	v, err := strconv.ParseUint(s, 0, 64)
+	*i = uintValue(v)
+	return err
+}
+
+func (i *uintValue) Get() interface{} { return uint(*i) }
+
+func (i *uintValue) String() string { return fmt.Sprintf("%v", *i) }
+
+// -- uint64 Value
+type uint64Value uint64
+
+func newUint64Value(val uint64, p *uint64) *uint64Value {
+	*p = val
+	return (*uint64Value)(p)
+}
+
+func (i *uint64Value) Set(s string) error {
+	v, err := strconv.ParseUint(s, 0, 64)
+	*i = uint64Value(v)
+	return err
+}
+
+func (i *uint64Value) Get() interface{} { return uint64(*i) }
+
+func (i *uint64Value) String() string { return fmt.Sprintf("%v", *i) }
+
+// -- uint16 Value
+type uint16Value uint16
+
+func newUint16Value(val uint16, p *uint16) *uint16Value {
+	*p = val
+	return (*uint16Value)(p)
+}
+
+func (i *uint16Value) Set(s string) error {
+	v, err := strconv.ParseUint(s, 0, 16)
+	*i = uint16Value(v)
+	return err
+}
+
+func (i *uint16Value) Get() interface{} { return uint16(*i) }
+
+func (i *uint16Value) String() string { return fmt.Sprintf("%v", *i) }
+
+// -- string Value
+type stringValue string
+
+func newStringValue(val string, p *string) *stringValue {
+	*p = val
+	return (*stringValue)(p)
+}
+
+func (s *stringValue) Set(val string) error {
+	*s = stringValue(val)
+	return nil
+}
+
+func (s *stringValue) Get() interface{} { return string(*s) }
+
+func (s *stringValue) String() string { return fmt.Sprintf("%s", *s) }
+
+// -- float64 Value
+type float64Value float64
+
+func newFloat64Value(val float64, p *float64) *float64Value {
+	*p = val
+	return (*float64Value)(p)
+}
+
+func (f *float64Value) Set(s string) error {
+	v, err := strconv.ParseFloat(s, 64)
+	*f = float64Value(v)
+	return err
+}
+
+func (f *float64Value) Get() interface{} { return float64(*f) }
+
+func (f *float64Value) String() string { return fmt.Sprintf("%v", *f) }
+
+// -- time.Duration Value
+type durationValue time.Duration
+
+func newDurationValue(val time.Duration, p *time.Duration) *durationValue {
+	*p = val
+	return (*durationValue)(p)
+}
+
+func (d *durationValue) Set(s string) error {
+	v, err := time.ParseDuration(s)
+	*d = durationValue(v)
+	return err
+}
+
+func (d *durationValue) Get() interface{} { return time.Duration(*d) }
+
+func (d *durationValue) String() string { return (*time.Duration)(d).String() }
+
+// Value is the interface to the dynamic value stored in a flag.
+// (The default value is represented as a string.)
+//
+// If a Value has an IsBoolFlag() bool method returning true,
+// the command-line parser makes -name equivalent to -name=true
+// rather than using the next command-line argument.
+type Value interface {
+	String() string
+	Set(string) error
+}
+
+// Getter is an interface that allows the contents of a Value to be retrieved.
+// It wraps the Value interface, rather than being part of it, because it
+// appeared after Go 1 and its compatibility rules. All Value types provided
+// by this package satisfy the Getter interface.
+type Getter interface {
+	Value
+	Get() interface{}
+}
+
+// ErrorHandling defines how to handle flag parsing errors.
+type ErrorHandling int
+
+// ErrorHandling strategies available when a flag parsing error occurs
+const (
+	ContinueOnError ErrorHandling = iota
+	ExitOnError
+	PanicOnError
+)
+
+// A FlagSet represents a set of defined flags.  The zero value of a FlagSet
+// has no name and has ContinueOnError error handling.
+type FlagSet struct {
+	// Usage is the function called when an error occurs while parsing flags.
+	// The field is a function (not a method) that may be changed to point to
+	// a custom error handler.
+	Usage      func()
+	ShortUsage func()
+
+	name             string
+	parsed           bool
+	actual           map[string]*Flag
+	formal           map[string]*Flag
+	args             []string // arguments after flags
+	errorHandling    ErrorHandling
+	output           io.Writer // nil means stderr; use Out() accessor
+	nArgRequirements []nArgRequirement
+}
+
+// A Flag represents the state of a flag.
+type Flag struct {
+	Names    []string // name as it appears on command line
+	Usage    string   // help message
+	Value    Value    // value as set
+	DefValue string   // default value (as text); for usage message
+}
+
+type flagSlice []string
+
+func (p flagSlice) Len() int { return len(p) }
+func (p flagSlice) Less(i, j int) bool {
+	pi, pj := strings.TrimPrefix(p[i], "-"), strings.TrimPrefix(p[j], "-")
+	lpi, lpj := strings.ToLower(pi), strings.ToLower(pj)
+	if lpi != lpj {
+		return lpi < lpj
+	}
+	return pi < pj
+}
+func (p flagSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+// sortFlags returns the flags as a slice in lexicographical sorted order.
+func sortFlags(flags map[string]*Flag) []*Flag {
+	var list flagSlice
+
+	// The sorted list is based on the first name, when flag map might use the other names.
+	nameMap := make(map[string]string)
+
+	for n, f := range flags {
+		fName := strings.TrimPrefix(f.Names[0], "#")
+		nameMap[fName] = n
+		if len(f.Names) == 1 {
+			list = append(list, fName)
+			continue
+		}
+
+		found := false
+		for _, name := range list {
+			if name == fName {
+				found = true
+				break
+			}
+		}
+		if !found {
+			list = append(list, fName)
+		}
+	}
+	sort.Sort(list)
+	result := make([]*Flag, len(list))
+	for i, name := range list {
+		result[i] = flags[nameMap[name]]
+	}
+	return result
+}
+
+// Name returns the name of the FlagSet.
+func (fs *FlagSet) Name() string {
+	return fs.name
+}
+
+// Out returns the destination for usage and error messages.
+func (fs *FlagSet) Out() io.Writer {
+	if fs.output == nil {
+		return os.Stderr
+	}
+	return fs.output
+}
+
+// SetOutput sets the destination for usage and error messages.
+// If output is nil, os.Stderr is used.
+func (fs *FlagSet) SetOutput(output io.Writer) {
+	fs.output = output
+}
+
+// VisitAll visits the flags in lexicographical order, calling fn for each.
+// It visits all flags, even those not set.
+func (fs *FlagSet) VisitAll(fn func(*Flag)) {
+	for _, flag := range sortFlags(fs.formal) {
+		fn(flag)
+	}
+}
+
+// VisitAll visits the command-line flags in lexicographical order, calling
+// fn for each.  It visits all flags, even those not set.
+func VisitAll(fn func(*Flag)) {
+	CommandLine.VisitAll(fn)
+}
+
+// Visit visits the flags in lexicographical order, calling fn for each.
+// It visits only those flags that have been set.
+func (fs *FlagSet) Visit(fn func(*Flag)) {
+	for _, flag := range sortFlags(fs.actual) {
+		fn(flag)
+	}
+}
+
+// Visit visits the command-line flags in lexicographical order, calling fn
+// for each.  It visits only those flags that have been set.
+func Visit(fn func(*Flag)) {
+	CommandLine.Visit(fn)
+}
+
+// Lookup returns the Flag structure of the named flag, returning nil if none exists.
+func (fs *FlagSet) Lookup(name string) *Flag {
+	return fs.formal[name]
+}
+
+// IsSet indicates whether the specified flag is set in the given FlagSet
+func (fs *FlagSet) IsSet(name string) bool {
+	return fs.actual[name] != nil
+}
+
+// Lookup returns the Flag structure of the named command-line flag,
+// returning nil if none exists.
+func Lookup(name string) *Flag {
+	return CommandLine.formal[name]
+}
+
+// IsSet indicates whether the specified flag was specified at all on the cmd line.
+func IsSet(name string) bool {
+	return CommandLine.IsSet(name)
+}
+
+type nArgRequirementType int
+
+// Indicator used to pass to BadArgs function
+const (
+	Exact nArgRequirementType = iota
+	Max
+	Min
+)
+
+type nArgRequirement struct {
+	Type nArgRequirementType
+	N    int
+}
+
+// Require adds a requirement about the number of arguments for the FlagSet.
+// The first parameter can be Exact, Max, or Min to respectively specify the exact,
+// the maximum, or the minimal number of arguments required.
+// The actual check is done in FlagSet.CheckArgs().
+func (fs *FlagSet) Require(nArgRequirementType nArgRequirementType, nArg int) {
+	fs.nArgRequirements = append(fs.nArgRequirements, nArgRequirement{nArgRequirementType, nArg})
+}
+
+// CheckArgs uses the requirements set by FlagSet.Require() to validate
+// the number of arguments. If the requirements are not met,
+// an error message string is returned.
+func (fs *FlagSet) CheckArgs() (message string) {
+	for _, req := range fs.nArgRequirements {
+		var arguments string
+		if req.N == 1 {
+			arguments = "1 argument"
+		} else {
+			arguments = fmt.Sprintf("%d arguments", req.N)
+		}
+
+		str := func(kind string) string {
+			return fmt.Sprintf("%q requires %s%s", fs.name, kind, arguments)
+		}
+
+		switch req.Type {
+		case Exact:
+			if fs.NArg() != req.N {
+				return str("")
+			}
+		case Max:
+			if fs.NArg() > req.N {
+				return str("a maximum of ")
+			}
+		case Min:
+			if fs.NArg() < req.N {
+				return str("a minimum of ")
+			}
+		}
+	}
+	return ""
+}
+
+// Set sets the value of the named flag.
+func (fs *FlagSet) Set(name, value string) error {
+	flag, ok := fs.formal[name]
+	if !ok {
+		return fmt.Errorf("no such flag -%v", name)
+	}
+	if err := flag.Value.Set(value); err != nil {
+		return err
+	}
+	if fs.actual == nil {
+		fs.actual = make(map[string]*Flag)
+	}
+	fs.actual[name] = flag
+	return nil
+}
+
+// Set sets the value of the named command-line flag.
+func Set(name, value string) error {
+	return CommandLine.Set(name, value)
+}
+
+// isZeroValue guesses whether the string represents the zero
+// value for a flag. It is not accurate but in practice works OK.
+func isZeroValue(value string) bool {
+	switch value {
+	case "false":
+		return true
+	case "":
+		return true
+	case "0":
+		return true
+	}
+	return false
+}
+
+// PrintDefaults prints, to standard error unless configured
+// otherwise, the default values of all defined flags in the set.
+func (fs *FlagSet) PrintDefaults() {
+	writer := tabwriter.NewWriter(fs.Out(), 20, 1, 3, ' ', 0)
+	home := homedir.Get()
+
+	// Don't substitute when HOME is /
+	if runtime.GOOS != "windows" && home == "/" {
+		home = ""
+	}
+
+	// Add a blank line between cmd description and list of options
+	if fs.FlagCount() > 0 {
+		fmt.Fprintln(writer, "")
+	}
+
+	fs.VisitAll(func(flag *Flag) {
+		names := []string{}
+		for _, name := range flag.Names {
+			if name[0] != '#' {
+				names = append(names, name)
+			}
+		}
+		if len(names) > 0 && len(flag.Usage) > 0 {
+			val := flag.DefValue
+
+			if home != "" && strings.HasPrefix(val, home) {
+				val = homedir.GetShortcutString() + val[len(home):]
+			}
+
+			if isZeroValue(val) {
+				format := "  -%s"
+				fmt.Fprintf(writer, format, strings.Join(names, ", -"))
+			} else {
+				format := "  -%s=%s"
+				fmt.Fprintf(writer, format, strings.Join(names, ", -"), val)
+			}
+			for _, line := range strings.Split(flag.Usage, "\n") {
+				fmt.Fprintln(writer, "\t", line)
+			}
+		}
+	})
+	writer.Flush()
+}
+
+// PrintDefaults prints to standard error the default values of all defined command-line flags.
+func PrintDefaults() {
+	CommandLine.PrintDefaults()
+}
+
+// defaultUsage is the default function to print a usage message.
+func defaultUsage(fs *FlagSet) {
+	if fs.name == "" {
+		fmt.Fprintf(fs.Out(), "Usage:\n")
+	} else {
+		fmt.Fprintf(fs.Out(), "Usage of %s:\n", fs.name)
+	}
+	fs.PrintDefaults()
+}
+
+// NOTE: Usage is not just defaultUsage(CommandLine)
+// because it serves (via godoc flag Usage) as the example
+// for how to write your own usage function.
+
+// Usage prints to standard error a usage message documenting all defined command-line flags.
+// The function is a variable that may be changed to point to a custom function.
+var Usage = func() {
+	fmt.Fprintf(CommandLine.Out(), "Usage of %s:\n", os.Args[0])
+	PrintDefaults()
+}
+
+// ShortUsage prints to standard error a usage message documenting the standard command layout
+// The function is a variable that may be changed to point to a custom function.
+var ShortUsage = func() {
+	fmt.Fprintf(CommandLine.output, "Usage of %s:\n", os.Args[0])
+}
+
+// FlagCount returns the number of flags that have been defined.
+func (fs *FlagSet) FlagCount() int { return len(sortFlags(fs.formal)) }
+
+// FlagCountUndeprecated returns the number of undeprecated flags that have been defined.
+func (fs *FlagSet) FlagCountUndeprecated() int {
+	count := 0
+	for _, flag := range sortFlags(fs.formal) {
+		for _, name := range flag.Names {
+			if name[0] != '#' {
+				count++
+				break
+			}
+		}
+	}
+	return count
+}
+
+// NFlag returns the number of flags that have been set.
+func (fs *FlagSet) NFlag() int { return len(fs.actual) }
+
+// NFlag returns the number of command-line flags that have been set.
+func NFlag() int { return len(CommandLine.actual) }
+
+// Arg returns the i'th argument.  Arg(0) is the first remaining argument
+// after flags have been processed.
+func (fs *FlagSet) Arg(i int) string {
+	if i < 0 || i >= len(fs.args) {
+		return ""
+	}
+	return fs.args[i]
+}
+
+// Arg returns the i'th command-line argument.  Arg(0) is the first remaining argument
+// after flags have been processed.
+func Arg(i int) string {
+	return CommandLine.Arg(i)
+}
+
+// NArg is the number of arguments remaining after flags have been processed.
+func (fs *FlagSet) NArg() int { return len(fs.args) }
+
+// NArg is the number of arguments remaining after flags have been processed.
+func NArg() int { return len(CommandLine.args) }
+
+// Args returns the non-flag arguments.
+func (fs *FlagSet) Args() []string { return fs.args }
+
+// Args returns the non-flag command-line arguments.
+func Args() []string { return CommandLine.args }
+
+// BoolVar defines a bool flag with specified name, default value, and usage string.
+// The argument p points to a bool variable in which to store the value of the flag.
+func (fs *FlagSet) BoolVar(p *bool, names []string, value bool, usage string) {
+	fs.Var(newBoolValue(value, p), names, usage)
+}
+
+// BoolVar defines a bool flag with specified name, default value, and usage string.
+// The argument p points to a bool variable in which to store the value of the flag.
+func BoolVar(p *bool, names []string, value bool, usage string) {
+	CommandLine.Var(newBoolValue(value, p), names, usage)
+}
+
+// Bool defines a bool flag with specified name, default value, and usage string.
+// The return value is the address of a bool variable that stores the value of the flag.
+func (fs *FlagSet) Bool(names []string, value bool, usage string) *bool {
+	p := new(bool)
+	fs.BoolVar(p, names, value, usage)
+	return p
+}
+
+// Bool defines a bool flag with specified name, default value, and usage string.
+// The return value is the address of a bool variable that stores the value of the flag.
+func Bool(names []string, value bool, usage string) *bool {
+	return CommandLine.Bool(names, value, usage)
+}
+
+// IntVar defines an int flag with specified name, default value, and usage string.
+// The argument p points to an int variable in which to store the value of the flag.
+func (fs *FlagSet) IntVar(p *int, names []string, value int, usage string) {
+	fs.Var(newIntValue(value, p), names, usage)
+}
+
+// IntVar defines an int flag with specified name, default value, and usage string.
+// The argument p points to an int variable in which to store the value of the flag.
+func IntVar(p *int, names []string, value int, usage string) {
+	CommandLine.Var(newIntValue(value, p), names, usage)
+}
+
+// Int defines an int flag with specified name, default value, and usage string.
+// The return value is the address of an int variable that stores the value of the flag.
+func (fs *FlagSet) Int(names []string, value int, usage string) *int {
+	p := new(int)
+	fs.IntVar(p, names, value, usage)
+	return p
+}
+
+// Int defines an int flag with specified name, default value, and usage string.
+// The return value is the address of an int variable that stores the value of the flag.
+func Int(names []string, value int, usage string) *int {
+	return CommandLine.Int(names, value, usage)
+}
+
+// Int64Var defines an int64 flag with specified name, default value, and usage string.
+// The argument p points to an int64 variable in which to store the value of the flag.
+func (fs *FlagSet) Int64Var(p *int64, names []string, value int64, usage string) {
+	fs.Var(newInt64Value(value, p), names, usage)
+}
+
+// Int64Var defines an int64 flag with specified name, default value, and usage string.
+// The argument p points to an int64 variable in which to store the value of the flag.
+func Int64Var(p *int64, names []string, value int64, usage string) {
+	CommandLine.Var(newInt64Value(value, p), names, usage)
+}
+
+// Int64 defines an int64 flag with specified name, default value, and usage string.
+// The return value is the address of an int64 variable that stores the value of the flag.
+func (fs *FlagSet) Int64(names []string, value int64, usage string) *int64 {
+	p := new(int64)
+	fs.Int64Var(p, names, value, usage)
+	return p
+}
+
+// Int64 defines an int64 flag with specified name, default value, and usage string.
+// The return value is the address of an int64 variable that stores the value of the flag.
+func Int64(names []string, value int64, usage string) *int64 {
+	return CommandLine.Int64(names, value, usage)
+}
+
+// UintVar defines a uint flag with specified name, default value, and usage string.
+// The argument p points to a uint variable in which to store the value of the flag.
+func (fs *FlagSet) UintVar(p *uint, names []string, value uint, usage string) {
+	fs.Var(newUintValue(value, p), names, usage)
+}
+
+// UintVar defines a uint flag with specified name, default value, and usage string.
+// The argument p points to a uint  variable in which to store the value of the flag.
+func UintVar(p *uint, names []string, value uint, usage string) {
+	CommandLine.Var(newUintValue(value, p), names, usage)
+}
+
+// Uint defines a uint flag with specified name, default value, and usage string.
+// The return value is the address of a uint  variable that stores the value of the flag.
+func (fs *FlagSet) Uint(names []string, value uint, usage string) *uint {
+	p := new(uint)
+	fs.UintVar(p, names, value, usage)
+	return p
+}
+
+// Uint defines a uint flag with specified name, default value, and usage string.
+// The return value is the address of a uint  variable that stores the value of the flag.
+func Uint(names []string, value uint, usage string) *uint {
+	return CommandLine.Uint(names, value, usage)
+}
+
+// Uint64Var defines a uint64 flag with specified name, default value, and usage string.
+// The argument p points to a uint64 variable in which to store the value of the flag.
+func (fs *FlagSet) Uint64Var(p *uint64, names []string, value uint64, usage string) {
+	fs.Var(newUint64Value(value, p), names, usage)
+}
+
+// Uint64Var defines a uint64 flag with specified name, default value, and usage string.
+// The argument p points to a uint64 variable in which to store the value of the flag.
+func Uint64Var(p *uint64, names []string, value uint64, usage string) {
+	CommandLine.Var(newUint64Value(value, p), names, usage)
+}
+
+// Uint64 defines a uint64 flag with specified name, default value, and usage string.
+// The return value is the address of a uint64 variable that stores the value of the flag.
+func (fs *FlagSet) Uint64(names []string, value uint64, usage string) *uint64 {
+	p := new(uint64)
+	fs.Uint64Var(p, names, value, usage)
+	return p
+}
+
+// Uint64 defines a uint64 flag with specified name, default value, and usage string.
+// The return value is the address of a uint64 variable that stores the value of the flag.
+func Uint64(names []string, value uint64, usage string) *uint64 {
+	return CommandLine.Uint64(names, value, usage)
+}
+
+// Uint16Var defines a uint16 flag with specified name, default value, and usage string.
+// The argument p points to a uint16 variable in which to store the value of the flag.
+func (fs *FlagSet) Uint16Var(p *uint16, names []string, value uint16, usage string) {
+	fs.Var(newUint16Value(value, p), names, usage)
+}
+
+// Uint16Var defines a uint16 flag with specified name, default value, and usage string.
+// The argument p points to a uint16 variable in which to store the value of the flag.
+func Uint16Var(p *uint16, names []string, value uint16, usage string) {
+	CommandLine.Var(newUint16Value(value, p), names, usage)
+}
+
+// Uint16 defines a uint16 flag with specified name, default value, and usage string.
+// The return value is the address of a uint16 variable that stores the value of the flag.
+func (fs *FlagSet) Uint16(names []string, value uint16, usage string) *uint16 {
+	p := new(uint16)
+	fs.Uint16Var(p, names, value, usage)
+	return p
+}
+
+// Uint16 defines a uint16 flag with specified name, default value, and usage string.
+// The return value is the address of a uint16 variable that stores the value of the flag.
+func Uint16(names []string, value uint16, usage string) *uint16 {
+	return CommandLine.Uint16(names, value, usage)
+}
+
+// StringVar defines a string flag with specified name, default value, and usage string.
+// The argument p points to a string variable in which to store the value of the flag.
+func (fs *FlagSet) StringVar(p *string, names []string, value string, usage string) {
+	fs.Var(newStringValue(value, p), names, usage)
+}
+
+// StringVar defines a string flag with specified name, default value, and usage string.
+// The argument p points to a string variable in which to store the value of the flag.
+func StringVar(p *string, names []string, value string, usage string) {
+	CommandLine.Var(newStringValue(value, p), names, usage)
+}
+
+// String defines a string flag with specified name, default value, and usage string.
+// The return value is the address of a string variable that stores the value of the flag.
+func (fs *FlagSet) String(names []string, value string, usage string) *string {
+	p := new(string)
+	fs.StringVar(p, names, value, usage)
+	return p
+}
+
+// String defines a string flag with specified name, default value, and usage string.
+// The return value is the address of a string variable that stores the value of the flag.
+func String(names []string, value string, usage string) *string {
+	return CommandLine.String(names, value, usage)
+}
+
+// Float64Var defines a float64 flag with specified name, default value, and usage string.
+// The argument p points to a float64 variable in which to store the value of the flag.
+func (fs *FlagSet) Float64Var(p *float64, names []string, value float64, usage string) {
+	fs.Var(newFloat64Value(value, p), names, usage)
+}
+
+// Float64Var defines a float64 flag with specified name, default value, and usage string.
+// The argument p points to a float64 variable in which to store the value of the flag.
+func Float64Var(p *float64, names []string, value float64, usage string) {
+	CommandLine.Var(newFloat64Value(value, p), names, usage)
+}
+
+// Float64 defines a float64 flag with specified name, default value, and usage string.
+// The return value is the address of a float64 variable that stores the value of the flag.
+func (fs *FlagSet) Float64(names []string, value float64, usage string) *float64 {
+	p := new(float64)
+	fs.Float64Var(p, names, value, usage)
+	return p
+}
+
+// Float64 defines a float64 flag with specified name, default value, and usage string.
+// The return value is the address of a float64 variable that stores the value of the flag.
+func Float64(names []string, value float64, usage string) *float64 {
+	return CommandLine.Float64(names, value, usage)
+}
+
+// DurationVar defines a time.Duration flag with specified name, default value, and usage string.
+// The argument p points to a time.Duration variable in which to store the value of the flag.
+func (fs *FlagSet) DurationVar(p *time.Duration, names []string, value time.Duration, usage string) {
+	fs.Var(newDurationValue(value, p), names, usage)
+}
+
+// DurationVar defines a time.Duration flag with specified name, default value, and usage string.
+// The argument p points to a time.Duration variable in which to store the value of the flag.
+func DurationVar(p *time.Duration, names []string, value time.Duration, usage string) {
+	CommandLine.Var(newDurationValue(value, p), names, usage)
+}
+
+// Duration defines a time.Duration flag with specified name, default value, and usage string.
+// The return value is the address of a time.Duration variable that stores the value of the flag.
+func (fs *FlagSet) Duration(names []string, value time.Duration, usage string) *time.Duration {
+	p := new(time.Duration)
+	fs.DurationVar(p, names, value, usage)
+	return p
+}
+
+// Duration defines a time.Duration flag with specified name, default value, and usage string.
+// The return value is the address of a time.Duration variable that stores the value of the flag.
+func Duration(names []string, value time.Duration, usage string) *time.Duration {
+	return CommandLine.Duration(names, value, usage)
+}
+
+// Var defines a flag with the specified name and usage string. The type and
+// value of the flag are represented by the first argument, of type Value, which
+// typically holds a user-defined implementation of Value. For instance, the
+// caller could create a flag that turns a comma-separated string into a slice
+// of strings by giving the slice the methods of Value; in particular, Set would
+// decompose the comma-separated string into the slice.
+func (fs *FlagSet) Var(value Value, names []string, usage string) {
+	// Remember the default value as a string; it won't change.
+	flag := &Flag{names, usage, value, value.String()}
+	for _, name := range names {
+		name = strings.TrimPrefix(name, "#")
+		_, alreadythere := fs.formal[name]
+		if alreadythere {
+			var msg string
+			if fs.name == "" {
+				msg = fmt.Sprintf("flag redefined: %s", name)
+			} else {
+				msg = fmt.Sprintf("%s flag redefined: %s", fs.name, name)
+			}
+			fmt.Fprintln(fs.Out(), msg)
+			panic(msg) // Happens only if flags are declared with identical names
+		}
+		if fs.formal == nil {
+			fs.formal = make(map[string]*Flag)
+		}
+		fs.formal[name] = flag
+	}
+}
+
+// Var defines a flag with the specified name and usage string. The type and
+// value of the flag are represented by the first argument, of type Value, which
+// typically holds a user-defined implementation of Value. For instance, the
+// caller could create a flag that turns a comma-separated string into a slice
+// of strings by giving the slice the methods of Value; in particular, Set would
+// decompose the comma-separated string into the slice.
+func Var(value Value, names []string, usage string) {
+	CommandLine.Var(value, names, usage)
+}
+
+// failf prints to standard error a formatted error and usage message and
+// returns the error.
+func (fs *FlagSet) failf(format string, a ...interface{}) error {
+	err := fmt.Errorf(format, a...)
+	fmt.Fprintln(fs.Out(), err)
+	if os.Args[0] == fs.name {
+		fmt.Fprintf(fs.Out(), "See '%s --help'.\n", os.Args[0])
+	} else {
+		fmt.Fprintf(fs.Out(), "See '%s %s --help'.\n", os.Args[0], fs.name)
+	}
+	return err
+}
+
+// usage calls the Usage method for the flag set, or the usage function if
+// the flag set is CommandLine.
+func (fs *FlagSet) usage() {
+	if fs == CommandLine {
+		Usage()
+	} else if fs.Usage == nil {
+		defaultUsage(fs)
+	} else {
+		fs.Usage()
+	}
+}
+
+func trimQuotes(str string) string {
+	if len(str) == 0 {
+		return str
+	}
+	type quote struct {
+		start, end byte
+	}
+
+	// All valid quote types.
+	quotes := []quote{
+		// Double quotes
+		{
+			start: '"',
+			end:   '"',
+		},
+
+		// Single quotes
+		{
+			start: '\'',
+			end:   '\'',
+		},
+	}
+
+	for _, quote := range quotes {
+		// Only strip if outermost match.
+		if str[0] == quote.start && str[len(str)-1] == quote.end {
+			str = str[1 : len(str)-1]
+			break
+		}
+	}
+
+	return str
+}
+
+// parseOne parses one flag. It reports whether a flag was seen.
+func (fs *FlagSet) parseOne() (bool, string, error) {
+	if len(fs.args) == 0 {
+		return false, "", nil
+	}
+	s := fs.args[0]
+	if len(s) == 0 || s[0] != '-' || len(s) == 1 {
+		return false, "", nil
+	}
+	if s[1] == '-' && len(s) == 2 { // "--" terminates the flags
+		fs.args = fs.args[1:]
+		return false, "", nil
+	}
+	name := s[1:]
+	if len(name) == 0 || name[0] == '=' {
+		return false, "", fs.failf("bad flag syntax: %s", s)
+	}
+
+	// it's a flag. does it have an argument?
+	fs.args = fs.args[1:]
+	hasValue := false
+	value := ""
+	if i := strings.Index(name, "="); i != -1 {
+		value = trimQuotes(name[i+1:])
+		hasValue = true
+		name = name[:i]
+	}
+
+	m := fs.formal
+	flag, alreadythere := m[name] // BUG
+	if !alreadythere {
+		if name == "-help" || name == "help" || name == "h" { // special case for nice help message.
+			fs.usage()
+			return false, "", ErrHelp
+		}
+		if len(name) > 0 && name[0] == '-' {
+			return false, "", fs.failf("flag provided but not defined: -%s", name)
+		}
+		return false, name, ErrRetry
+	}
+	if fv, ok := flag.Value.(boolFlag); ok && fv.IsBoolFlag() { // special case: doesn't need an arg
+		if hasValue {
+			if err := fv.Set(value); err != nil {
+				return false, "", fs.failf("invalid boolean value %q for  -%s: %v", value, name, err)
+			}
+		} else {
+			fv.Set("true")
+		}
+	} else {
+		// It must have a value, which might be the next argument.
+		if !hasValue && len(fs.args) > 0 {
+			// value is the next arg
+			hasValue = true
+			value, fs.args = fs.args[0], fs.args[1:]
+		}
+		if !hasValue {
+			return false, "", fs.failf("flag needs an argument: -%s", name)
+		}
+		if err := flag.Value.Set(value); err != nil {
+			return false, "", fs.failf("invalid value %q for flag -%s: %v", value, name, err)
+		}
+	}
+	if fs.actual == nil {
+		fs.actual = make(map[string]*Flag)
+	}
+	fs.actual[name] = flag
+	for i, n := range flag.Names {
+		if n == fmt.Sprintf("#%s", name) {
+			replacement := ""
+			for j := i; j < len(flag.Names); j++ {
+				if flag.Names[j][0] != '#' {
+					replacement = flag.Names[j]
+					break
+				}
+			}
+			if replacement != "" {
+				fmt.Fprintf(fs.Out(), "Warning: '-%s' is deprecated, it will be replaced by '-%s' soon. See usage.\n", name, replacement)
+			} else {
+				fmt.Fprintf(fs.Out(), "Warning: '-%s' is deprecated, it will be removed soon. See usage.\n", name)
+			}
+		}
+	}
+	return true, "", nil
+}
+
+// Parse parses flag definitions from the argument list, which should not
+// include the command name.  Must be called after all flags in the FlagSet
+// are defined and before flags are accessed by the program.
+// The return value will be ErrHelp if -help was set but not defined.
+func (fs *FlagSet) Parse(arguments []string) error {
+	fs.parsed = true
+	fs.args = arguments
+	for {
+		seen, name, err := fs.parseOne()
+		if seen {
+			continue
+		}
+		if err == nil {
+			break
+		}
+		if err == ErrRetry {
+			if len(name) > 1 {
+				err = nil
+				for _, letter := range strings.Split(name, "") {
+					fs.args = append([]string{"-" + letter}, fs.args...)
+					seen2, _, err2 := fs.parseOne()
+					if seen2 {
+						continue
+					}
+					if err2 != nil {
+						err = fs.failf("flag provided but not defined: -%s", name)
+						break
+					}
+				}
+				if err == nil {
+					continue
+				}
+			} else {
+				err = fs.failf("flag provided but not defined: -%s", name)
+			}
+		}
+		switch fs.errorHandling {
+		case ContinueOnError:
+			return err
+		case ExitOnError:
+			os.Exit(125)
+		case PanicOnError:
+			panic(err)
+		}
+	}
+	return nil
+}
+
+// ParseFlags is a utility function that adds a help flag if withHelp is true,
+// calls fs.Parse(args) and prints a relevant error message if there are
+// incorrect number of arguments. It returns error only if error handling is
+// set to ContinueOnError and parsing fails. If error handling is set to
+// ExitOnError, it's safe to ignore the return value.
+func (fs *FlagSet) ParseFlags(args []string, withHelp bool) error {
+	var help *bool
+	if withHelp {
+		help = fs.Bool([]string{"#help", "-help"}, false, "Print usage")
+	}
+	if err := fs.Parse(args); err != nil {
+		return err
+	}
+	if help != nil && *help {
+		fs.SetOutput(os.Stdout)
+		fs.Usage()
+		os.Exit(0)
+	}
+	if str := fs.CheckArgs(); str != "" {
+		fs.SetOutput(os.Stderr)
+		fs.ReportError(str, withHelp)
+		fs.ShortUsage()
+		os.Exit(1)
+	}
+	return nil
+}
+
+// ReportError is a utility method that prints a user-friendly message
+// containing the error that occurred during parsing and a suggestion to get help
+func (fs *FlagSet) ReportError(str string, withHelp bool) {
+	if withHelp {
+		if os.Args[0] == fs.Name() {
+			str += ".\nSee '" + os.Args[0] + " --help'"
+		} else {
+			str += ".\nSee '" + os.Args[0] + " " + fs.Name() + " --help'"
+		}
+	}
+	fmt.Fprintf(fs.Out(), "%s: %s.\n", os.Args[0], str)
+}
+
+// Parsed reports whether fs.Parse has been called.
+func (fs *FlagSet) Parsed() bool {
+	return fs.parsed
+}
+
+// Parse parses the command-line flags from os.Args[1:].  Must be called
+// after all flags are defined and before flags are accessed by the program.
+func Parse() {
+	// Ignore errors; CommandLine is set for ExitOnError.
+	CommandLine.Parse(os.Args[1:])
+}
+
+// Parsed returns true if the command-line flags have been parsed.
+func Parsed() bool {
+	return CommandLine.Parsed()
+}
+
+// CommandLine is the default set of command-line flags, parsed from os.Args.
+// The top-level functions such as BoolVar, Arg, and on are wrappers for the
+// methods of CommandLine.
+var CommandLine = NewFlagSet(os.Args[0], ExitOnError)
+
+// NewFlagSet returns a new, empty flag set with the specified name and
+// error handling property.
+func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {
+	f := &FlagSet{
+		name:          name,
+		errorHandling: errorHandling,
+	}
+	return f
+}
+
+// Init sets the name and error handling property for a flag set.
+// By default, the zero FlagSet uses an empty name and the
+// ContinueOnError error handling policy.
+func (fs *FlagSet) Init(name string, errorHandling ErrorHandling) {
+	fs.name = name
+	fs.errorHandling = errorHandling
+}
+
+type mergeVal struct {
+	Value
+	key  string
+	fset *FlagSet
+}
+
+func (v mergeVal) Set(s string) error {
+	return v.fset.Set(v.key, s)
+}
+
+func (v mergeVal) IsBoolFlag() bool {
+	if b, ok := v.Value.(boolFlag); ok {
+		return b.IsBoolFlag()
+	}
+	return false
+}
+
+// Name returns the name of a mergeVal.
+// If the original value had a name, return the original name,
+// otherwise, return the key asinged to this mergeVal.
+func (v mergeVal) Name() string {
+	type namedValue interface {
+		Name() string
+	}
+	if nVal, ok := v.Value.(namedValue); ok {
+		return nVal.Name()
+	}
+	return v.key
+}
+
+// Merge is an helper function that merges n FlagSets into a single dest FlagSet
+// In case of name collision between the flagsets it will apply
+// the destination FlagSet's errorHandling behavior.
+func Merge(dest *FlagSet, flagsets ...*FlagSet) error {
+	for _, fset := range flagsets {
+		if fset.formal == nil {
+			continue
+		}
+		for k, f := range fset.formal {
+			if _, ok := dest.formal[k]; ok {
+				var err error
+				if fset.name == "" {
+					err = fmt.Errorf("flag redefined: %s", k)
+				} else {
+					err = fmt.Errorf("%s flag redefined: %s", fset.name, k)
+				}
+				fmt.Fprintln(fset.Out(), err.Error())
+				// Happens only if flags are declared with identical names
+				switch dest.errorHandling {
+				case ContinueOnError:
+					return err
+				case ExitOnError:
+					os.Exit(2)
+				case PanicOnError:
+					panic(err)
+				}
+			}
+			newF := *f
+			newF.Value = mergeVal{f.Value, k, fset}
+			if dest.formal == nil {
+				dest.formal = make(map[string]*Flag)
+			}
+			dest.formal[k] = &newF
+		}
+	}
+	return nil
+}
+
+// IsEmpty reports if the FlagSet is actually empty.
+func (fs *FlagSet) IsEmpty() bool {
+	return len(fs.actual) == 0
+}

+ 529 - 0
libnetwork/client/mflag/flag_test.go

@@ -0,0 +1,529 @@
+// Copyright 2014-2016 The Docker & Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package mflag
+
+import (
+	"bytes"
+	"fmt"
+	"os"
+	"sort"
+	"strings"
+	"testing"
+	"time"
+
+	_ "github.com/docker/libnetwork/testutils"
+)
+
+// ResetForTesting clears all flag state and sets the usage function as directed.
+// After calling ResetForTesting, parse errors in flag handling will not
+// exit the program.
+func ResetForTesting(usage func()) {
+	CommandLine = NewFlagSet(os.Args[0], ContinueOnError)
+	Usage = usage
+}
+func boolString(s string) string {
+	if s == "0" {
+		return "false"
+	}
+	return "true"
+}
+
+func TestEverything(t *testing.T) {
+	ResetForTesting(nil)
+	Bool([]string{"test_bool"}, false, "bool value")
+	Int([]string{"test_int"}, 0, "int value")
+	Int64([]string{"test_int64"}, 0, "int64 value")
+	Uint([]string{"test_uint"}, 0, "uint value")
+	Uint64([]string{"test_uint64"}, 0, "uint64 value")
+	String([]string{"test_string"}, "0", "string value")
+	Float64([]string{"test_float64"}, 0, "float64 value")
+	Duration([]string{"test_duration"}, 0, "time.Duration value")
+
+	m := make(map[string]*Flag)
+	desired := "0"
+	visitor := func(f *Flag) {
+		for _, name := range f.Names {
+			if len(name) > 5 && name[0:5] == "test_" {
+				m[name] = f
+				ok := false
+				switch {
+				case f.Value.String() == desired:
+					ok = true
+				case name == "test_bool" && f.Value.String() == boolString(desired):
+					ok = true
+				case name == "test_duration" && f.Value.String() == desired+"s":
+					ok = true
+				}
+				if !ok {
+					t.Error("Visit: bad value", f.Value.String(), "for", name)
+				}
+			}
+		}
+	}
+	VisitAll(visitor)
+	if len(m) != 8 {
+		t.Error("VisitAll misses some flags")
+		for k, v := range m {
+			t.Log(k, *v)
+		}
+	}
+	m = make(map[string]*Flag)
+	Visit(visitor)
+	if len(m) != 0 {
+		t.Errorf("Visit sees unset flags")
+		for k, v := range m {
+			t.Log(k, *v)
+		}
+	}
+	// Now set all flags
+	Set("test_bool", "true")
+	Set("test_int", "1")
+	Set("test_int64", "1")
+	Set("test_uint", "1")
+	Set("test_uint64", "1")
+	Set("test_string", "1")
+	Set("test_float64", "1")
+	Set("test_duration", "1s")
+	desired = "1"
+	Visit(visitor)
+	if len(m) != 8 {
+		t.Error("Visit fails after set")
+		for k, v := range m {
+			t.Log(k, *v)
+		}
+	}
+	// Now test they're visited in sort order.
+	var flagNames []string
+	Visit(func(f *Flag) {
+		for _, name := range f.Names {
+			flagNames = append(flagNames, name)
+		}
+	})
+	if !sort.StringsAreSorted(flagNames) {
+		t.Errorf("flag names not sorted: %v", flagNames)
+	}
+}
+
+func TestGet(t *testing.T) {
+	ResetForTesting(nil)
+	Bool([]string{"test_bool"}, true, "bool value")
+	Int([]string{"test_int"}, 1, "int value")
+	Int64([]string{"test_int64"}, 2, "int64 value")
+	Uint([]string{"test_uint"}, 3, "uint value")
+	Uint64([]string{"test_uint64"}, 4, "uint64 value")
+	String([]string{"test_string"}, "5", "string value")
+	Float64([]string{"test_float64"}, 6, "float64 value")
+	Duration([]string{"test_duration"}, 7, "time.Duration value")
+
+	visitor := func(f *Flag) {
+		for _, name := range f.Names {
+			if len(name) > 5 && name[0:5] == "test_" {
+				g, ok := f.Value.(Getter)
+				if !ok {
+					t.Errorf("Visit: value does not satisfy Getter: %T", f.Value)
+					return
+				}
+				switch name {
+				case "test_bool":
+					ok = g.Get() == true
+				case "test_int":
+					ok = g.Get() == int(1)
+				case "test_int64":
+					ok = g.Get() == int64(2)
+				case "test_uint":
+					ok = g.Get() == uint(3)
+				case "test_uint64":
+					ok = g.Get() == uint64(4)
+				case "test_string":
+					ok = g.Get() == "5"
+				case "test_float64":
+					ok = g.Get() == float64(6)
+				case "test_duration":
+					ok = g.Get() == time.Duration(7)
+				}
+				if !ok {
+					t.Errorf("Visit: bad value %T(%v) for %s", g.Get(), g.Get(), name)
+				}
+			}
+		}
+	}
+	VisitAll(visitor)
+}
+
+func testParse(f *FlagSet, t *testing.T) {
+	if f.Parsed() {
+		t.Error("f.Parse() = true before Parse")
+	}
+	boolFlag := f.Bool([]string{"bool"}, false, "bool value")
+	bool2Flag := f.Bool([]string{"bool2"}, false, "bool2 value")
+	f.Bool([]string{"bool3"}, false, "bool3 value")
+	bool4Flag := f.Bool([]string{"bool4"}, false, "bool4 value")
+	intFlag := f.Int([]string{"-int"}, 0, "int value")
+	int64Flag := f.Int64([]string{"-int64"}, 0, "int64 value")
+	uintFlag := f.Uint([]string{"uint"}, 0, "uint value")
+	uint64Flag := f.Uint64([]string{"-uint64"}, 0, "uint64 value")
+	stringFlag := f.String([]string{"string"}, "0", "string value")
+	f.String([]string{"string2"}, "0", "string2 value")
+	singleQuoteFlag := f.String([]string{"squote"}, "", "single quoted value")
+	doubleQuoteFlag := f.String([]string{"dquote"}, "", "double quoted value")
+	mixedQuoteFlag := f.String([]string{"mquote"}, "", "mixed quoted value")
+	mixed2QuoteFlag := f.String([]string{"mquote2"}, "", "mixed2 quoted value")
+	nestedQuoteFlag := f.String([]string{"nquote"}, "", "nested quoted value")
+	nested2QuoteFlag := f.String([]string{"nquote2"}, "", "nested2 quoted value")
+	float64Flag := f.Float64([]string{"float64"}, 0, "float64 value")
+	durationFlag := f.Duration([]string{"duration"}, 5*time.Second, "time.Duration value")
+	extra := "one-extra-argument"
+	args := []string{
+		"-bool",
+		"-bool2=true",
+		"-bool4=false",
+		"--int", "22",
+		"--int64", "0x23",
+		"-uint", "24",
+		"--uint64", "25",
+		"-string", "hello",
+		"-squote='single'",
+		`-dquote="double"`,
+		`-mquote='mixed"`,
+		`-mquote2="mixed2'`,
+		`-nquote="'single nested'"`,
+		`-nquote2='"double nested"'`,
+		"-float64", "2718e28",
+		"-duration", "2m",
+		extra,
+	}
+	if err := f.Parse(args); err != nil {
+		t.Fatal(err)
+	}
+	if !f.Parsed() {
+		t.Error("f.Parse() = false after Parse")
+	}
+	if *boolFlag != true {
+		t.Error("bool flag should be true, is ", *boolFlag)
+	}
+	if *bool2Flag != true {
+		t.Error("bool2 flag should be true, is ", *bool2Flag)
+	}
+	if !f.IsSet("bool2") {
+		t.Error("bool2 should be marked as set")
+	}
+	if f.IsSet("bool3") {
+		t.Error("bool3 should not be marked as set")
+	}
+	if !f.IsSet("bool4") {
+		t.Error("bool4 should be marked as set")
+	}
+	if *bool4Flag != false {
+		t.Error("bool4 flag should be false, is ", *bool4Flag)
+	}
+	if *intFlag != 22 {
+		t.Error("int flag should be 22, is ", *intFlag)
+	}
+	if *int64Flag != 0x23 {
+		t.Error("int64 flag should be 0x23, is ", *int64Flag)
+	}
+	if *uintFlag != 24 {
+		t.Error("uint flag should be 24, is ", *uintFlag)
+	}
+	if *uint64Flag != 25 {
+		t.Error("uint64 flag should be 25, is ", *uint64Flag)
+	}
+	if *stringFlag != "hello" {
+		t.Error("string flag should be `hello`, is ", *stringFlag)
+	}
+	if !f.IsSet("string") {
+		t.Error("string flag should be marked as set")
+	}
+	if f.IsSet("string2") {
+		t.Error("string2 flag should not be marked as set")
+	}
+	if *singleQuoteFlag != "single" {
+		t.Error("single quote string flag should be `single`, is ", *singleQuoteFlag)
+	}
+	if *doubleQuoteFlag != "double" {
+		t.Error("double quote string flag should be `double`, is ", *doubleQuoteFlag)
+	}
+	if *mixedQuoteFlag != `'mixed"` {
+		t.Error("mixed quote string flag should be `'mixed\"`, is ", *mixedQuoteFlag)
+	}
+	if *mixed2QuoteFlag != `"mixed2'` {
+		t.Error("mixed2 quote string flag should be `\"mixed2'`, is ", *mixed2QuoteFlag)
+	}
+	if *nestedQuoteFlag != "'single nested'" {
+		t.Error("nested quote string flag should be `'single nested'`, is ", *nestedQuoteFlag)
+	}
+	if *nested2QuoteFlag != `"double nested"` {
+		t.Error("double quote string flag should be `\"double nested\"`, is ", *nested2QuoteFlag)
+	}
+	if *float64Flag != 2718e28 {
+		t.Error("float64 flag should be 2718e28, is ", *float64Flag)
+	}
+	if *durationFlag != 2*time.Minute {
+		t.Error("duration flag should be 2m, is ", *durationFlag)
+	}
+	if len(f.Args()) != 1 {
+		t.Error("expected one argument, got", len(f.Args()))
+	} else if f.Args()[0] != extra {
+		t.Errorf("expected argument %q got %q", extra, f.Args()[0])
+	}
+}
+
+func testPanic(f *FlagSet, t *testing.T) {
+	f.Int([]string{"-int"}, 0, "int value")
+	if f.Parsed() {
+		t.Error("f.Parse() = true before Parse")
+	}
+	args := []string{
+		"-int", "21",
+	}
+	f.Parse(args)
+}
+
+func TestParsePanic(t *testing.T) {
+	ResetForTesting(func() {})
+	testPanic(CommandLine, t)
+}
+
+func TestParse(t *testing.T) {
+	ResetForTesting(func() { t.Error("bad parse") })
+	testParse(CommandLine, t)
+}
+
+func TestFlagSetParse(t *testing.T) {
+	testParse(NewFlagSet("test", ContinueOnError), t)
+}
+
+// Declare a user-defined flag type.
+type flagVar []string
+
+func (f *flagVar) String() string {
+	return fmt.Sprint([]string(*f))
+}
+
+func (f *flagVar) Set(value string) error {
+	*f = append(*f, value)
+	return nil
+}
+
+func TestUserDefined(t *testing.T) {
+	var flags FlagSet
+	flags.Init("test", ContinueOnError)
+	var v flagVar
+	flags.Var(&v, []string{"v"}, "usage")
+	if err := flags.Parse([]string{"-v", "1", "-v", "2", "-v=3"}); err != nil {
+		t.Error(err)
+	}
+	if len(v) != 3 {
+		t.Fatal("expected 3 args; got ", len(v))
+	}
+	expect := "[1 2 3]"
+	if v.String() != expect {
+		t.Errorf("expected value %q got %q", expect, v.String())
+	}
+}
+
+// Declare a user-defined boolean flag type.
+type boolFlagVar struct {
+	count int
+}
+
+func (b *boolFlagVar) String() string {
+	return fmt.Sprintf("%d", b.count)
+}
+
+func (b *boolFlagVar) Set(value string) error {
+	if value == "true" {
+		b.count++
+	}
+	return nil
+}
+
+func (b *boolFlagVar) IsBoolFlag() bool {
+	return b.count < 4
+}
+
+func TestUserDefinedBool(t *testing.T) {
+	var flags FlagSet
+	flags.Init("test", ContinueOnError)
+	var b boolFlagVar
+	var err error
+	flags.Var(&b, []string{"b"}, "usage")
+	if err = flags.Parse([]string{"-b", "-b", "-b", "-b=true", "-b=false", "-b", "barg", "-b"}); err != nil {
+		if b.count < 4 {
+			t.Error(err)
+		}
+	}
+
+	if b.count != 4 {
+		t.Errorf("want: %d; got: %d", 4, b.count)
+	}
+
+	if err == nil {
+		t.Error("expected error; got none")
+	}
+}
+
+func TestSetOutput(t *testing.T) {
+	var flags FlagSet
+	var buf bytes.Buffer
+	flags.SetOutput(&buf)
+	flags.Init("test", ContinueOnError)
+	flags.Parse([]string{"-unknown"})
+	if out := buf.String(); !strings.Contains(out, "-unknown") {
+		t.Logf("expected output mentioning unknown; got %q", out)
+	}
+}
+
+// This tests that one can reset the flags. This still works but not well, and is
+// superseded by FlagSet.
+func TestChangingArgs(t *testing.T) {
+	ResetForTesting(func() { t.Fatal("bad parse") })
+	oldArgs := os.Args
+	defer func() { os.Args = oldArgs }()
+	os.Args = []string{"cmd", "-before", "subcmd", "-after", "args"}
+	before := Bool([]string{"before"}, false, "")
+	if err := CommandLine.Parse(os.Args[1:]); err != nil {
+		t.Fatal(err)
+	}
+	cmd := Arg(0)
+	os.Args = Args()
+	after := Bool([]string{"after"}, false, "")
+	Parse()
+	args := Args()
+
+	if !*before || cmd != "subcmd" || !*after || len(args) != 1 || args[0] != "args" {
+		t.Fatalf("expected true subcmd true [args] got %v %v %v %v", *before, cmd, *after, args)
+	}
+}
+
+// Test that -help invokes the usage message and returns ErrHelp.
+func TestHelp(t *testing.T) {
+	var helpCalled = false
+	fs := NewFlagSet("help test", ContinueOnError)
+	fs.Usage = func() { helpCalled = true }
+	var flag bool
+	fs.BoolVar(&flag, []string{"flag"}, false, "regular flag")
+	// Regular flag invocation should work
+	err := fs.Parse([]string{"-flag=true"})
+	if err != nil {
+		t.Fatal("expected no error; got ", err)
+	}
+	if !flag {
+		t.Error("flag was not set by -flag")
+	}
+	if helpCalled {
+		t.Error("help called for regular flag")
+		helpCalled = false // reset for next test
+	}
+	// Help flag should work as expected.
+	err = fs.Parse([]string{"-help"})
+	if err == nil {
+		t.Fatal("error expected")
+	}
+	if err != ErrHelp {
+		t.Fatal("expected ErrHelp; got ", err)
+	}
+	if !helpCalled {
+		t.Fatal("help was not called")
+	}
+	// If we define a help flag, that should override.
+	var help bool
+	fs.BoolVar(&help, []string{"help"}, false, "help flag")
+	helpCalled = false
+	err = fs.Parse([]string{"-help"})
+	if err != nil {
+		t.Fatal("expected no error for defined -help; got ", err)
+	}
+	if helpCalled {
+		t.Fatal("help was called; should not have been for defined help flag")
+	}
+}
+
+// Test the flag count functions.
+func TestFlagCounts(t *testing.T) {
+	fs := NewFlagSet("help test", ContinueOnError)
+	var flag bool
+	fs.BoolVar(&flag, []string{"flag1"}, false, "regular flag")
+	fs.BoolVar(&flag, []string{"#deprecated1"}, false, "regular flag")
+	fs.BoolVar(&flag, []string{"f", "flag2"}, false, "regular flag")
+	fs.BoolVar(&flag, []string{"#d", "#deprecated2"}, false, "regular flag")
+	fs.BoolVar(&flag, []string{"flag3"}, false, "regular flag")
+	fs.BoolVar(&flag, []string{"g", "#flag4", "-flag4"}, false, "regular flag")
+
+	if fs.FlagCount() != 6 {
+		t.Fatal("FlagCount wrong. ", fs.FlagCount())
+	}
+	if fs.FlagCountUndeprecated() != 4 {
+		t.Fatal("FlagCountUndeprecated wrong. ", fs.FlagCountUndeprecated())
+	}
+	if fs.NFlag() != 0 {
+		t.Fatal("NFlag wrong. ", fs.NFlag())
+	}
+	err := fs.Parse([]string{"-fd", "-g", "-flag4"})
+	if err != nil {
+		t.Fatal("expected no error for defined -help; got ", err)
+	}
+	if fs.NFlag() != 4 {
+		t.Fatal("NFlag wrong. ", fs.NFlag())
+	}
+}
+
+// Show up bug in sortFlags
+func TestSortFlags(t *testing.T) {
+	fs := NewFlagSet("help TestSortFlags", ContinueOnError)
+
+	var err error
+
+	var b bool
+	fs.BoolVar(&b, []string{"b", "-banana"}, false, "usage")
+
+	err = fs.Parse([]string{"--banana=true"})
+	if err != nil {
+		t.Fatal("expected no error; got ", err)
+	}
+
+	count := 0
+
+	fs.VisitAll(func(flag *Flag) {
+		count++
+		if flag == nil {
+			t.Fatal("VisitAll should not return a nil flag")
+		}
+	})
+	flagcount := fs.FlagCount()
+	if flagcount != count {
+		t.Fatalf("FlagCount (%d) != number (%d) of elements visited", flagcount, count)
+	}
+	// Make sure its idempotent
+	if flagcount != fs.FlagCount() {
+		t.Fatalf("FlagCount (%d) != fs.FlagCount() (%d) of elements visited", flagcount, fs.FlagCount())
+	}
+
+	count = 0
+	fs.Visit(func(flag *Flag) {
+		count++
+		if flag == nil {
+			t.Fatal("Visit should not return a nil flag")
+		}
+	})
+	nflag := fs.NFlag()
+	if nflag != count {
+		t.Fatalf("NFlag (%d) != number (%d) of elements visited", nflag, count)
+	}
+	if nflag != fs.NFlag() {
+		t.Fatalf("NFlag (%d) != fs.NFlag() (%d) of elements visited", nflag, fs.NFlag())
+	}
+}
+
+func TestMergeFlags(t *testing.T) {
+	base := NewFlagSet("base", ContinueOnError)
+	base.String([]string{"f"}, "", "")
+
+	fs := NewFlagSet("test", ContinueOnError)
+	Merge(fs, base)
+	if len(fs.formal) != 1 {
+		t.Fatalf("FlagCount (%d) != number (1) of elements merged", len(fs.formal))
+	}
+}

+ 1 - 1
libnetwork/client/network.go

@@ -8,8 +8,8 @@ import (
 	"strings"
 	"text/tabwriter"
 
-	flag "github.com/docker/docker/pkg/mflag"
 	"github.com/docker/docker/pkg/stringid"
+	flag "github.com/docker/libnetwork/client/mflag"
 	"github.com/docker/libnetwork/netlabel"
 )
 

+ 1 - 1
libnetwork/client/service.go

@@ -9,8 +9,8 @@ import (
 	"text/tabwriter"
 
 	"github.com/docker/docker/opts"
-	flag "github.com/docker/docker/pkg/mflag"
 	"github.com/docker/docker/pkg/stringid"
+	flag "github.com/docker/libnetwork/client/mflag"
 	"github.com/docker/libnetwork/netutils"
 )