github.com/lazyboychen7/engine@v17.12.1-ce-rc2+incompatible/builder/dockerfile/instructions/bflag.go (about) 1 package instructions 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 returns 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 // NewBFlagsWithArgs returns the new BFlags struct with Args set to args 41 func NewBFlagsWithArgs(args []string) *BFlags { 42 flags := NewBFlags() 43 flags.Args = args 44 return flags 45 } 46 47 // AddBool adds a bool flag to BFlags 48 // Note, any error will be generated when Parse() is called (see Parse). 49 func (bf *BFlags) AddBool(name string, def bool) *Flag { 50 flag := bf.addFlag(name, boolType) 51 if flag == nil { 52 return nil 53 } 54 if def { 55 flag.Value = "true" 56 } else { 57 flag.Value = "false" 58 } 59 return flag 60 } 61 62 // AddString adds a string flag to BFlags 63 // Note, any error will be generated when Parse() is called (see Parse). 64 func (bf *BFlags) AddString(name string, def string) *Flag { 65 flag := bf.addFlag(name, stringType) 66 if flag == nil { 67 return nil 68 } 69 flag.Value = def 70 return flag 71 } 72 73 // addFlag is a generic func used by the other AddXXX() func 74 // to add a new flag to the BFlags struct. 75 // Note, any error will be generated when Parse() is called (see Parse). 76 func (bf *BFlags) addFlag(name string, flagType FlagType) *Flag { 77 if _, ok := bf.flags[name]; ok { 78 bf.Err = fmt.Errorf("Duplicate flag defined: %s", name) 79 return nil 80 } 81 82 newFlag := &Flag{ 83 bf: bf, 84 name: name, 85 flagType: flagType, 86 } 87 bf.flags[name] = newFlag 88 89 return newFlag 90 } 91 92 // IsUsed checks if the flag is used 93 func (fl *Flag) IsUsed() bool { 94 if _, ok := fl.bf.used[fl.name]; ok { 95 return true 96 } 97 return false 98 } 99 100 // IsTrue checks if a bool flag is true 101 func (fl *Flag) IsTrue() bool { 102 if fl.flagType != boolType { 103 // Should never get here 104 panic(fmt.Errorf("Trying to use IsTrue on a non-boolean: %s", fl.name)) 105 } 106 return fl.Value == "true" 107 } 108 109 // Parse parses and checks if the BFlags is valid. 110 // Any error noticed during the AddXXX() funcs will be generated/returned 111 // here. We do this because an error during AddXXX() is more like a 112 // compile time error so it doesn't matter too much when we stop our 113 // processing as long as we do stop it, so this allows the code 114 // around AddXXX() to be just: 115 // defFlag := AddString("description", "") 116 // w/o needing to add an if-statement around each one. 117 func (bf *BFlags) Parse() error { 118 // If there was an error while defining the possible flags 119 // go ahead and bubble it back up here since we didn't do it 120 // earlier in the processing 121 if bf.Err != nil { 122 return fmt.Errorf("Error setting up flags: %s", bf.Err) 123 } 124 125 for _, arg := range bf.Args { 126 if !strings.HasPrefix(arg, "--") { 127 return fmt.Errorf("Arg should start with -- : %s", arg) 128 } 129 130 if arg == "--" { 131 return nil 132 } 133 134 arg = arg[2:] 135 value := "" 136 137 index := strings.Index(arg, "=") 138 if index >= 0 { 139 value = arg[index+1:] 140 arg = arg[:index] 141 } 142 143 flag, ok := bf.flags[arg] 144 if !ok { 145 return fmt.Errorf("Unknown flag: %s", arg) 146 } 147 148 if _, ok = bf.used[arg]; ok { 149 return fmt.Errorf("Duplicate flag specified: %s", arg) 150 } 151 152 bf.used[arg] = flag 153 154 switch flag.flagType { 155 case boolType: 156 // value == "" is only ok if no "=" was specified 157 if index >= 0 && value == "" { 158 return fmt.Errorf("Missing a value on flag: %s", arg) 159 } 160 161 lower := strings.ToLower(value) 162 if lower == "" { 163 flag.Value = "true" 164 } else if lower == "true" || lower == "false" { 165 flag.Value = lower 166 } else { 167 return fmt.Errorf("Expecting boolean value for flag %s, not: %s", arg, value) 168 } 169 170 case stringType: 171 if index < 0 { 172 return fmt.Errorf("Missing a value on flag: %s", arg) 173 } 174 flag.Value = value 175 176 default: 177 panic("No idea what kind of flag we have! Should never get here!") 178 } 179 180 } 181 182 return nil 183 }