123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- package dockerfile
- import (
- "fmt"
- "strings"
- )
- // FlagType is the type of the build flag
- type FlagType int
- const (
- boolType FlagType = iota
- stringType
- )
- // BFlags contains all flags information for the builder
- type BFlags struct {
- Args []string // actual flags/args from cmd line
- flags map[string]*Flag
- used map[string]*Flag
- Err error
- }
- // Flag contains all information for a flag
- type Flag struct {
- bf *BFlags
- name string
- flagType FlagType
- Value string
- }
- // NewBFlags return the new BFlags struct
- func NewBFlags() *BFlags {
- return &BFlags{
- flags: make(map[string]*Flag),
- used: make(map[string]*Flag),
- }
- }
- // AddBool adds a bool flag to BFlags
- // Note, any error will be generated when Parse() is called (see Parse).
- func (bf *BFlags) AddBool(name string, def bool) *Flag {
- flag := bf.addFlag(name, boolType)
- if flag == nil {
- return nil
- }
- if def {
- flag.Value = "true"
- } else {
- flag.Value = "false"
- }
- return flag
- }
- // AddString adds a string flag to BFlags
- // Note, any error will be generated when Parse() is called (see Parse).
- func (bf *BFlags) AddString(name string, def string) *Flag {
- flag := bf.addFlag(name, stringType)
- if flag == nil {
- return nil
- }
- flag.Value = def
- return flag
- }
- // addFlag is a generic func used by the other AddXXX() func
- // to add a new flag to the BFlags struct.
- // Note, any error will be generated when Parse() is called (see Parse).
- func (bf *BFlags) addFlag(name string, flagType FlagType) *Flag {
- if _, ok := bf.flags[name]; ok {
- bf.Err = fmt.Errorf("Duplicate flag defined: %s", name)
- return nil
- }
- newFlag := &Flag{
- bf: bf,
- name: name,
- flagType: flagType,
- }
- bf.flags[name] = newFlag
- return newFlag
- }
- // IsUsed checks if the flag is used
- func (fl *Flag) IsUsed() bool {
- if _, ok := fl.bf.used[fl.name]; ok {
- return true
- }
- return false
- }
- // IsTrue checks if a bool flag is true
- func (fl *Flag) IsTrue() bool {
- if fl.flagType != boolType {
- // Should never get here
- panic(fmt.Errorf("Trying to use IsTrue on a non-boolean: %s", fl.name))
- }
- return fl.Value == "true"
- }
- // Parse parses and checks if the BFlags is valid.
- // Any error noticed during the AddXXX() funcs will be generated/returned
- // here. We do this because an error during AddXXX() is more like a
- // compile time error so it doesn't matter too much when we stop our
- // processing as long as we do stop it, so this allows the code
- // around AddXXX() to be just:
- // defFlag := AddString("description", "")
- // w/o needing to add an if-statement around each one.
- func (bf *BFlags) Parse() error {
- // If there was an error while defining the possible flags
- // go ahead and bubble it back up here since we didn't do it
- // earlier in the processing
- if bf.Err != nil {
- return fmt.Errorf("Error setting up flags: %s", bf.Err)
- }
- for _, arg := range bf.Args {
- if !strings.HasPrefix(arg, "--") {
- return fmt.Errorf("Arg should start with -- : %s", arg)
- }
- if arg == "--" {
- return nil
- }
- arg = arg[2:]
- value := ""
- index := strings.Index(arg, "=")
- if index >= 0 {
- value = arg[index+1:]
- arg = arg[:index]
- }
- flag, ok := bf.flags[arg]
- if !ok {
- return fmt.Errorf("Unknown flag: %s", arg)
- }
- if _, ok = bf.used[arg]; ok {
- return fmt.Errorf("Duplicate flag specified: %s", arg)
- }
- bf.used[arg] = flag
- switch flag.flagType {
- case boolType:
- // value == "" is only ok if no "=" was specified
- if index >= 0 && value == "" {
- return fmt.Errorf("Missing a value on flag: %s", arg)
- }
- lower := strings.ToLower(value)
- if lower == "" {
- flag.Value = "true"
- } else if lower == "true" || lower == "false" {
- flag.Value = lower
- } else {
- return fmt.Errorf("Expecting boolean value for flag %s, not: %s", arg, value)
- }
- case stringType:
- if index < 0 {
- return fmt.Errorf("Missing a value on flag: %s", arg)
- }
- flag.Value = value
- default:
- panic(fmt.Errorf("No idea what kind of flag we have! Should never get here!"))
- }
- }
- return nil
- }
|