mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
a8e871b0bb
This adds support for Dockerfile commands to have options - e.g: COPY --user=john foo /tmp/ COPY --ignore-mtime foo /tmp/ Supports both booleans and strings. Signed-off-by: Doug Davis <dug@us.ibm.com>
155 lines
2.9 KiB
Go
155 lines
2.9 KiB
Go
package builder
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
type FlagType int
|
|
|
|
const (
|
|
boolType FlagType = iota
|
|
stringType
|
|
)
|
|
|
|
type BuilderFlags struct {
|
|
Args []string // actual flags/args from cmd line
|
|
flags map[string]*Flag
|
|
used map[string]*Flag
|
|
Err error
|
|
}
|
|
|
|
type Flag struct {
|
|
bf *BuilderFlags
|
|
name string
|
|
flagType FlagType
|
|
Value string
|
|
}
|
|
|
|
func NewBuilderFlags() *BuilderFlags {
|
|
return &BuilderFlags{
|
|
flags: make(map[string]*Flag),
|
|
used: make(map[string]*Flag),
|
|
}
|
|
}
|
|
|
|
func (bf *BuilderFlags) 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
|
|
}
|
|
|
|
func (bf *BuilderFlags) AddString(name string, def string) *Flag {
|
|
flag := bf.addFlag(name, stringType)
|
|
if flag == nil {
|
|
return nil
|
|
}
|
|
flag.Value = def
|
|
return flag
|
|
}
|
|
|
|
func (bf *BuilderFlags) 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
|
|
}
|
|
|
|
func (fl *Flag) IsUsed() bool {
|
|
if _, ok := fl.bf.used[fl.name]; ok {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
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"
|
|
}
|
|
|
|
func (bf *BuilderFlags) 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
|
|
}
|