github.com/ld86/docker@v1.7.1-rc3/builder/bflag.go (about)

     1  package builder
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  )
     7  
     8  type FlagType int
     9  
    10  const (
    11  	boolType FlagType = iota
    12  	stringType
    13  )
    14  
    15  type BuilderFlags struct {
    16  	Args  []string // actual flags/args from cmd line
    17  	flags map[string]*Flag
    18  	used  map[string]*Flag
    19  	Err   error
    20  }
    21  
    22  type Flag struct {
    23  	bf       *BuilderFlags
    24  	name     string
    25  	flagType FlagType
    26  	Value    string
    27  }
    28  
    29  func NewBuilderFlags() *BuilderFlags {
    30  	return &BuilderFlags{
    31  		flags: make(map[string]*Flag),
    32  		used:  make(map[string]*Flag),
    33  	}
    34  }
    35  
    36  func (bf *BuilderFlags) AddBool(name string, def bool) *Flag {
    37  	flag := bf.addFlag(name, boolType)
    38  	if flag == nil {
    39  		return nil
    40  	}
    41  	if def {
    42  		flag.Value = "true"
    43  	} else {
    44  		flag.Value = "false"
    45  	}
    46  	return flag
    47  }
    48  
    49  func (bf *BuilderFlags) AddString(name string, def string) *Flag {
    50  	flag := bf.addFlag(name, stringType)
    51  	if flag == nil {
    52  		return nil
    53  	}
    54  	flag.Value = def
    55  	return flag
    56  }
    57  
    58  func (bf *BuilderFlags) addFlag(name string, flagType FlagType) *Flag {
    59  	if _, ok := bf.flags[name]; ok {
    60  		bf.Err = fmt.Errorf("Duplicate flag defined: %s", name)
    61  		return nil
    62  	}
    63  
    64  	newFlag := &Flag{
    65  		bf:       bf,
    66  		name:     name,
    67  		flagType: flagType,
    68  	}
    69  	bf.flags[name] = newFlag
    70  
    71  	return newFlag
    72  }
    73  
    74  func (fl *Flag) IsUsed() bool {
    75  	if _, ok := fl.bf.used[fl.name]; ok {
    76  		return true
    77  	}
    78  	return false
    79  }
    80  
    81  func (fl *Flag) IsTrue() bool {
    82  	if fl.flagType != boolType {
    83  		// Should never get here
    84  		panic(fmt.Errorf("Trying to use IsTrue on a non-boolean: %s", fl.name))
    85  	}
    86  	return fl.Value == "true"
    87  }
    88  
    89  func (bf *BuilderFlags) Parse() error {
    90  	// If there was an error while defining the possible flags
    91  	// go ahead and bubble it back up here since we didn't do it
    92  	// earlier in the processing
    93  	if bf.Err != nil {
    94  		return fmt.Errorf("Error setting up flags: %s", bf.Err)
    95  	}
    96  
    97  	for _, arg := range bf.Args {
    98  		if !strings.HasPrefix(arg, "--") {
    99  			return fmt.Errorf("Arg should start with -- : %s", arg)
   100  		}
   101  
   102  		if arg == "--" {
   103  			return nil
   104  		}
   105  
   106  		arg = arg[2:]
   107  		value := ""
   108  
   109  		index := strings.Index(arg, "=")
   110  		if index >= 0 {
   111  			value = arg[index+1:]
   112  			arg = arg[:index]
   113  		}
   114  
   115  		flag, ok := bf.flags[arg]
   116  		if !ok {
   117  			return fmt.Errorf("Unknown flag: %s", arg)
   118  		}
   119  
   120  		if _, ok = bf.used[arg]; ok {
   121  			return fmt.Errorf("Duplicate flag specified: %s", arg)
   122  		}
   123  
   124  		bf.used[arg] = flag
   125  
   126  		switch flag.flagType {
   127  		case boolType:
   128  			// value == "" is only ok if no "=" was specified
   129  			if index >= 0 && value == "" {
   130  				return fmt.Errorf("Missing a value on flag: %s", arg)
   131  			}
   132  
   133  			lower := strings.ToLower(value)
   134  			if lower == "" {
   135  				flag.Value = "true"
   136  			} else if lower == "true" || lower == "false" {
   137  				flag.Value = lower
   138  			} else {
   139  				return fmt.Errorf("Expecting boolean value for flag %s, not: %s", arg, value)
   140  			}
   141  
   142  		case stringType:
   143  			if index < 0 {
   144  				return fmt.Errorf("Missing a value on flag: %s", arg)
   145  			}
   146  			flag.Value = value
   147  
   148  		default:
   149  			panic(fmt.Errorf("No idea what kind of flag we have! Should never get here!"))
   150  		}
   151  
   152  	}
   153  
   154  	return nil
   155  }