summaryrefslogtreecommitdiff
path: root/vendor/github.com/pborman/getopt/v2/option.go
diff options
context:
space:
mode:
authorDan Duvall <dduvall@wikimedia.org>2018-03-06 20:31:58 -0800
committerDan Duvall <dduvall@wikimedia.org>2018-03-19 15:55:16 -0700
commiteb9b69dd3d710cb7afa1dfb6e23a5987842b21cc (patch)
tree049b11cc885e4e9f54aac8981c91a1bf3620e7af /vendor/github.com/pborman/getopt/v2/option.go
parent6896e655eb5cc88b90e66979bc2d862eb92cbb9f (diff)
downloadblubber-eb9b69dd3d710cb7afa1dfb6e23a5987842b21cc.tar.gz
Allow for configuration policies
Summary: Implements a rough interface for validating configuration against arbitrary policy rules. Policies are provided as YAML and passed via the command line as file paths or remote URIs. The format of policies is: enforcements: - path: <path> rule: <rule> Where `<path>` is a YAML-ish path to a config field and `<rule>` is any expression our config validator understands (expressions built in by the validator library and custom tags defined in `config.validation.go`). Example policy: enforcements: - path: variants.production.base rule: oneof=debian:jessie debian:stretch - path: variants.production.runs.as rule: ne=foo - path: variants.production.node.dependencies rule: isfalse Command flag parsing was implemented in `main.go` to support the new `--policy=uri` flag and improve existing handling of `--version` and the usage statement. Test Plan: Run `go test ./...`. Reviewers: thcipriani, demon, hashar, mmodell, #release-engineering-team Reviewed By: thcipriani, #release-engineering-team Tags: #release-engineering-team Differential Revision: https://phabricator.wikimedia.org/D999
Diffstat (limited to 'vendor/github.com/pborman/getopt/v2/option.go')
-rw-r--r--vendor/github.com/pborman/getopt/v2/option.go193
1 files changed, 193 insertions, 0 deletions
diff --git a/vendor/github.com/pborman/getopt/v2/option.go b/vendor/github.com/pborman/getopt/v2/option.go
new file mode 100644
index 0000000..6d5fc47
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/option.go
@@ -0,0 +1,193 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strings"
+)
+
+// An Option can be either a Flag or a Value
+type Option interface {
+ // Name returns the name of the option. If the option has been seen
+ // then the last way it was referenced (short or long) is returned
+ // otherwise if there is a short name then this will be the short name
+ // as a string, else it will be the long name.
+ Name() string
+
+ // IsFlag returns true if Option is a flag.
+ IsFlag() bool
+
+ // Seen returns true if the flag was seen.
+ Seen() bool
+
+ // Count returns the number of times the flag was seen.
+ Count() int
+
+ // String returns the last value the option was set to.
+ String() string
+
+ // Value returns the Value of the option.
+ Value() Value
+
+ // SetOptional makes the value optional. The option and value are
+ // always a single argument. Either --option or --option=value. In
+ // the former case the value of the option does not change but the Set()
+ // will return true and the value returned by Count() is incremented.
+ // The short form is either -o or -ovalue. SetOptional returns
+ // the Option
+ SetOptional() Option
+
+ // SetFlag makes the value a flag. Flags are boolean values and
+ // normally do not taken a value. They are set to true when seen.
+ // If a value is passed in the long form then it must be on, case
+ // insensitivinsensitive, one of "true", "false", "t", "f", "on", "off", "1", "0".
+ // SetFlag returns the Option
+ SetFlag() Option
+
+ // Reset resets the state of the option so it appears it has not
+ // yet been seen, including resetting the value of the option
+ // to its original default state.
+ Reset()
+}
+
+type option struct {
+ short rune // 0 means no short name
+ long string // "" means no long name
+ isLong bool // True if they used the long name
+ flag bool // true if a boolean flag
+ defval string // default value
+ optional bool // true if we take an optional value
+ help string // help message
+ where string // file where the option was defined
+ value Value // current value of option
+ count int // number of times we have seen this option
+ name string // name of the value (for usage)
+ uname string // name of the option (for usage)
+}
+
+// usageName returns the name of the option for printing usage lines in one
+// of the following forms:
+//
+// -f
+// --flag
+// -f, --flag
+// -s value
+// --set=value
+// -s, --set=value
+func (o *option) usageName() string {
+ // Don't print help messages if we have none and there is only one
+ // way to specify the option.
+ if o.help == "" && (o.short == 0 || o.long == "") {
+ return ""
+ }
+ n := ""
+
+ switch {
+ case o.short != 0 && o.long == "":
+ n = "-" + string(o.short)
+ case o.short == 0 && o.long != "":
+ n = " --" + o.long
+ case o.short != 0 && o.long != "":
+ n = "-" + string(o.short) + ", --" + o.long
+ }
+
+ switch {
+ case o.flag:
+ return n
+ case o.optional:
+ return n + "[=" + o.name + "]"
+ case o.long != "":
+ return n + "=" + o.name
+ }
+ return n + " " + o.name
+}
+
+// sortName returns the name to sort the option on.
+func (o *option) sortName() string {
+ if o.short != 0 {
+ return string(o.short) + o.long
+ }
+ return o.long[:1] + o.long
+}
+
+func (o *option) Seen() bool { return o.count > 0 }
+func (o *option) Count() int { return o.count }
+func (o *option) IsFlag() bool { return o.flag }
+func (o *option) String() string { return o.value.String() }
+func (o *option) SetOptional() Option { o.optional = true; return o }
+func (o *option) SetFlag() Option { o.flag = true; return o }
+
+func (o *option) Value() Value {
+ if o == nil {
+ return nil
+ }
+ return o.value
+}
+
+func (o *option) Name() string {
+ if !o.isLong && o.short != 0 {
+ return "-" + string(o.short)
+ }
+ return "--" + o.long
+}
+
+// Reset rests an option so that it appears it has not yet been seen.
+func (o *option) Reset() {
+ o.isLong = false
+ o.count = 0
+ o.value.Set(o.defval, o)
+}
+
+type optionList []*option
+
+func (ol optionList) Len() int { return len(ol) }
+func (ol optionList) Swap(i, j int) { ol[i], ol[j] = ol[j], ol[i] }
+func (ol optionList) Less(i, j int) bool {
+ // first check the short names (or the first letter of the long name)
+ // If they are not equal (case insensitive) then we have our answer
+ n1 := ol[i].sortName()
+ n2 := ol[j].sortName()
+ l1 := strings.ToLower(n1)
+ l2 := strings.ToLower(n2)
+ if l1 < l2 {
+ return true
+ }
+ if l2 < l1 {
+ return false
+ }
+ return n1 < n2
+}
+
+// AddOption add the option o to set CommandLine if o is not already in set
+// CommandLine.
+func AddOption(o Option) {
+ CommandLine.AddOption(o)
+}
+
+// AddOption add the option o to set s if o is not already in set s.
+func (s *Set) AddOption(o Option) {
+ opt := o.(*option)
+ for _, eopt := range s.options {
+ if opt == eopt {
+ return
+ }
+ }
+ if opt.short != 0 {
+ if oo, ok := s.shortOptions[opt.short]; ok {
+ fmt.Fprintf(stderr, "%s: -%c already declared at %s\n", opt.where, opt.short, oo.where)
+ exit(1)
+ }
+ s.shortOptions[opt.short] = opt
+ }
+ if opt.long != "" {
+ if oo, ok := s.longOptions[opt.long]; ok {
+ fmt.Fprintf(stderr, "%s: --%s already declared at %s\n", opt.where, opt.long, oo.where)
+ exit(1)
+ }
+ s.longOptions[opt.long] = opt
+ }
+ s.options = append(s.options, opt)
+}