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