mirror of
https://github.com/Luzifer/elastic_cron.git
synced 2024-12-22 18:31:20 +00:00
Cleanup for switching to elasticsearch
This commit is contained in:
parent
aeaaf0be28
commit
c752a62b0f
741 changed files with 19 additions and 182261 deletions
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
|
|
||||||
image: "quay.io/luzifer/repo-runner-image"
|
image: reporunner/golang-alpine
|
||||||
checkout_dir: /go/src/github.com/Luzifer/rsyslog_cron
|
checkout_dir: /go/src/github.com/Luzifer/elastic_cron
|
||||||
|
|
||||||
commands:
|
commands:
|
||||||
- make publish
|
- make publish
|
||||||
|
|
51
Gopkg.lock
generated
51
Gopkg.lock
generated
|
@ -1,51 +0,0 @@
|
||||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
|
||||||
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/Luzifer/rconfig"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "7aef1d393c1e2d0758901853b59981c7adc67c7e"
|
|
||||||
version = "v1.2.0"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/cenkalti/backoff"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "61153c768f31ee5f130071d08fc82b85208528de"
|
|
||||||
version = "v1.1.0"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/robfig/cron"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "b024fc5ea0e34bc3f83d9941c8d60b0622bfaca4"
|
|
||||||
version = "v1"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/spf13/pflag"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "e57e3eeb33f795204c1ca35f56c44f83227c6e66"
|
|
||||||
version = "v1.0.0"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "golang.org/x/net"
|
|
||||||
packages = ["context"]
|
|
||||||
revision = "b129b8e0fbeb39c8358e51a07ab6c50ad415e72e"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "v2"
|
|
||||||
name = "gopkg.in/validator.v2"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "460c83432a98c35224a6fe352acf8b23e067ad06"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "v2"
|
|
||||||
name = "gopkg.in/yaml.v2"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "eb3733d160e74a9c7e442f435eb3bea458e1d19f"
|
|
||||||
|
|
||||||
[solve-meta]
|
|
||||||
analyzer-name = "dep"
|
|
||||||
analyzer-version = 1
|
|
||||||
inputs-digest = "b486e560170c1f96bbf1ac412d054d122e586eabc3169853576007f52b88cae3"
|
|
||||||
solver-name = "gps-cdcl"
|
|
||||||
solver-version = 1
|
|
39
Gopkg.toml
39
Gopkg.toml
|
@ -1,39 +0,0 @@
|
||||||
|
|
||||||
# Gopkg.toml example
|
|
||||||
#
|
|
||||||
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
|
||||||
# for detailed Gopkg.toml documentation.
|
|
||||||
#
|
|
||||||
# required = ["github.com/user/thing/cmd/thing"]
|
|
||||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
|
||||||
#
|
|
||||||
# [[constraint]]
|
|
||||||
# name = "github.com/user/project"
|
|
||||||
# version = "1.0.0"
|
|
||||||
#
|
|
||||||
# [[constraint]]
|
|
||||||
# name = "github.com/user/project2"
|
|
||||||
# branch = "dev"
|
|
||||||
# source = "github.com/myfork/project2"
|
|
||||||
#
|
|
||||||
# [[override]]
|
|
||||||
# name = "github.com/x/y"
|
|
||||||
# version = "2.4.0"
|
|
||||||
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "github.com/Luzifer/rconfig"
|
|
||||||
version = "1.1.0"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "github.com/cenkalti/backoff"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "github.com/robfig/cron"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "golang.org/x/net"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "gopkg.in/yaml.v2"
|
|
4
LICENSE
4
LICENSE
|
@ -178,7 +178,7 @@
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
To apply the Apache License to your work, attach the following
|
||||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
replaced with your own identifying information. (Don't include
|
replaced with your own identifying information. (Don't include
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
comment syntax for the file format. We also recommend that a
|
comment syntax for the file format. We also recommend that a
|
||||||
|
@ -186,7 +186,7 @@
|
||||||
same "printed page" as the copyright notice for easier
|
same "printed page" as the copyright notice for easier
|
||||||
identification within third-party archives.
|
identification within third-party archives.
|
||||||
|
|
||||||
Copyright 2017 Knut Ahlers <knut@ahlers.me>
|
Copyright 2016- Knut Ahlers <knut@ahlers.me>
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
|
23
README.md
23
README.md
|
@ -1,17 +1,17 @@
|
||||||
# Luzifer / rsyslog\_cron
|
# Luzifer / elastic\_cron
|
||||||
|
|
||||||
This project is a quick and dirty replacement for running a cron daemon inside docker containers.
|
This project is a quick and dirty replacement for running a cron daemon inside docker containers while logging into an elasticsearch instance.
|
||||||
|
|
||||||
## Advantages
|
## Advantages
|
||||||
|
|
||||||
- It logs the output of the jobs into a remote syslog target (like Papertrail) using TCP syslog
|
- It logs the output of the jobs into an elasticsearch instance
|
||||||
- Crons can be started on seconds, not only on minutes like a conventional cron
|
- Crons can be started on seconds, not only on minutes like a conventional cron
|
||||||
- Due to the logs cron jobs can get debugged
|
- Due to the logs cron jobs can get debugged
|
||||||
- On success and failure a HTTP ping to [Healthchecks](https://healthchecks.io/) or [Cronitor](https://cronitor.io/) can be executed
|
- On success and failure a HTTP ping to [Healthchecks](https://healthchecks.io/) or [Cronitor](https://cronitor.io/) can be executed
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
1. Put the [binary](https://github.com/Luzifer/rsyslog_cron/releases/latest) into your container
|
1. Put the [binary](https://github.com/Luzifer/elastic_cron/releases/latest) into your container
|
||||||
2. Generate a YAML file containing the cron definition
|
2. Generate a YAML file containing the cron definition
|
||||||
3. Watch your crons get executed in your log stream
|
3. Watch your crons get executed in your log stream
|
||||||
|
|
||||||
|
@ -19,8 +19,12 @@ This project is a quick and dirty replacement for running a cron daemon inside d
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
---
|
---
|
||||||
rsyslog_target: logs.myserver.com:12345
|
|
||||||
log_format: '<{{ syslogpri .Severity }}>{{ .Date.Format "Jan 02 15:04:05" }} {{ .Hostname }} {{ .JobName }}: {{ .Message }}'
|
elasticsearch:
|
||||||
|
servers:
|
||||||
|
- http://localhost:9200
|
||||||
|
auth: [username, password]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
- name: date
|
- name: date
|
||||||
schedule: "0 * * * * *"
|
schedule: "0 * * * * *"
|
||||||
|
@ -29,10 +33,13 @@ jobs:
|
||||||
- "+%+"
|
- "+%+"
|
||||||
ping_success: "https://..."
|
ping_success: "https://..."
|
||||||
ping_failure: "https://..."
|
ping_failure: "https://..."
|
||||||
|
|
||||||
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
- `rsyslog_target` - needs to be a rsyslog endpoint supporting TCP plain connections like Loggly or Papertrail does.
|
- `elasticsearch`
|
||||||
- `log_format` - format to use for generating the log line (above shown is default and does not need to be provided)
|
- `servers` - List of elasticsearch instances of the same cluster to log to
|
||||||
|
- `auth` - List consisting of two elements: username and password
|
||||||
- `schedule` - consists of 6 instead of the normal 5 fields:
|
- `schedule` - consists of 6 instead of the normal 5 fields:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
106
syslog.go
106
syslog.go
|
@ -1,106 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net"
|
|
||||||
"text/template"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/cenkalti/backoff"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
readWriteTimeout = 1 * time.Second
|
|
||||||
tcpDialTimeout = 5 * time.Second
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewSyslogAdapter(address, logFormat string) (*SyslogAdapter, error) {
|
|
||||||
return &SyslogAdapter{
|
|
||||||
address: address,
|
|
||||||
logFormat: logFormat,
|
|
||||||
dialer: &net.Dialer{
|
|
||||||
Timeout: tcpDialTimeout,
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type message struct {
|
|
||||||
Date time.Time
|
|
||||||
JobName string
|
|
||||||
Message string
|
|
||||||
Severity int
|
|
||||||
}
|
|
||||||
|
|
||||||
type SyslogAdapter struct {
|
|
||||||
address string
|
|
||||||
logFormat string
|
|
||||||
dialer *net.Dialer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *SyslogAdapter) formatMessage(m *message) (string, error) {
|
|
||||||
t, err := template.New("logFormat").Funcs(template.FuncMap{
|
|
||||||
"syslogpri": func(pri int) int { return 16*8 + pri },
|
|
||||||
}).Parse(a.logFormat)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := bytes.NewBufferString("")
|
|
||||||
if err := t.Execute(buf, map[string]interface{}{
|
|
||||||
"Date": m.Date,
|
|
||||||
"JobName": m.JobName,
|
|
||||||
"Hostname": cfg.Hostname,
|
|
||||||
"Message": m.Message,
|
|
||||||
"Severity": m.Severity,
|
|
||||||
}); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return buf.String(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *SyslogAdapter) Stream(logstream chan *message) {
|
|
||||||
backoff.Retry(func() error {
|
|
||||||
conn, err := a.dialer.Dial("tcp", a.address)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("syslog: Unable to dial to remote address\n")
|
|
||||||
return fmt.Errorf("Catch me if you can.")
|
|
||||||
}
|
|
||||||
defer conn.Close()
|
|
||||||
|
|
||||||
b := new(bytes.Buffer)
|
|
||||||
for msg := range logstream {
|
|
||||||
b.Reset()
|
|
||||||
|
|
||||||
msgLine, err := a.formatMessage(msg)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Fprintln(b, msgLine)
|
|
||||||
|
|
||||||
if err := conn.SetDeadline(time.Now().Add(readWriteTimeout)); err != nil {
|
|
||||||
fmt.Printf("syslog: Unable to set deadline: %s\n", err)
|
|
||||||
return fmt.Errorf("Catch me if you can.")
|
|
||||||
}
|
|
||||||
|
|
||||||
logLine := b.Bytes()
|
|
||||||
written, err := io.Copy(conn, b)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
if written > 0 {
|
|
||||||
fmt.Printf("syslog: (%d/%d) %s\n", written, len(logLine), err)
|
|
||||||
} else {
|
|
||||||
fmt.Printf("syslog: %s\n", err)
|
|
||||||
}
|
|
||||||
return fmt.Errorf("syslog: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("syslog: I got out of the channel watch. This should never happen.\n")
|
|
||||||
return fmt.Errorf("Wat? Why am I here?")
|
|
||||||
|
|
||||||
}, &backoff.ZeroBackOff{})
|
|
||||||
}
|
|
8
vendor/github.com/Luzifer/rconfig/.travis.yml
generated
vendored
8
vendor/github.com/Luzifer/rconfig/.travis.yml
generated
vendored
|
@ -1,8 +0,0 @@
|
||||||
language: go
|
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.6
|
|
||||||
- 1.7
|
|
||||||
- tip
|
|
||||||
|
|
||||||
script: go test -v -race -cover ./...
|
|
9
vendor/github.com/Luzifer/rconfig/History.md
generated
vendored
9
vendor/github.com/Luzifer/rconfig/History.md
generated
vendored
|
@ -1,9 +0,0 @@
|
||||||
# 1.2.0 / 2017-06-19
|
|
||||||
|
|
||||||
* Add ParseAndValidate method
|
|
||||||
|
|
||||||
# 1.1.0 / 2016-06-28
|
|
||||||
|
|
||||||
* Support time.Duration config parameters
|
|
||||||
* Added goreportcard badge
|
|
||||||
* Added testcase for using bool with ENV and default
|
|
13
vendor/github.com/Luzifer/rconfig/LICENSE
generated
vendored
13
vendor/github.com/Luzifer/rconfig/LICENSE
generated
vendored
|
@ -1,13 +0,0 @@
|
||||||
Copyright 2015 Knut Ahlers <knut@ahlers.me>
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
87
vendor/github.com/Luzifer/rconfig/README.md
generated
vendored
87
vendor/github.com/Luzifer/rconfig/README.md
generated
vendored
|
@ -1,87 +0,0 @@
|
||||||
[![Build Status](https://travis-ci.org/Luzifer/rconfig.svg?branch=master)](https://travis-ci.org/Luzifer/rconfig)
|
|
||||||
[![License: Apache v2.0](https://badge.luzifer.io/v1/badge?color=5d79b5&title=license&text=Apache+v2.0)](http://www.apache.org/licenses/LICENSE-2.0)
|
|
||||||
[![Documentation](https://badge.luzifer.io/v1/badge?title=godoc&text=reference)](https://godoc.org/github.com/Luzifer/rconfig)
|
|
||||||
[![Go Report](http://goreportcard.com/badge/Luzifer/rconfig)](http://goreportcard.com/report/Luzifer/rconfig)
|
|
||||||
|
|
||||||
## Description
|
|
||||||
|
|
||||||
> Package rconfig implements a CLI configuration reader with struct-embedded defaults, environment variables and posix compatible flag parsing using the [pflag](https://github.com/spf13/pflag) library.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
Install by running:
|
|
||||||
|
|
||||||
```
|
|
||||||
go get -u github.com/Luzifer/rconfig
|
|
||||||
```
|
|
||||||
|
|
||||||
OR fetch a specific version:
|
|
||||||
|
|
||||||
```
|
|
||||||
go get -u gopkg.in/luzifer/rconfig.v1
|
|
||||||
```
|
|
||||||
|
|
||||||
Run tests by running:
|
|
||||||
|
|
||||||
```
|
|
||||||
go test -v -race -cover github.com/Luzifer/rconfig
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
A very simple usecase is to just configure a struct inside the vars section of your `main.go` and to parse the commandline flags from the `main()` function:
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/Luzifer/rconfig"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
cfg = struct {
|
|
||||||
Username string `default:"unknown" flag:"user" description:"Your name"`
|
|
||||||
Details struct {
|
|
||||||
Age int `default:"25" flag:"age" env:"age" description:"Your age"`
|
|
||||||
}
|
|
||||||
}{}
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
rconfig.Parse(&cfg)
|
|
||||||
|
|
||||||
fmt.Printf("Hello %s, happy birthday for your %dth birthday.",
|
|
||||||
cfg.Username,
|
|
||||||
cfg.Details.Age)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Provide variable defaults by using a file
|
|
||||||
|
|
||||||
Given you have a file `~/.myapp.yml` containing some secrets or usernames (for the example below username is assumed to be "luzifer") as a default configuration for your application you can use this source code to load the defaults from that file using the `vardefault` tag in your configuration struct.
|
|
||||||
|
|
||||||
The order of the directives (lower number = higher precedence):
|
|
||||||
|
|
||||||
1. Flags provided in command line
|
|
||||||
1. Environment variables
|
|
||||||
1. Variable defaults (`vardefault` tag in the struct)
|
|
||||||
1. `default` tag in the struct
|
|
||||||
|
|
||||||
```go
|
|
||||||
var cfg = struct {
|
|
||||||
Username string `vardefault:"username" flag:"username" description:"Your username"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
rconfig.SetVariableDefaults(rconfig.VarDefaultsFromYAMLFile("~/.myapp.yml"))
|
|
||||||
rconfig.Parse(&cfg)
|
|
||||||
|
|
||||||
fmt.Printf("Username = %s", cfg.Username)
|
|
||||||
// Output: Username = luzifer
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## More info
|
|
||||||
|
|
||||||
You can see the full reference documentation of the rconfig package [at godoc.org](https://godoc.org/github.com/Luzifer/rconfig), or through go's standard documentation system by running `godoc -http=:6060` and browsing to [http://localhost:6060/pkg/github.com/Luzifer/rconfig](http://localhost:6060/pkg/github.com/Luzifer/rconfig) after installation.
|
|
70
vendor/github.com/Luzifer/rconfig/bool_test.go
generated
vendored
70
vendor/github.com/Luzifer/rconfig/bool_test.go
generated
vendored
|
@ -1,70 +0,0 @@
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = Describe("Testing bool parsing", func() {
|
|
||||||
type t struct {
|
|
||||||
Test1 bool `default:"true"`
|
|
||||||
Test2 bool `default:"false" flag:"test2"`
|
|
||||||
Test3 bool `default:"true" flag:"test3,t"`
|
|
||||||
Test4 bool `flag:"test4"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
args []string
|
|
||||||
cfg t
|
|
||||||
)
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
args = []string{
|
|
||||||
"--test2",
|
|
||||||
"-t",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values", func() {
|
|
||||||
Expect(cfg.Test1).To(Equal(true))
|
|
||||||
Expect(cfg.Test2).To(Equal(true))
|
|
||||||
Expect(cfg.Test3).To(Equal(true))
|
|
||||||
Expect(cfg.Test4).To(Equal(false))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
var _ = Describe("Testing to set bool from ENV with default", func() {
|
|
||||||
type t struct {
|
|
||||||
Test1 bool `default:"true" env:"TEST1"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
args []string
|
|
||||||
cfg t
|
|
||||||
)
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
args = []string{}
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
os.Unsetenv("TEST1")
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values", func() {
|
|
||||||
Expect(cfg.Test1).To(Equal(true))
|
|
||||||
})
|
|
||||||
})
|
|
356
vendor/github.com/Luzifer/rconfig/config.go
generated
vendored
356
vendor/github.com/Luzifer/rconfig/config.go
generated
vendored
|
@ -1,356 +0,0 @@
|
||||||
// Package rconfig implements a CLI configuration reader with struct-embedded
|
|
||||||
// defaults, environment variables and posix compatible flag parsing using
|
|
||||||
// the pflag library.
|
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/spf13/pflag"
|
|
||||||
validator "gopkg.in/validator.v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
fs *pflag.FlagSet
|
|
||||||
variableDefaults map[string]string
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
variableDefaults = make(map[string]string)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse takes the pointer to a struct filled with variables which should be read
|
|
||||||
// from ENV, default or flag. The precedence in this is flag > ENV > default. So
|
|
||||||
// if a flag is specified on the CLI it will overwrite the ENV and otherwise ENV
|
|
||||||
// overwrites the default specified.
|
|
||||||
//
|
|
||||||
// For your configuration struct you can use the following struct-tags to control
|
|
||||||
// the behavior of rconfig:
|
|
||||||
//
|
|
||||||
// default: Set a default value
|
|
||||||
// vardefault: Read the default value from the variable defaults
|
|
||||||
// env: Read the value from this environment variable
|
|
||||||
// flag: Flag to read in format "long,short" (for example "listen,l")
|
|
||||||
// description: A help text for Usage output to guide your users
|
|
||||||
//
|
|
||||||
// The format you need to specify those values you can see in the example to this
|
|
||||||
// function.
|
|
||||||
//
|
|
||||||
func Parse(config interface{}) error {
|
|
||||||
return parse(config, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseAndValidate works exactly like Parse but implements an additional run of
|
|
||||||
// the go-validator package on the configuration struct. Therefore additonal struct
|
|
||||||
// tags are supported like described in the readme file of the go-validator package:
|
|
||||||
//
|
|
||||||
// https://github.com/go-validator/validator/tree/v2#usage
|
|
||||||
func ParseAndValidate(config interface{}) error {
|
|
||||||
return parseAndValidate(config, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Args returns the non-flag command-line arguments.
|
|
||||||
func Args() []string {
|
|
||||||
return fs.Args()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Usage prints a basic usage with the corresponding defaults for the flags to
|
|
||||||
// os.Stdout. The defaults are derived from the `default` struct-tag and the ENV.
|
|
||||||
func Usage() {
|
|
||||||
if fs != nil && fs.Parsed() {
|
|
||||||
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
|
|
||||||
fs.PrintDefaults()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetVariableDefaults presets the parser with a map of default values to be used
|
|
||||||
// when specifying the vardefault tag
|
|
||||||
func SetVariableDefaults(defaults map[string]string) {
|
|
||||||
variableDefaults = defaults
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseAndValidate(in interface{}, args []string) error {
|
|
||||||
if err := parse(in, args); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return validator.Validate(in)
|
|
||||||
}
|
|
||||||
|
|
||||||
func parse(in interface{}, args []string) error {
|
|
||||||
if args == nil {
|
|
||||||
args = os.Args
|
|
||||||
}
|
|
||||||
|
|
||||||
fs = pflag.NewFlagSet(os.Args[0], pflag.ExitOnError)
|
|
||||||
if err := execTags(in, fs); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return fs.Parse(args)
|
|
||||||
}
|
|
||||||
|
|
||||||
func execTags(in interface{}, fs *pflag.FlagSet) error {
|
|
||||||
if reflect.TypeOf(in).Kind() != reflect.Ptr {
|
|
||||||
return errors.New("Calling parser with non-pointer")
|
|
||||||
}
|
|
||||||
|
|
||||||
if reflect.ValueOf(in).Elem().Kind() != reflect.Struct {
|
|
||||||
return errors.New("Calling parser with pointer to non-struct")
|
|
||||||
}
|
|
||||||
|
|
||||||
st := reflect.ValueOf(in).Elem()
|
|
||||||
for i := 0; i < st.NumField(); i++ {
|
|
||||||
valField := st.Field(i)
|
|
||||||
typeField := st.Type().Field(i)
|
|
||||||
|
|
||||||
if typeField.Tag.Get("default") == "" && typeField.Tag.Get("env") == "" && typeField.Tag.Get("flag") == "" && typeField.Type.Kind() != reflect.Struct {
|
|
||||||
// None of our supported tags is present and it's not a sub-struct
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
value := varDefault(typeField.Tag.Get("vardefault"), typeField.Tag.Get("default"))
|
|
||||||
value = envDefault(typeField.Tag.Get("env"), value)
|
|
||||||
parts := strings.Split(typeField.Tag.Get("flag"), ",")
|
|
||||||
|
|
||||||
switch typeField.Type {
|
|
||||||
case reflect.TypeOf(time.Duration(0)):
|
|
||||||
v, err := time.ParseDuration(value)
|
|
||||||
if err != nil {
|
|
||||||
if value == "" {
|
|
||||||
v = time.Duration(0)
|
|
||||||
} else {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if typeField.Tag.Get("flag") != "" {
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.DurationVar(valField.Addr().Interface().(*time.Duration), parts[0], v, typeField.Tag.Get("description"))
|
|
||||||
} else {
|
|
||||||
fs.DurationVarP(valField.Addr().Interface().(*time.Duration), parts[0], parts[1], v, typeField.Tag.Get("description"))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
valField.Set(reflect.ValueOf(v))
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
switch typeField.Type.Kind() {
|
|
||||||
case reflect.String:
|
|
||||||
if typeField.Tag.Get("flag") != "" {
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.StringVar(valField.Addr().Interface().(*string), parts[0], value, typeField.Tag.Get("description"))
|
|
||||||
} else {
|
|
||||||
fs.StringVarP(valField.Addr().Interface().(*string), parts[0], parts[1], value, typeField.Tag.Get("description"))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
valField.SetString(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Bool:
|
|
||||||
v := value == "true"
|
|
||||||
if typeField.Tag.Get("flag") != "" {
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.BoolVar(valField.Addr().Interface().(*bool), parts[0], v, typeField.Tag.Get("description"))
|
|
||||||
} else {
|
|
||||||
fs.BoolVarP(valField.Addr().Interface().(*bool), parts[0], parts[1], v, typeField.Tag.Get("description"))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
valField.SetBool(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Int, reflect.Int8, reflect.Int32, reflect.Int64:
|
|
||||||
vt, err := strconv.ParseInt(value, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
if value == "" {
|
|
||||||
vt = 0
|
|
||||||
} else {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if typeField.Tag.Get("flag") != "" {
|
|
||||||
registerFlagInt(typeField.Type.Kind(), fs, valField.Addr().Interface(), parts, vt, typeField.Tag.Get("description"))
|
|
||||||
} else {
|
|
||||||
valField.SetInt(vt)
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
|
||||||
vt, err := strconv.ParseUint(value, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
if value == "" {
|
|
||||||
vt = 0
|
|
||||||
} else {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if typeField.Tag.Get("flag") != "" {
|
|
||||||
registerFlagUint(typeField.Type.Kind(), fs, valField.Addr().Interface(), parts, vt, typeField.Tag.Get("description"))
|
|
||||||
} else {
|
|
||||||
valField.SetUint(vt)
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Float32, reflect.Float64:
|
|
||||||
vt, err := strconv.ParseFloat(value, 64)
|
|
||||||
if err != nil {
|
|
||||||
if value == "" {
|
|
||||||
vt = 0.0
|
|
||||||
} else {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if typeField.Tag.Get("flag") != "" {
|
|
||||||
registerFlagFloat(typeField.Type.Kind(), fs, valField.Addr().Interface(), parts, vt, typeField.Tag.Get("description"))
|
|
||||||
} else {
|
|
||||||
valField.SetFloat(vt)
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Struct:
|
|
||||||
if err := execTags(valField.Addr().Interface(), fs); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Slice:
|
|
||||||
switch typeField.Type.Elem().Kind() {
|
|
||||||
case reflect.Int:
|
|
||||||
def := []int{}
|
|
||||||
for _, v := range strings.Split(value, ",") {
|
|
||||||
it, err := strconv.ParseInt(strings.TrimSpace(v), 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
def = append(def, int(it))
|
|
||||||
}
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.IntSliceVar(valField.Addr().Interface().(*[]int), parts[0], def, typeField.Tag.Get("description"))
|
|
||||||
} else {
|
|
||||||
fs.IntSliceVarP(valField.Addr().Interface().(*[]int), parts[0], parts[1], def, typeField.Tag.Get("description"))
|
|
||||||
}
|
|
||||||
case reflect.String:
|
|
||||||
del := typeField.Tag.Get("delimiter")
|
|
||||||
if len(del) == 0 {
|
|
||||||
del = ","
|
|
||||||
}
|
|
||||||
def := strings.Split(value, del)
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.StringSliceVar(valField.Addr().Interface().(*[]string), parts[0], def, typeField.Tag.Get("description"))
|
|
||||||
} else {
|
|
||||||
fs.StringSliceVarP(valField.Addr().Interface().(*[]string), parts[0], parts[1], def, typeField.Tag.Get("description"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func registerFlagFloat(t reflect.Kind, fs *pflag.FlagSet, field interface{}, parts []string, vt float64, desc string) {
|
|
||||||
switch t {
|
|
||||||
case reflect.Float32:
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.Float32Var(field.(*float32), parts[0], float32(vt), desc)
|
|
||||||
} else {
|
|
||||||
fs.Float32VarP(field.(*float32), parts[0], parts[1], float32(vt), desc)
|
|
||||||
}
|
|
||||||
case reflect.Float64:
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.Float64Var(field.(*float64), parts[0], float64(vt), desc)
|
|
||||||
} else {
|
|
||||||
fs.Float64VarP(field.(*float64), parts[0], parts[1], float64(vt), desc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func registerFlagInt(t reflect.Kind, fs *pflag.FlagSet, field interface{}, parts []string, vt int64, desc string) {
|
|
||||||
switch t {
|
|
||||||
case reflect.Int:
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.IntVar(field.(*int), parts[0], int(vt), desc)
|
|
||||||
} else {
|
|
||||||
fs.IntVarP(field.(*int), parts[0], parts[1], int(vt), desc)
|
|
||||||
}
|
|
||||||
case reflect.Int8:
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.Int8Var(field.(*int8), parts[0], int8(vt), desc)
|
|
||||||
} else {
|
|
||||||
fs.Int8VarP(field.(*int8), parts[0], parts[1], int8(vt), desc)
|
|
||||||
}
|
|
||||||
case reflect.Int32:
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.Int32Var(field.(*int32), parts[0], int32(vt), desc)
|
|
||||||
} else {
|
|
||||||
fs.Int32VarP(field.(*int32), parts[0], parts[1], int32(vt), desc)
|
|
||||||
}
|
|
||||||
case reflect.Int64:
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.Int64Var(field.(*int64), parts[0], int64(vt), desc)
|
|
||||||
} else {
|
|
||||||
fs.Int64VarP(field.(*int64), parts[0], parts[1], int64(vt), desc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func registerFlagUint(t reflect.Kind, fs *pflag.FlagSet, field interface{}, parts []string, vt uint64, desc string) {
|
|
||||||
switch t {
|
|
||||||
case reflect.Uint:
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.UintVar(field.(*uint), parts[0], uint(vt), desc)
|
|
||||||
} else {
|
|
||||||
fs.UintVarP(field.(*uint), parts[0], parts[1], uint(vt), desc)
|
|
||||||
}
|
|
||||||
case reflect.Uint8:
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.Uint8Var(field.(*uint8), parts[0], uint8(vt), desc)
|
|
||||||
} else {
|
|
||||||
fs.Uint8VarP(field.(*uint8), parts[0], parts[1], uint8(vt), desc)
|
|
||||||
}
|
|
||||||
case reflect.Uint16:
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.Uint16Var(field.(*uint16), parts[0], uint16(vt), desc)
|
|
||||||
} else {
|
|
||||||
fs.Uint16VarP(field.(*uint16), parts[0], parts[1], uint16(vt), desc)
|
|
||||||
}
|
|
||||||
case reflect.Uint32:
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.Uint32Var(field.(*uint32), parts[0], uint32(vt), desc)
|
|
||||||
} else {
|
|
||||||
fs.Uint32VarP(field.(*uint32), parts[0], parts[1], uint32(vt), desc)
|
|
||||||
}
|
|
||||||
case reflect.Uint64:
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.Uint64Var(field.(*uint64), parts[0], uint64(vt), desc)
|
|
||||||
} else {
|
|
||||||
fs.Uint64VarP(field.(*uint64), parts[0], parts[1], uint64(vt), desc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func envDefault(env, def string) string {
|
|
||||||
value := def
|
|
||||||
|
|
||||||
if env != "" {
|
|
||||||
if e := os.Getenv(env); e != "" {
|
|
||||||
value = e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
func varDefault(name, def string) string {
|
|
||||||
value := def
|
|
||||||
|
|
||||||
if name != "" {
|
|
||||||
if v, ok := variableDefaults[name]; ok {
|
|
||||||
value = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return value
|
|
||||||
}
|
|
41
vendor/github.com/Luzifer/rconfig/duration_test.go
generated
vendored
41
vendor/github.com/Luzifer/rconfig/duration_test.go
generated
vendored
|
@ -1,41 +0,0 @@
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = Describe("Duration", func() {
|
|
||||||
type t struct {
|
|
||||||
Test time.Duration `flag:"duration"`
|
|
||||||
TestS time.Duration `flag:"other-duration,o"`
|
|
||||||
TestDef time.Duration `default:"30h"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
args []string
|
|
||||||
cfg t
|
|
||||||
)
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
args = []string{
|
|
||||||
"--duration=23s", "-o", "45m",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values", func() {
|
|
||||||
Expect(cfg.Test).To(Equal(23 * time.Second))
|
|
||||||
Expect(cfg.TestS).To(Equal(45 * time.Minute))
|
|
||||||
|
|
||||||
Expect(cfg.TestDef).To(Equal(30 * time.Hour))
|
|
||||||
})
|
|
||||||
})
|
|
56
vendor/github.com/Luzifer/rconfig/errors_test.go
generated
vendored
56
vendor/github.com/Luzifer/rconfig/errors_test.go
generated
vendored
|
@ -1,56 +0,0 @@
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = Describe("Testing errors", func() {
|
|
||||||
|
|
||||||
It("should not accept string as int", func() {
|
|
||||||
Expect(parse(&struct {
|
|
||||||
A int `default:"a"`
|
|
||||||
}{}, []string{})).To(HaveOccurred())
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not accept string as float", func() {
|
|
||||||
Expect(parse(&struct {
|
|
||||||
A float32 `default:"a"`
|
|
||||||
}{}, []string{})).To(HaveOccurred())
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not accept string as uint", func() {
|
|
||||||
Expect(parse(&struct {
|
|
||||||
A uint `default:"a"`
|
|
||||||
}{}, []string{})).To(HaveOccurred())
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not accept string as uint in sub-struct", func() {
|
|
||||||
Expect(parse(&struct {
|
|
||||||
B struct {
|
|
||||||
A uint `default:"a"`
|
|
||||||
}
|
|
||||||
}{}, []string{})).To(HaveOccurred())
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not accept string slice as int slice", func() {
|
|
||||||
Expect(parse(&struct {
|
|
||||||
A []int `default:"a,bn"`
|
|
||||||
}{}, []string{})).To(HaveOccurred())
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not accept variables not being pointers", func() {
|
|
||||||
cfg := struct {
|
|
||||||
A string `default:"a"`
|
|
||||||
}{}
|
|
||||||
|
|
||||||
Expect(parse(cfg, []string{})).To(HaveOccurred())
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not accept variables not being pointers to structs", func() {
|
|
||||||
cfg := "test"
|
|
||||||
|
|
||||||
Expect(parse(cfg, []string{})).To(HaveOccurred())
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
37
vendor/github.com/Luzifer/rconfig/example_test.go
generated
vendored
37
vendor/github.com/Luzifer/rconfig/example_test.go
generated
vendored
|
@ -1,37 +0,0 @@
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ExampleParse() {
|
|
||||||
// We're building an example configuration with a sub-struct to be filled
|
|
||||||
// by the Parse command.
|
|
||||||
config := struct {
|
|
||||||
Username string `default:"unknown" flag:"user,u" description:"Your name"`
|
|
||||||
Details struct {
|
|
||||||
Age int `default:"25" flag:"age" description:"Your age"`
|
|
||||||
}
|
|
||||||
}{}
|
|
||||||
|
|
||||||
// To have more relieable results we're setting os.Args to a known value.
|
|
||||||
// In real-life use cases you wouldn't do this but parse the original
|
|
||||||
// commandline arguments.
|
|
||||||
os.Args = []string{
|
|
||||||
"example",
|
|
||||||
"--user=Luzifer",
|
|
||||||
}
|
|
||||||
|
|
||||||
Parse(&config)
|
|
||||||
|
|
||||||
fmt.Printf("Hello %s, happy birthday for your %dth birthday.",
|
|
||||||
config.Username,
|
|
||||||
config.Details.Age)
|
|
||||||
|
|
||||||
// You can also show an usage message for your user
|
|
||||||
Usage()
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// Hello Luzifer, happy birthday for your 25th birthday.
|
|
||||||
}
|
|
44
vendor/github.com/Luzifer/rconfig/float_test.go
generated
vendored
44
vendor/github.com/Luzifer/rconfig/float_test.go
generated
vendored
|
@ -1,44 +0,0 @@
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = Describe("Testing float parsing", func() {
|
|
||||||
type t struct {
|
|
||||||
Test32 float32 `flag:"float32"`
|
|
||||||
Test32P float32 `flag:"float32p,3"`
|
|
||||||
Test64 float64 `flag:"float64"`
|
|
||||||
Test64P float64 `flag:"float64p,6"`
|
|
||||||
TestDef float32 `default:"66.256"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
args []string
|
|
||||||
cfg t
|
|
||||||
)
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
args = []string{
|
|
||||||
"--float32=5.5", "-3", "6.6",
|
|
||||||
"--float64=7.7", "-6", "8.8",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values", func() {
|
|
||||||
Expect(cfg.Test32).To(Equal(float32(5.5)))
|
|
||||||
Expect(cfg.Test32P).To(Equal(float32(6.6)))
|
|
||||||
Expect(cfg.Test64).To(Equal(float64(7.7)))
|
|
||||||
Expect(cfg.Test64P).To(Equal(float64(8.8)))
|
|
||||||
|
|
||||||
Expect(cfg.TestDef).To(Equal(float32(66.256)))
|
|
||||||
})
|
|
||||||
})
|
|
128
vendor/github.com/Luzifer/rconfig/general_test.go
generated
vendored
128
vendor/github.com/Luzifer/rconfig/general_test.go
generated
vendored
|
@ -1,128 +0,0 @@
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = Describe("Testing general parsing", func() {
|
|
||||||
type t struct {
|
|
||||||
Test string `default:"foo" env:"shell" flag:"shell" description:"Test"`
|
|
||||||
Test2 string `default:"blub" env:"testvar" flag:"testvar,t" description:"Test"`
|
|
||||||
DefaultFlag string `default:"goo"`
|
|
||||||
SadFlag string
|
|
||||||
}
|
|
||||||
|
|
||||||
type tValidated struct {
|
|
||||||
Test string `flag:"test" default:"" validate:"nonzero"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
args []string
|
|
||||||
cfg t
|
|
||||||
)
|
|
||||||
|
|
||||||
Context("with defined arguments", func() {
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
args = []string{
|
|
||||||
"--shell=test23",
|
|
||||||
"-t", "bla",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have parsed the expected values", func() {
|
|
||||||
Expect(cfg.Test).To(Equal("test23"))
|
|
||||||
Expect(cfg.Test2).To(Equal("bla"))
|
|
||||||
Expect(cfg.SadFlag).To(Equal(""))
|
|
||||||
Expect(cfg.DefaultFlag).To(Equal("goo"))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("with no arguments", func() {
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
args = []string{}
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have used the default value", func() {
|
|
||||||
Expect(cfg.Test).To(Equal("foo"))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("with no arguments and set env", func() {
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
args = []string{}
|
|
||||||
os.Setenv("shell", "test546")
|
|
||||||
})
|
|
||||||
|
|
||||||
AfterEach(func() {
|
|
||||||
os.Unsetenv("shell")
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have used the value from env", func() {
|
|
||||||
Expect(cfg.Test).To(Equal("test546"))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("with additional arguments", func() {
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
args = []string{
|
|
||||||
"--shell=test23",
|
|
||||||
"-t", "bla",
|
|
||||||
"positional1", "positional2",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have parsed the expected values", func() {
|
|
||||||
Expect(cfg.Test).To(Equal("test23"))
|
|
||||||
Expect(cfg.Test2).To(Equal("bla"))
|
|
||||||
Expect(cfg.SadFlag).To(Equal(""))
|
|
||||||
Expect(cfg.DefaultFlag).To(Equal("goo"))
|
|
||||||
})
|
|
||||||
It("should have detected the positional arguments", func() {
|
|
||||||
Expect(Args()).To(Equal([]string{"positional1", "positional2"}))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("making use of the validator package", func() {
|
|
||||||
var cfgValidated tValidated
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfgValidated = tValidated{}
|
|
||||||
args = []string{}
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = parseAndValidate(&cfgValidated, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should have errored", func() { Expect(err).To(HaveOccurred()) })
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
54
vendor/github.com/Luzifer/rconfig/int_test.go
generated
vendored
54
vendor/github.com/Luzifer/rconfig/int_test.go
generated
vendored
|
@ -1,54 +0,0 @@
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = Describe("Testing int parsing", func() {
|
|
||||||
type t struct {
|
|
||||||
Test int `flag:"int"`
|
|
||||||
TestP int `flag:"intp,i"`
|
|
||||||
Test8 int8 `flag:"int8"`
|
|
||||||
Test8P int8 `flag:"int8p,8"`
|
|
||||||
Test32 int32 `flag:"int32"`
|
|
||||||
Test32P int32 `flag:"int32p,3"`
|
|
||||||
Test64 int64 `flag:"int64"`
|
|
||||||
Test64P int64 `flag:"int64p,6"`
|
|
||||||
TestDef int8 `default:"66"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
args []string
|
|
||||||
cfg t
|
|
||||||
)
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
args = []string{
|
|
||||||
"--int=1", "-i", "2",
|
|
||||||
"--int8=3", "-8", "4",
|
|
||||||
"--int32=5", "-3", "6",
|
|
||||||
"--int64=7", "-6", "8",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values", func() {
|
|
||||||
Expect(cfg.Test).To(Equal(1))
|
|
||||||
Expect(cfg.TestP).To(Equal(2))
|
|
||||||
Expect(cfg.Test8).To(Equal(int8(3)))
|
|
||||||
Expect(cfg.Test8P).To(Equal(int8(4)))
|
|
||||||
Expect(cfg.Test32).To(Equal(int32(5)))
|
|
||||||
Expect(cfg.Test32P).To(Equal(int32(6)))
|
|
||||||
Expect(cfg.Test64).To(Equal(int64(7)))
|
|
||||||
Expect(cfg.Test64P).To(Equal(int64(8)))
|
|
||||||
|
|
||||||
Expect(cfg.TestDef).To(Equal(int8(66)))
|
|
||||||
})
|
|
||||||
})
|
|
40
vendor/github.com/Luzifer/rconfig/os-args_test.go
generated
vendored
40
vendor/github.com/Luzifer/rconfig/os-args_test.go
generated
vendored
|
@ -1,40 +0,0 @@
|
||||||
package rconfig_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
|
|
||||||
. "github.com/Luzifer/rconfig"
|
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = Describe("Testing os.Args", func() {
|
|
||||||
type t struct {
|
|
||||||
A string `default:"a" flag:"a"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
cfg t
|
|
||||||
)
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = Parse(&cfg)
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("With only valid arguments", func() {
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
os.Args = []string{"--a=bar"}
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values", func() {
|
|
||||||
Expect(cfg.A).To(Equal("bar"))
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
87
vendor/github.com/Luzifer/rconfig/precedence_test.go
generated
vendored
87
vendor/github.com/Luzifer/rconfig/precedence_test.go
generated
vendored
|
@ -1,87 +0,0 @@
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = Describe("Precedence", func() {
|
|
||||||
|
|
||||||
type t struct {
|
|
||||||
A int `default:"1" vardefault:"a" env:"a" flag:"avar,a" description:"a"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
cfg t
|
|
||||||
args []string
|
|
||||||
vardefaults map[string]string
|
|
||||||
)
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
SetVariableDefaults(vardefaults)
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("Provided: Flag, Env, Default, VarDefault", func() {
|
|
||||||
BeforeEach(func() {
|
|
||||||
args = []string{"-a", "5"}
|
|
||||||
os.Setenv("a", "8")
|
|
||||||
vardefaults = map[string]string{
|
|
||||||
"a": "3",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have used the flag value", func() {
|
|
||||||
Expect(cfg.A).To(Equal(5))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("Provided: Env, Default, VarDefault", func() {
|
|
||||||
BeforeEach(func() {
|
|
||||||
args = []string{}
|
|
||||||
os.Setenv("a", "8")
|
|
||||||
vardefaults = map[string]string{
|
|
||||||
"a": "3",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have used the env value", func() {
|
|
||||||
Expect(cfg.A).To(Equal(8))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("Provided: Default, VarDefault", func() {
|
|
||||||
BeforeEach(func() {
|
|
||||||
args = []string{}
|
|
||||||
os.Unsetenv("a")
|
|
||||||
vardefaults = map[string]string{
|
|
||||||
"a": "3",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have used the vardefault value", func() {
|
|
||||||
Expect(cfg.A).To(Equal(3))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("Provided: Default", func() {
|
|
||||||
BeforeEach(func() {
|
|
||||||
args = []string{}
|
|
||||||
os.Unsetenv("a")
|
|
||||||
vardefaults = map[string]string{}
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have used the default value", func() {
|
|
||||||
Expect(cfg.A).To(Equal(1))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
13
vendor/github.com/Luzifer/rconfig/rconfig_suite_test.go
generated
vendored
13
vendor/github.com/Luzifer/rconfig/rconfig_suite_test.go
generated
vendored
|
@ -1,13 +0,0 @@
|
||||||
package rconfig_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestRconfig(t *testing.T) {
|
|
||||||
RegisterFailHandler(Fail)
|
|
||||||
RunSpecs(t, "Rconfig Suite")
|
|
||||||
}
|
|
51
vendor/github.com/Luzifer/rconfig/slice_test.go
generated
vendored
51
vendor/github.com/Luzifer/rconfig/slice_test.go
generated
vendored
|
@ -1,51 +0,0 @@
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = Describe("Testing slices", func() {
|
|
||||||
type t struct {
|
|
||||||
Int []int `default:"1,2,3" flag:"int"`
|
|
||||||
String []string `default:"a,b,c" flag:"string"`
|
|
||||||
IntP []int `default:"1,2,3" flag:"intp,i"`
|
|
||||||
StringP []string `default:"a,b,c" flag:"stringp,s"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
args []string
|
|
||||||
cfg t
|
|
||||||
)
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
args = []string{
|
|
||||||
"--int=4,5", "-s", "hallo,welt",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values for int-slice", func() {
|
|
||||||
Expect(len(cfg.Int)).To(Equal(2))
|
|
||||||
Expect(cfg.Int).To(Equal([]int{4, 5}))
|
|
||||||
Expect(cfg.Int).NotTo(Equal([]int{5, 4}))
|
|
||||||
})
|
|
||||||
It("should have the expected values for int-shorthand-slice", func() {
|
|
||||||
Expect(len(cfg.IntP)).To(Equal(3))
|
|
||||||
Expect(cfg.IntP).To(Equal([]int{1, 2, 3}))
|
|
||||||
})
|
|
||||||
It("should have the expected values for string-slice", func() {
|
|
||||||
Expect(len(cfg.String)).To(Equal(3))
|
|
||||||
Expect(cfg.String).To(Equal([]string{"a", "b", "c"}))
|
|
||||||
})
|
|
||||||
It("should have the expected values for string-shorthand-slice", func() {
|
|
||||||
Expect(len(cfg.StringP)).To(Equal(2))
|
|
||||||
Expect(cfg.StringP).To(Equal([]string{"hallo", "welt"}))
|
|
||||||
})
|
|
||||||
})
|
|
36
vendor/github.com/Luzifer/rconfig/sub-struct_test.go
generated
vendored
36
vendor/github.com/Luzifer/rconfig/sub-struct_test.go
generated
vendored
|
@ -1,36 +0,0 @@
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = Describe("Testing sub-structs", func() {
|
|
||||||
type t struct {
|
|
||||||
Test string `default:"blubb"`
|
|
||||||
Sub struct {
|
|
||||||
Test string `default:"Hallo"`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
args []string
|
|
||||||
cfg t
|
|
||||||
)
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
args = []string{}
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values", func() {
|
|
||||||
Expect(cfg.Test).To(Equal("blubb"))
|
|
||||||
Expect(cfg.Sub.Test).To(Equal("Hallo"))
|
|
||||||
})
|
|
||||||
})
|
|
59
vendor/github.com/Luzifer/rconfig/uint_test.go
generated
vendored
59
vendor/github.com/Luzifer/rconfig/uint_test.go
generated
vendored
|
@ -1,59 +0,0 @@
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = Describe("Testing uint parsing", func() {
|
|
||||||
type t struct {
|
|
||||||
Test uint `flag:"int"`
|
|
||||||
TestP uint `flag:"intp,i"`
|
|
||||||
Test8 uint8 `flag:"int8"`
|
|
||||||
Test8P uint8 `flag:"int8p,8"`
|
|
||||||
Test16 uint16 `flag:"int16"`
|
|
||||||
Test16P uint16 `flag:"int16p,1"`
|
|
||||||
Test32 uint32 `flag:"int32"`
|
|
||||||
Test32P uint32 `flag:"int32p,3"`
|
|
||||||
Test64 uint64 `flag:"int64"`
|
|
||||||
Test64P uint64 `flag:"int64p,6"`
|
|
||||||
TestDef uint8 `default:"66"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
args []string
|
|
||||||
cfg t
|
|
||||||
)
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
args = []string{
|
|
||||||
"--int=1", "-i", "2",
|
|
||||||
"--int8=3", "-8", "4",
|
|
||||||
"--int32=5", "-3", "6",
|
|
||||||
"--int64=7", "-6", "8",
|
|
||||||
"--int16=9", "-1", "10",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values", func() {
|
|
||||||
Expect(cfg.Test).To(Equal(uint(1)))
|
|
||||||
Expect(cfg.TestP).To(Equal(uint(2)))
|
|
||||||
Expect(cfg.Test8).To(Equal(uint8(3)))
|
|
||||||
Expect(cfg.Test8P).To(Equal(uint8(4)))
|
|
||||||
Expect(cfg.Test32).To(Equal(uint32(5)))
|
|
||||||
Expect(cfg.Test32P).To(Equal(uint32(6)))
|
|
||||||
Expect(cfg.Test64).To(Equal(uint64(7)))
|
|
||||||
Expect(cfg.Test64P).To(Equal(uint64(8)))
|
|
||||||
Expect(cfg.Test16).To(Equal(uint16(9)))
|
|
||||||
Expect(cfg.Test16P).To(Equal(uint16(10)))
|
|
||||||
|
|
||||||
Expect(cfg.TestDef).To(Equal(uint8(66)))
|
|
||||||
})
|
|
||||||
})
|
|
27
vendor/github.com/Luzifer/rconfig/vardefault_providers.go
generated
vendored
27
vendor/github.com/Luzifer/rconfig/vardefault_providers.go
generated
vendored
|
@ -1,27 +0,0 @@
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/ioutil"
|
|
||||||
|
|
||||||
"gopkg.in/yaml.v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
// VarDefaultsFromYAMLFile reads contents of a file and calls VarDefaultsFromYAML
|
|
||||||
func VarDefaultsFromYAMLFile(filename string) map[string]string {
|
|
||||||
data, err := ioutil.ReadFile(filename)
|
|
||||||
if err != nil {
|
|
||||||
return make(map[string]string)
|
|
||||||
}
|
|
||||||
|
|
||||||
return VarDefaultsFromYAML(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
// VarDefaultsFromYAML creates a vardefaults map from YAML raw data
|
|
||||||
func VarDefaultsFromYAML(in []byte) map[string]string {
|
|
||||||
out := make(map[string]string)
|
|
||||||
err := yaml.Unmarshal(in, &out)
|
|
||||||
if err != nil {
|
|
||||||
return make(map[string]string)
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
122
vendor/github.com/Luzifer/rconfig/vardefault_test.go
generated
vendored
122
vendor/github.com/Luzifer/rconfig/vardefault_test.go
generated
vendored
|
@ -1,122 +0,0 @@
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = Describe("Testing variable defaults", func() {
|
|
||||||
|
|
||||||
type t struct {
|
|
||||||
MySecretValue string `default:"secret" env:"foo" vardefault:"my_secret_value"`
|
|
||||||
MyUsername string `default:"luzifer" vardefault:"username"`
|
|
||||||
SomeVar string `flag:"var" description:"some variable"`
|
|
||||||
IntVar int64 `vardefault:"int_var" default:"23"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
cfg t
|
|
||||||
args = []string{}
|
|
||||||
vardefaults = map[string]string{
|
|
||||||
"my_secret_value": "veryverysecretkey",
|
|
||||||
"unkownkey": "hi there",
|
|
||||||
"int_var": "42",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("With manually provided variables", func() {
|
|
||||||
BeforeEach(func() {
|
|
||||||
SetVariableDefaults(vardefaults)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values", func() {
|
|
||||||
Expect(cfg.IntVar).To(Equal(int64(42)))
|
|
||||||
Expect(cfg.MySecretValue).To(Equal("veryverysecretkey"))
|
|
||||||
Expect(cfg.MyUsername).To(Equal("luzifer"))
|
|
||||||
Expect(cfg.SomeVar).To(Equal(""))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("With defaults from YAML data", func() {
|
|
||||||
BeforeEach(func() {
|
|
||||||
yamlData := []byte("---\nmy_secret_value: veryverysecretkey\nunknownkey: hi there\nint_var: 42\n")
|
|
||||||
SetVariableDefaults(VarDefaultsFromYAML(yamlData))
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values", func() {
|
|
||||||
Expect(cfg.IntVar).To(Equal(int64(42)))
|
|
||||||
Expect(cfg.MySecretValue).To(Equal("veryverysecretkey"))
|
|
||||||
Expect(cfg.MyUsername).To(Equal("luzifer"))
|
|
||||||
Expect(cfg.SomeVar).To(Equal(""))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("With defaults from YAML file", func() {
|
|
||||||
var tmp *os.File
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
|
||||||
tmp, _ = ioutil.TempFile("", "")
|
|
||||||
yamlData := "---\nmy_secret_value: veryverysecretkey\nunknownkey: hi there\nint_var: 42\n"
|
|
||||||
tmp.WriteString(yamlData)
|
|
||||||
SetVariableDefaults(VarDefaultsFromYAMLFile(tmp.Name()))
|
|
||||||
})
|
|
||||||
|
|
||||||
AfterEach(func() {
|
|
||||||
tmp.Close()
|
|
||||||
os.Remove(tmp.Name())
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values", func() {
|
|
||||||
Expect(cfg.IntVar).To(Equal(int64(42)))
|
|
||||||
Expect(cfg.MySecretValue).To(Equal("veryverysecretkey"))
|
|
||||||
Expect(cfg.MyUsername).To(Equal("luzifer"))
|
|
||||||
Expect(cfg.SomeVar).To(Equal(""))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("With defaults from invalid YAML data", func() {
|
|
||||||
BeforeEach(func() {
|
|
||||||
yamlData := []byte("---\nmy_secret_value = veryverysecretkey\nunknownkey = hi there\nint_var = 42\n")
|
|
||||||
SetVariableDefaults(VarDefaultsFromYAML(yamlData))
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values", func() {
|
|
||||||
Expect(cfg.IntVar).To(Equal(int64(23)))
|
|
||||||
Expect(cfg.MySecretValue).To(Equal("secret"))
|
|
||||||
Expect(cfg.MyUsername).To(Equal("luzifer"))
|
|
||||||
Expect(cfg.SomeVar).To(Equal(""))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("With defaults from non existent YAML file", func() {
|
|
||||||
BeforeEach(func() {
|
|
||||||
file := "/tmp/this_file_should_not_exist_146e26723r"
|
|
||||||
SetVariableDefaults(VarDefaultsFromYAMLFile(file))
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values", func() {
|
|
||||||
Expect(cfg.IntVar).To(Equal(int64(23)))
|
|
||||||
Expect(cfg.MySecretValue).To(Equal("secret"))
|
|
||||||
Expect(cfg.MyUsername).To(Equal("luzifer"))
|
|
||||||
Expect(cfg.SomeVar).To(Equal(""))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
22
vendor/github.com/cenkalti/backoff/.gitignore
generated
vendored
22
vendor/github.com/cenkalti/backoff/.gitignore
generated
vendored
|
@ -1,22 +0,0 @@
|
||||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
|
||||||
*.o
|
|
||||||
*.a
|
|
||||||
*.so
|
|
||||||
|
|
||||||
# Folders
|
|
||||||
_obj
|
|
||||||
_test
|
|
||||||
|
|
||||||
# Architecture specific extensions/prefixes
|
|
||||||
*.[568vq]
|
|
||||||
[568vq].out
|
|
||||||
|
|
||||||
*.cgo1.go
|
|
||||||
*.cgo2.c
|
|
||||||
_cgo_defun.c
|
|
||||||
_cgo_gotypes.go
|
|
||||||
_cgo_export.*
|
|
||||||
|
|
||||||
_testmain.go
|
|
||||||
|
|
||||||
*.exe
|
|
9
vendor/github.com/cenkalti/backoff/.travis.yml
generated
vendored
9
vendor/github.com/cenkalti/backoff/.travis.yml
generated
vendored
|
@ -1,9 +0,0 @@
|
||||||
language: go
|
|
||||||
go:
|
|
||||||
- 1.3.3
|
|
||||||
- tip
|
|
||||||
before_install:
|
|
||||||
- go get github.com/mattn/goveralls
|
|
||||||
- go get golang.org/x/tools/cmd/cover
|
|
||||||
script:
|
|
||||||
- $HOME/gopath/bin/goveralls -service=travis-ci
|
|
20
vendor/github.com/cenkalti/backoff/LICENSE
generated
vendored
20
vendor/github.com/cenkalti/backoff/LICENSE
generated
vendored
|
@ -1,20 +0,0 @@
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2014 Cenk Altı
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
this software and associated documentation files (the "Software"), to deal in
|
|
||||||
the Software without restriction, including without limitation the rights to
|
|
||||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
||||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
||||||
subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
||||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
||||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
||||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
||||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
30
vendor/github.com/cenkalti/backoff/README.md
generated
vendored
30
vendor/github.com/cenkalti/backoff/README.md
generated
vendored
|
@ -1,30 +0,0 @@
|
||||||
# Exponential Backoff [![GoDoc][godoc image]][godoc] [![Build Status][travis image]][travis] [![Coverage Status][coveralls image]][coveralls]
|
|
||||||
|
|
||||||
This is a Go port of the exponential backoff algorithm from [Google's HTTP Client Library for Java][google-http-java-client].
|
|
||||||
|
|
||||||
[Exponential backoff][exponential backoff wiki]
|
|
||||||
is an algorithm that uses feedback to multiplicatively decrease the rate of some process,
|
|
||||||
in order to gradually find an acceptable rate.
|
|
||||||
The retries exponentially increase and stop increasing when a certain threshold is met.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
See https://godoc.org/github.com/cenkalti/backoff#pkg-examples
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
* I would like to keep this library as small as possible.
|
|
||||||
* Please don't send a PR without opening an issue and discussing it first.
|
|
||||||
* If proposed change is not a common use case, I will probably not accept it.
|
|
||||||
|
|
||||||
[godoc]: https://godoc.org/github.com/cenkalti/backoff
|
|
||||||
[godoc image]: https://godoc.org/github.com/cenkalti/backoff?status.png
|
|
||||||
[travis]: https://travis-ci.org/cenkalti/backoff
|
|
||||||
[travis image]: https://travis-ci.org/cenkalti/backoff.png?branch=master
|
|
||||||
[coveralls]: https://coveralls.io/github/cenkalti/backoff?branch=master
|
|
||||||
[coveralls image]: https://coveralls.io/repos/github/cenkalti/backoff/badge.svg?branch=master
|
|
||||||
|
|
||||||
[google-http-java-client]: https://github.com/google/google-http-java-client
|
|
||||||
[exponential backoff wiki]: http://en.wikipedia.org/wiki/Exponential_backoff
|
|
||||||
|
|
||||||
[advanced example]: https://godoc.org/github.com/cenkalti/backoff#example_
|
|
66
vendor/github.com/cenkalti/backoff/backoff.go
generated
vendored
66
vendor/github.com/cenkalti/backoff/backoff.go
generated
vendored
|
@ -1,66 +0,0 @@
|
||||||
// Package backoff implements backoff algorithms for retrying operations.
|
|
||||||
//
|
|
||||||
// Use Retry function for retrying operations that may fail.
|
|
||||||
// If Retry does not meet your needs,
|
|
||||||
// copy/paste the function into your project and modify as you wish.
|
|
||||||
//
|
|
||||||
// There is also Ticker type similar to time.Ticker.
|
|
||||||
// You can use it if you need to work with channels.
|
|
||||||
//
|
|
||||||
// See Examples section below for usage examples.
|
|
||||||
package backoff
|
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
// BackOff is a backoff policy for retrying an operation.
|
|
||||||
type BackOff interface {
|
|
||||||
// NextBackOff returns the duration to wait before retrying the operation,
|
|
||||||
// or backoff.Stop to indicate that no more retries should be made.
|
|
||||||
//
|
|
||||||
// Example usage:
|
|
||||||
//
|
|
||||||
// duration := backoff.NextBackOff();
|
|
||||||
// if (duration == backoff.Stop) {
|
|
||||||
// // Do not retry operation.
|
|
||||||
// } else {
|
|
||||||
// // Sleep for duration and retry operation.
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
NextBackOff() time.Duration
|
|
||||||
|
|
||||||
// Reset to initial state.
|
|
||||||
Reset()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop indicates that no more retries should be made for use in NextBackOff().
|
|
||||||
const Stop time.Duration = -1
|
|
||||||
|
|
||||||
// ZeroBackOff is a fixed backoff policy whose backoff time is always zero,
|
|
||||||
// meaning that the operation is retried immediately without waiting, indefinitely.
|
|
||||||
type ZeroBackOff struct{}
|
|
||||||
|
|
||||||
func (b *ZeroBackOff) Reset() {}
|
|
||||||
|
|
||||||
func (b *ZeroBackOff) NextBackOff() time.Duration { return 0 }
|
|
||||||
|
|
||||||
// StopBackOff is a fixed backoff policy that always returns backoff.Stop for
|
|
||||||
// NextBackOff(), meaning that the operation should never be retried.
|
|
||||||
type StopBackOff struct{}
|
|
||||||
|
|
||||||
func (b *StopBackOff) Reset() {}
|
|
||||||
|
|
||||||
func (b *StopBackOff) NextBackOff() time.Duration { return Stop }
|
|
||||||
|
|
||||||
// ConstantBackOff is a backoff policy that always returns the same backoff delay.
|
|
||||||
// This is in contrast to an exponential backoff policy,
|
|
||||||
// which returns a delay that grows longer as you call NextBackOff() over and over again.
|
|
||||||
type ConstantBackOff struct {
|
|
||||||
Interval time.Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *ConstantBackOff) Reset() {}
|
|
||||||
func (b *ConstantBackOff) NextBackOff() time.Duration { return b.Interval }
|
|
||||||
|
|
||||||
func NewConstantBackOff(d time.Duration) *ConstantBackOff {
|
|
||||||
return &ConstantBackOff{Interval: d}
|
|
||||||
}
|
|
27
vendor/github.com/cenkalti/backoff/backoff_test.go
generated
vendored
27
vendor/github.com/cenkalti/backoff/backoff_test.go
generated
vendored
|
@ -1,27 +0,0 @@
|
||||||
package backoff
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestNextBackOffMillis(t *testing.T) {
|
|
||||||
subtestNextBackOff(t, 0, new(ZeroBackOff))
|
|
||||||
subtestNextBackOff(t, Stop, new(StopBackOff))
|
|
||||||
}
|
|
||||||
|
|
||||||
func subtestNextBackOff(t *testing.T, expectedValue time.Duration, backOffPolicy BackOff) {
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
next := backOffPolicy.NextBackOff()
|
|
||||||
if next != expectedValue {
|
|
||||||
t.Errorf("got: %d expected: %d", next, expectedValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConstantBackOff(t *testing.T) {
|
|
||||||
backoff := NewConstantBackOff(time.Second)
|
|
||||||
if backoff.NextBackOff() != time.Second {
|
|
||||||
t.Error("invalid interval")
|
|
||||||
}
|
|
||||||
}
|
|
60
vendor/github.com/cenkalti/backoff/context.go
generated
vendored
60
vendor/github.com/cenkalti/backoff/context.go
generated
vendored
|
@ -1,60 +0,0 @@
|
||||||
package backoff
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
)
|
|
||||||
|
|
||||||
// BackOffContext is a backoff policy that stops retrying after the context
|
|
||||||
// is canceled.
|
|
||||||
type BackOffContext interface {
|
|
||||||
BackOff
|
|
||||||
Context() context.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
type backOffContext struct {
|
|
||||||
BackOff
|
|
||||||
ctx context.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithContext returns a BackOffContext with context ctx
|
|
||||||
//
|
|
||||||
// ctx must not be nil
|
|
||||||
func WithContext(b BackOff, ctx context.Context) BackOffContext {
|
|
||||||
if ctx == nil {
|
|
||||||
panic("nil context")
|
|
||||||
}
|
|
||||||
|
|
||||||
if b, ok := b.(*backOffContext); ok {
|
|
||||||
return &backOffContext{
|
|
||||||
BackOff: b.BackOff,
|
|
||||||
ctx: ctx,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &backOffContext{
|
|
||||||
BackOff: b,
|
|
||||||
ctx: ctx,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ensureContext(b BackOff) BackOffContext {
|
|
||||||
if cb, ok := b.(BackOffContext); ok {
|
|
||||||
return cb
|
|
||||||
}
|
|
||||||
return WithContext(b, context.Background())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *backOffContext) Context() context.Context {
|
|
||||||
return b.ctx
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *backOffContext) NextBackOff() time.Duration {
|
|
||||||
select {
|
|
||||||
case <-b.Context().Done():
|
|
||||||
return Stop
|
|
||||||
default:
|
|
||||||
return b.BackOff.NextBackOff()
|
|
||||||
}
|
|
||||||
}
|
|
26
vendor/github.com/cenkalti/backoff/context_test.go
generated
vendored
26
vendor/github.com/cenkalti/backoff/context_test.go
generated
vendored
|
@ -1,26 +0,0 @@
|
||||||
package backoff
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestContext(t *testing.T) {
|
|
||||||
b := NewConstantBackOff(time.Millisecond)
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
cb := WithContext(b, ctx)
|
|
||||||
|
|
||||||
if cb.Context() != ctx {
|
|
||||||
t.Error("invalid context")
|
|
||||||
}
|
|
||||||
|
|
||||||
cancel()
|
|
||||||
|
|
||||||
if cb.NextBackOff() != Stop {
|
|
||||||
t.Error("invalid next back off")
|
|
||||||
}
|
|
||||||
}
|
|
73
vendor/github.com/cenkalti/backoff/example_test.go
generated
vendored
73
vendor/github.com/cenkalti/backoff/example_test.go
generated
vendored
|
@ -1,73 +0,0 @@
|
||||||
package backoff
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ExampleRetry() {
|
|
||||||
// An operation that may fail.
|
|
||||||
operation := func() error {
|
|
||||||
return nil // or an error
|
|
||||||
}
|
|
||||||
|
|
||||||
err := Retry(operation, NewExponentialBackOff())
|
|
||||||
if err != nil {
|
|
||||||
// Handle error.
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Operation is successful.
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleRetryContext() {
|
|
||||||
// A context
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
// An operation that may fail.
|
|
||||||
operation := func() error {
|
|
||||||
return nil // or an error
|
|
||||||
}
|
|
||||||
|
|
||||||
b := WithContext(NewExponentialBackOff(), ctx)
|
|
||||||
|
|
||||||
err := Retry(operation, b)
|
|
||||||
if err != nil {
|
|
||||||
// Handle error.
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Operation is successful.
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleTicker() {
|
|
||||||
// An operation that may fail.
|
|
||||||
operation := func() error {
|
|
||||||
return nil // or an error
|
|
||||||
}
|
|
||||||
|
|
||||||
ticker := NewTicker(NewExponentialBackOff())
|
|
||||||
|
|
||||||
var err error
|
|
||||||
|
|
||||||
// Ticks will continue to arrive when the previous operation is still running,
|
|
||||||
// so operations that take a while to fail could run in quick succession.
|
|
||||||
for _ = range ticker.C {
|
|
||||||
if err = operation(); err != nil {
|
|
||||||
log.Println(err, "will retry...")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
ticker.Stop()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
// Operation has failed.
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Operation is successful.
|
|
||||||
return
|
|
||||||
}
|
|
156
vendor/github.com/cenkalti/backoff/exponential.go
generated
vendored
156
vendor/github.com/cenkalti/backoff/exponential.go
generated
vendored
|
@ -1,156 +0,0 @@
|
||||||
package backoff
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/rand"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
/*
|
|
||||||
ExponentialBackOff is a backoff implementation that increases the backoff
|
|
||||||
period for each retry attempt using a randomization function that grows exponentially.
|
|
||||||
|
|
||||||
NextBackOff() is calculated using the following formula:
|
|
||||||
|
|
||||||
randomized interval =
|
|
||||||
RetryInterval * (random value in range [1 - RandomizationFactor, 1 + RandomizationFactor])
|
|
||||||
|
|
||||||
In other words NextBackOff() will range between the randomization factor
|
|
||||||
percentage below and above the retry interval.
|
|
||||||
|
|
||||||
For example, given the following parameters:
|
|
||||||
|
|
||||||
RetryInterval = 2
|
|
||||||
RandomizationFactor = 0.5
|
|
||||||
Multiplier = 2
|
|
||||||
|
|
||||||
the actual backoff period used in the next retry attempt will range between 1 and 3 seconds,
|
|
||||||
multiplied by the exponential, that is, between 2 and 6 seconds.
|
|
||||||
|
|
||||||
Note: MaxInterval caps the RetryInterval and not the randomized interval.
|
|
||||||
|
|
||||||
If the time elapsed since an ExponentialBackOff instance is created goes past the
|
|
||||||
MaxElapsedTime, then the method NextBackOff() starts returning backoff.Stop.
|
|
||||||
|
|
||||||
The elapsed time can be reset by calling Reset().
|
|
||||||
|
|
||||||
Example: Given the following default arguments, for 10 tries the sequence will be,
|
|
||||||
and assuming we go over the MaxElapsedTime on the 10th try:
|
|
||||||
|
|
||||||
Request # RetryInterval (seconds) Randomized Interval (seconds)
|
|
||||||
|
|
||||||
1 0.5 [0.25, 0.75]
|
|
||||||
2 0.75 [0.375, 1.125]
|
|
||||||
3 1.125 [0.562, 1.687]
|
|
||||||
4 1.687 [0.8435, 2.53]
|
|
||||||
5 2.53 [1.265, 3.795]
|
|
||||||
6 3.795 [1.897, 5.692]
|
|
||||||
7 5.692 [2.846, 8.538]
|
|
||||||
8 8.538 [4.269, 12.807]
|
|
||||||
9 12.807 [6.403, 19.210]
|
|
||||||
10 19.210 backoff.Stop
|
|
||||||
|
|
||||||
Note: Implementation is not thread-safe.
|
|
||||||
*/
|
|
||||||
type ExponentialBackOff struct {
|
|
||||||
InitialInterval time.Duration
|
|
||||||
RandomizationFactor float64
|
|
||||||
Multiplier float64
|
|
||||||
MaxInterval time.Duration
|
|
||||||
// After MaxElapsedTime the ExponentialBackOff stops.
|
|
||||||
// It never stops if MaxElapsedTime == 0.
|
|
||||||
MaxElapsedTime time.Duration
|
|
||||||
Clock Clock
|
|
||||||
|
|
||||||
currentInterval time.Duration
|
|
||||||
startTime time.Time
|
|
||||||
random *rand.Rand
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clock is an interface that returns current time for BackOff.
|
|
||||||
type Clock interface {
|
|
||||||
Now() time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default values for ExponentialBackOff.
|
|
||||||
const (
|
|
||||||
DefaultInitialInterval = 500 * time.Millisecond
|
|
||||||
DefaultRandomizationFactor = 0.5
|
|
||||||
DefaultMultiplier = 1.5
|
|
||||||
DefaultMaxInterval = 60 * time.Second
|
|
||||||
DefaultMaxElapsedTime = 15 * time.Minute
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewExponentialBackOff creates an instance of ExponentialBackOff using default values.
|
|
||||||
func NewExponentialBackOff() *ExponentialBackOff {
|
|
||||||
b := &ExponentialBackOff{
|
|
||||||
InitialInterval: DefaultInitialInterval,
|
|
||||||
RandomizationFactor: DefaultRandomizationFactor,
|
|
||||||
Multiplier: DefaultMultiplier,
|
|
||||||
MaxInterval: DefaultMaxInterval,
|
|
||||||
MaxElapsedTime: DefaultMaxElapsedTime,
|
|
||||||
Clock: SystemClock,
|
|
||||||
random: rand.New(rand.NewSource(time.Now().UnixNano())),
|
|
||||||
}
|
|
||||||
b.Reset()
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
type systemClock struct{}
|
|
||||||
|
|
||||||
func (t systemClock) Now() time.Time {
|
|
||||||
return time.Now()
|
|
||||||
}
|
|
||||||
|
|
||||||
// SystemClock implements Clock interface that uses time.Now().
|
|
||||||
var SystemClock = systemClock{}
|
|
||||||
|
|
||||||
// Reset the interval back to the initial retry interval and restarts the timer.
|
|
||||||
func (b *ExponentialBackOff) Reset() {
|
|
||||||
b.currentInterval = b.InitialInterval
|
|
||||||
b.startTime = b.Clock.Now()
|
|
||||||
}
|
|
||||||
|
|
||||||
// NextBackOff calculates the next backoff interval using the formula:
|
|
||||||
// Randomized interval = RetryInterval +/- (RandomizationFactor * RetryInterval)
|
|
||||||
func (b *ExponentialBackOff) NextBackOff() time.Duration {
|
|
||||||
// Make sure we have not gone over the maximum elapsed time.
|
|
||||||
if b.MaxElapsedTime != 0 && b.GetElapsedTime() > b.MaxElapsedTime {
|
|
||||||
return Stop
|
|
||||||
}
|
|
||||||
defer b.incrementCurrentInterval()
|
|
||||||
if b.random == nil {
|
|
||||||
b.random = rand.New(rand.NewSource(time.Now().UnixNano()))
|
|
||||||
}
|
|
||||||
return getRandomValueFromInterval(b.RandomizationFactor, b.random.Float64(), b.currentInterval)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetElapsedTime returns the elapsed time since an ExponentialBackOff instance
|
|
||||||
// is created and is reset when Reset() is called.
|
|
||||||
//
|
|
||||||
// The elapsed time is computed using time.Now().UnixNano().
|
|
||||||
func (b *ExponentialBackOff) GetElapsedTime() time.Duration {
|
|
||||||
return b.Clock.Now().Sub(b.startTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Increments the current interval by multiplying it with the multiplier.
|
|
||||||
func (b *ExponentialBackOff) incrementCurrentInterval() {
|
|
||||||
// Check for overflow, if overflow is detected set the current interval to the max interval.
|
|
||||||
if float64(b.currentInterval) >= float64(b.MaxInterval)/b.Multiplier {
|
|
||||||
b.currentInterval = b.MaxInterval
|
|
||||||
} else {
|
|
||||||
b.currentInterval = time.Duration(float64(b.currentInterval) * b.Multiplier)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a random value from the following interval:
|
|
||||||
// [randomizationFactor * currentInterval, randomizationFactor * currentInterval].
|
|
||||||
func getRandomValueFromInterval(randomizationFactor, random float64, currentInterval time.Duration) time.Duration {
|
|
||||||
var delta = randomizationFactor * float64(currentInterval)
|
|
||||||
var minInterval = float64(currentInterval) - delta
|
|
||||||
var maxInterval = float64(currentInterval) + delta
|
|
||||||
|
|
||||||
// Get a random value from the range [minInterval, maxInterval].
|
|
||||||
// The formula used below has a +1 because if the minInterval is 1 and the maxInterval is 3 then
|
|
||||||
// we want a 33% chance for selecting either 1, 2 or 3.
|
|
||||||
return time.Duration(minInterval + (random * (maxInterval - minInterval + 1)))
|
|
||||||
}
|
|
108
vendor/github.com/cenkalti/backoff/exponential_test.go
generated
vendored
108
vendor/github.com/cenkalti/backoff/exponential_test.go
generated
vendored
|
@ -1,108 +0,0 @@
|
||||||
package backoff
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestBackOff(t *testing.T) {
|
|
||||||
var (
|
|
||||||
testInitialInterval = 500 * time.Millisecond
|
|
||||||
testRandomizationFactor = 0.1
|
|
||||||
testMultiplier = 2.0
|
|
||||||
testMaxInterval = 5 * time.Second
|
|
||||||
testMaxElapsedTime = 15 * time.Minute
|
|
||||||
)
|
|
||||||
|
|
||||||
exp := NewExponentialBackOff()
|
|
||||||
exp.InitialInterval = testInitialInterval
|
|
||||||
exp.RandomizationFactor = testRandomizationFactor
|
|
||||||
exp.Multiplier = testMultiplier
|
|
||||||
exp.MaxInterval = testMaxInterval
|
|
||||||
exp.MaxElapsedTime = testMaxElapsedTime
|
|
||||||
exp.Reset()
|
|
||||||
|
|
||||||
var expectedResults = []time.Duration{500, 1000, 2000, 4000, 5000, 5000, 5000, 5000, 5000, 5000}
|
|
||||||
for i, d := range expectedResults {
|
|
||||||
expectedResults[i] = d * time.Millisecond
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, expected := range expectedResults {
|
|
||||||
assertEquals(t, expected, exp.currentInterval)
|
|
||||||
// Assert that the next backoff falls in the expected range.
|
|
||||||
var minInterval = expected - time.Duration(testRandomizationFactor*float64(expected))
|
|
||||||
var maxInterval = expected + time.Duration(testRandomizationFactor*float64(expected))
|
|
||||||
var actualInterval = exp.NextBackOff()
|
|
||||||
if !(minInterval <= actualInterval && actualInterval <= maxInterval) {
|
|
||||||
t.Error("error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetRandomizedInterval(t *testing.T) {
|
|
||||||
// 33% chance of being 1.
|
|
||||||
assertEquals(t, 1, getRandomValueFromInterval(0.5, 0, 2))
|
|
||||||
assertEquals(t, 1, getRandomValueFromInterval(0.5, 0.33, 2))
|
|
||||||
// 33% chance of being 2.
|
|
||||||
assertEquals(t, 2, getRandomValueFromInterval(0.5, 0.34, 2))
|
|
||||||
assertEquals(t, 2, getRandomValueFromInterval(0.5, 0.66, 2))
|
|
||||||
// 33% chance of being 3.
|
|
||||||
assertEquals(t, 3, getRandomValueFromInterval(0.5, 0.67, 2))
|
|
||||||
assertEquals(t, 3, getRandomValueFromInterval(0.5, 0.99, 2))
|
|
||||||
}
|
|
||||||
|
|
||||||
type TestClock struct {
|
|
||||||
i time.Duration
|
|
||||||
start time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *TestClock) Now() time.Time {
|
|
||||||
t := c.start.Add(c.i)
|
|
||||||
c.i += time.Second
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetElapsedTime(t *testing.T) {
|
|
||||||
var exp = NewExponentialBackOff()
|
|
||||||
exp.Clock = &TestClock{}
|
|
||||||
exp.Reset()
|
|
||||||
|
|
||||||
var elapsedTime = exp.GetElapsedTime()
|
|
||||||
if elapsedTime != time.Second {
|
|
||||||
t.Errorf("elapsedTime=%d", elapsedTime)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMaxElapsedTime(t *testing.T) {
|
|
||||||
var exp = NewExponentialBackOff()
|
|
||||||
exp.Clock = &TestClock{start: time.Time{}.Add(10000 * time.Second)}
|
|
||||||
// Change the currentElapsedTime to be 0 ensuring that the elapsed time will be greater
|
|
||||||
// than the max elapsed time.
|
|
||||||
exp.startTime = time.Time{}
|
|
||||||
assertEquals(t, Stop, exp.NextBackOff())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBackOffOverflow(t *testing.T) {
|
|
||||||
var (
|
|
||||||
testInitialInterval time.Duration = math.MaxInt64 / 2
|
|
||||||
testMaxInterval time.Duration = math.MaxInt64
|
|
||||||
testMultiplier = 2.1
|
|
||||||
)
|
|
||||||
|
|
||||||
exp := NewExponentialBackOff()
|
|
||||||
exp.InitialInterval = testInitialInterval
|
|
||||||
exp.Multiplier = testMultiplier
|
|
||||||
exp.MaxInterval = testMaxInterval
|
|
||||||
exp.Reset()
|
|
||||||
|
|
||||||
exp.NextBackOff()
|
|
||||||
// Assert that when an overflow is possible the current varerval time.Duration is set to the max varerval time.Duration .
|
|
||||||
assertEquals(t, testMaxInterval, exp.currentInterval)
|
|
||||||
}
|
|
||||||
|
|
||||||
func assertEquals(t *testing.T, expected, value time.Duration) {
|
|
||||||
if expected != value {
|
|
||||||
t.Errorf("got: %d, expected: %d", value, expected)
|
|
||||||
}
|
|
||||||
}
|
|
78
vendor/github.com/cenkalti/backoff/retry.go
generated
vendored
78
vendor/github.com/cenkalti/backoff/retry.go
generated
vendored
|
@ -1,78 +0,0 @@
|
||||||
package backoff
|
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
// An Operation is executing by Retry() or RetryNotify().
|
|
||||||
// The operation will be retried using a backoff policy if it returns an error.
|
|
||||||
type Operation func() error
|
|
||||||
|
|
||||||
// Notify is a notify-on-error function. It receives an operation error and
|
|
||||||
// backoff delay if the operation failed (with an error).
|
|
||||||
//
|
|
||||||
// NOTE that if the backoff policy stated to stop retrying,
|
|
||||||
// the notify function isn't called.
|
|
||||||
type Notify func(error, time.Duration)
|
|
||||||
|
|
||||||
// Retry the operation o until it does not return error or BackOff stops.
|
|
||||||
// o is guaranteed to be run at least once.
|
|
||||||
// It is the caller's responsibility to reset b after Retry returns.
|
|
||||||
//
|
|
||||||
// If o returns a *PermanentError, the operation is not retried, and the
|
|
||||||
// wrapped error is returned.
|
|
||||||
//
|
|
||||||
// Retry sleeps the goroutine for the duration returned by BackOff after a
|
|
||||||
// failed operation returns.
|
|
||||||
func Retry(o Operation, b BackOff) error { return RetryNotify(o, b, nil) }
|
|
||||||
|
|
||||||
// RetryNotify calls notify function with the error and wait duration
|
|
||||||
// for each failed attempt before sleep.
|
|
||||||
func RetryNotify(operation Operation, b BackOff, notify Notify) error {
|
|
||||||
var err error
|
|
||||||
var next time.Duration
|
|
||||||
|
|
||||||
cb := ensureContext(b)
|
|
||||||
|
|
||||||
b.Reset()
|
|
||||||
for {
|
|
||||||
if err = operation(); err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if permanent, ok := err.(*PermanentError); ok {
|
|
||||||
return permanent.Err
|
|
||||||
}
|
|
||||||
|
|
||||||
if next = b.NextBackOff(); next == Stop {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if notify != nil {
|
|
||||||
notify(err, next)
|
|
||||||
}
|
|
||||||
|
|
||||||
t := time.NewTimer(next)
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-cb.Context().Done():
|
|
||||||
t.Stop()
|
|
||||||
return err
|
|
||||||
case <-t.C:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PermanentError signals that the operation should not be retried.
|
|
||||||
type PermanentError struct {
|
|
||||||
Err error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *PermanentError) Error() string {
|
|
||||||
return e.Err.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Permanent wraps the given err in a *PermanentError.
|
|
||||||
func Permanent(err error) *PermanentError {
|
|
||||||
return &PermanentError{
|
|
||||||
Err: err,
|
|
||||||
}
|
|
||||||
}
|
|
99
vendor/github.com/cenkalti/backoff/retry_test.go
generated
vendored
99
vendor/github.com/cenkalti/backoff/retry_test.go
generated
vendored
|
@ -1,99 +0,0 @@
|
||||||
package backoff
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestRetry(t *testing.T) {
|
|
||||||
const successOn = 3
|
|
||||||
var i = 0
|
|
||||||
|
|
||||||
// This function is successful on "successOn" calls.
|
|
||||||
f := func() error {
|
|
||||||
i++
|
|
||||||
log.Printf("function is called %d. time\n", i)
|
|
||||||
|
|
||||||
if i == successOn {
|
|
||||||
log.Println("OK")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Println("error")
|
|
||||||
return errors.New("error")
|
|
||||||
}
|
|
||||||
|
|
||||||
err := Retry(f, NewExponentialBackOff())
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error: %s", err.Error())
|
|
||||||
}
|
|
||||||
if i != successOn {
|
|
||||||
t.Errorf("invalid number of retries: %d", i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRetryContext(t *testing.T) {
|
|
||||||
var cancelOn = 3
|
|
||||||
var i = 0
|
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
// This function cancels context on "cancelOn" calls.
|
|
||||||
f := func() error {
|
|
||||||
i++
|
|
||||||
log.Printf("function is called %d. time\n", i)
|
|
||||||
|
|
||||||
// cancelling the context in the operation function is not a typical
|
|
||||||
// use-case, however it allows to get predictable test results.
|
|
||||||
if i == cancelOn {
|
|
||||||
cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Println("error")
|
|
||||||
return fmt.Errorf("error (%d)", i)
|
|
||||||
}
|
|
||||||
|
|
||||||
err := Retry(f, WithContext(NewConstantBackOff(time.Millisecond), ctx))
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("error is unexpectedly nil")
|
|
||||||
}
|
|
||||||
if err.Error() != "error (3)" {
|
|
||||||
t.Errorf("unexpected error: %s", err.Error())
|
|
||||||
}
|
|
||||||
if i != cancelOn {
|
|
||||||
t.Errorf("invalid number of retries: %d", i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRetryPermenent(t *testing.T) {
|
|
||||||
const permanentOn = 3
|
|
||||||
var i = 0
|
|
||||||
|
|
||||||
// This function fails permanently after permanentOn tries
|
|
||||||
f := func() error {
|
|
||||||
i++
|
|
||||||
log.Printf("function is called %d. time\n", i)
|
|
||||||
|
|
||||||
if i == permanentOn {
|
|
||||||
log.Println("permanent error")
|
|
||||||
return Permanent(errors.New("permanent error"))
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Println("error")
|
|
||||||
return errors.New("error")
|
|
||||||
}
|
|
||||||
|
|
||||||
err := Retry(f, NewExponentialBackOff())
|
|
||||||
if err == nil || err.Error() != "permanent error" {
|
|
||||||
t.Errorf("unexpected error: %s", err)
|
|
||||||
}
|
|
||||||
if i != permanentOn {
|
|
||||||
t.Errorf("invalid number of retries: %d", i)
|
|
||||||
}
|
|
||||||
}
|
|
81
vendor/github.com/cenkalti/backoff/ticker.go
generated
vendored
81
vendor/github.com/cenkalti/backoff/ticker.go
generated
vendored
|
@ -1,81 +0,0 @@
|
||||||
package backoff
|
|
||||||
|
|
||||||
import (
|
|
||||||
"runtime"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Ticker holds a channel that delivers `ticks' of a clock at times reported by a BackOff.
|
|
||||||
//
|
|
||||||
// Ticks will continue to arrive when the previous operation is still running,
|
|
||||||
// so operations that take a while to fail could run in quick succession.
|
|
||||||
type Ticker struct {
|
|
||||||
C <-chan time.Time
|
|
||||||
c chan time.Time
|
|
||||||
b BackOffContext
|
|
||||||
stop chan struct{}
|
|
||||||
stopOnce sync.Once
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewTicker returns a new Ticker containing a channel that will send the time at times
|
|
||||||
// specified by the BackOff argument. Ticker is guaranteed to tick at least once.
|
|
||||||
// The channel is closed when Stop method is called or BackOff stops.
|
|
||||||
func NewTicker(b BackOff) *Ticker {
|
|
||||||
c := make(chan time.Time)
|
|
||||||
t := &Ticker{
|
|
||||||
C: c,
|
|
||||||
c: c,
|
|
||||||
b: ensureContext(b),
|
|
||||||
stop: make(chan struct{}),
|
|
||||||
}
|
|
||||||
go t.run()
|
|
||||||
runtime.SetFinalizer(t, (*Ticker).Stop)
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop turns off a ticker. After Stop, no more ticks will be sent.
|
|
||||||
func (t *Ticker) Stop() {
|
|
||||||
t.stopOnce.Do(func() { close(t.stop) })
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Ticker) run() {
|
|
||||||
c := t.c
|
|
||||||
defer close(c)
|
|
||||||
t.b.Reset()
|
|
||||||
|
|
||||||
// Ticker is guaranteed to tick at least once.
|
|
||||||
afterC := t.send(time.Now())
|
|
||||||
|
|
||||||
for {
|
|
||||||
if afterC == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
case tick := <-afterC:
|
|
||||||
afterC = t.send(tick)
|
|
||||||
case <-t.stop:
|
|
||||||
t.c = nil // Prevent future ticks from being sent to the channel.
|
|
||||||
return
|
|
||||||
case <-t.b.Context().Done():
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Ticker) send(tick time.Time) <-chan time.Time {
|
|
||||||
select {
|
|
||||||
case t.c <- tick:
|
|
||||||
case <-t.stop:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
next := t.b.NextBackOff()
|
|
||||||
if next == Stop {
|
|
||||||
t.Stop()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return time.After(next)
|
|
||||||
}
|
|
94
vendor/github.com/cenkalti/backoff/ticker_test.go
generated
vendored
94
vendor/github.com/cenkalti/backoff/ticker_test.go
generated
vendored
|
@ -1,94 +0,0 @@
|
||||||
package backoff
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestTicker(t *testing.T) {
|
|
||||||
const successOn = 3
|
|
||||||
var i = 0
|
|
||||||
|
|
||||||
// This function is successful on "successOn" calls.
|
|
||||||
f := func() error {
|
|
||||||
i++
|
|
||||||
log.Printf("function is called %d. time\n", i)
|
|
||||||
|
|
||||||
if i == successOn {
|
|
||||||
log.Println("OK")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Println("error")
|
|
||||||
return errors.New("error")
|
|
||||||
}
|
|
||||||
|
|
||||||
b := NewExponentialBackOff()
|
|
||||||
ticker := NewTicker(b)
|
|
||||||
|
|
||||||
var err error
|
|
||||||
for _ = range ticker.C {
|
|
||||||
if err = f(); err != nil {
|
|
||||||
t.Log(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error: %s", err.Error())
|
|
||||||
}
|
|
||||||
if i != successOn {
|
|
||||||
t.Errorf("invalid number of retries: %d", i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTickerContext(t *testing.T) {
|
|
||||||
const cancelOn = 3
|
|
||||||
var i = 0
|
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
// This function cancels context on "cancelOn" calls.
|
|
||||||
f := func() error {
|
|
||||||
i++
|
|
||||||
log.Printf("function is called %d. time\n", i)
|
|
||||||
|
|
||||||
// cancelling the context in the operation function is not a typical
|
|
||||||
// use-case, however it allows to get predictable test results.
|
|
||||||
if i == cancelOn {
|
|
||||||
cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Println("error")
|
|
||||||
return fmt.Errorf("error (%d)", i)
|
|
||||||
}
|
|
||||||
|
|
||||||
b := WithContext(NewConstantBackOff(time.Millisecond), ctx)
|
|
||||||
ticker := NewTicker(b)
|
|
||||||
|
|
||||||
var err error
|
|
||||||
for _ = range ticker.C {
|
|
||||||
if err = f(); err != nil {
|
|
||||||
t.Log(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("error is unexpectedly nil")
|
|
||||||
}
|
|
||||||
if err.Error() != "error (3)" {
|
|
||||||
t.Errorf("unexpected error: %s", err.Error())
|
|
||||||
}
|
|
||||||
if i != cancelOn {
|
|
||||||
t.Errorf("invalid number of retries: %d", i)
|
|
||||||
}
|
|
||||||
}
|
|
35
vendor/github.com/cenkalti/backoff/tries.go
generated
vendored
35
vendor/github.com/cenkalti/backoff/tries.go
generated
vendored
|
@ -1,35 +0,0 @@
|
||||||
package backoff
|
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
/*
|
|
||||||
WithMaxTries creates a wrapper around another BackOff, which will
|
|
||||||
return Stop if NextBackOff() has been called too many times since
|
|
||||||
the last time Reset() was called
|
|
||||||
|
|
||||||
Note: Implementation is not thread-safe.
|
|
||||||
*/
|
|
||||||
func WithMaxTries(b BackOff, max uint64) BackOff {
|
|
||||||
return &backOffTries{delegate: b, maxTries: max}
|
|
||||||
}
|
|
||||||
|
|
||||||
type backOffTries struct {
|
|
||||||
delegate BackOff
|
|
||||||
maxTries uint64
|
|
||||||
numTries uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *backOffTries) NextBackOff() time.Duration {
|
|
||||||
if b.maxTries > 0 {
|
|
||||||
if b.maxTries <= b.numTries {
|
|
||||||
return Stop
|
|
||||||
}
|
|
||||||
b.numTries++
|
|
||||||
}
|
|
||||||
return b.delegate.NextBackOff()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *backOffTries) Reset() {
|
|
||||||
b.numTries = 0
|
|
||||||
b.delegate.Reset()
|
|
||||||
}
|
|
55
vendor/github.com/cenkalti/backoff/tries_test.go
generated
vendored
55
vendor/github.com/cenkalti/backoff/tries_test.go
generated
vendored
|
@ -1,55 +0,0 @@
|
||||||
package backoff
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/rand"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestMaxTriesHappy(t *testing.T) {
|
|
||||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
|
||||||
max := 17 + r.Intn(13)
|
|
||||||
bo := WithMaxTries(&ZeroBackOff{}, uint64(max))
|
|
||||||
|
|
||||||
// Load up the tries count, but reset should clear the record
|
|
||||||
for ix := 0; ix < max/2; ix++ {
|
|
||||||
bo.NextBackOff()
|
|
||||||
}
|
|
||||||
bo.Reset()
|
|
||||||
|
|
||||||
// Now fill the tries count all the way up
|
|
||||||
for ix := 0; ix < max; ix++ {
|
|
||||||
d := bo.NextBackOff()
|
|
||||||
if d == Stop {
|
|
||||||
t.Errorf("returned Stop on try %d", ix)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We have now called the BackOff max number of times, we expect
|
|
||||||
// the next result to be Stop, even if we try it multiple times
|
|
||||||
for ix := 0; ix < 7; ix++ {
|
|
||||||
d := bo.NextBackOff()
|
|
||||||
if d != Stop {
|
|
||||||
t.Error("invalid next back off")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset makes it all work again
|
|
||||||
bo.Reset()
|
|
||||||
d := bo.NextBackOff()
|
|
||||||
if d == Stop {
|
|
||||||
t.Error("returned Stop after reset")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMaxTriesZero(t *testing.T) {
|
|
||||||
// It might not make sense, but its okay to send a zero
|
|
||||||
bo := WithMaxTries(&ZeroBackOff{}, uint64(0))
|
|
||||||
for ix := 0; ix < 11; ix++ {
|
|
||||||
d := bo.NextBackOff()
|
|
||||||
if d == Stop {
|
|
||||||
t.Errorf("returned Stop on try %d", ix)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
22
vendor/github.com/robfig/cron/.gitignore
generated
vendored
22
vendor/github.com/robfig/cron/.gitignore
generated
vendored
|
@ -1,22 +0,0 @@
|
||||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
|
||||||
*.o
|
|
||||||
*.a
|
|
||||||
*.so
|
|
||||||
|
|
||||||
# Folders
|
|
||||||
_obj
|
|
||||||
_test
|
|
||||||
|
|
||||||
# Architecture specific extensions/prefixes
|
|
||||||
*.[568vq]
|
|
||||||
[568vq].out
|
|
||||||
|
|
||||||
*.cgo1.go
|
|
||||||
*.cgo2.c
|
|
||||||
_cgo_defun.c
|
|
||||||
_cgo_gotypes.go
|
|
||||||
_cgo_export.*
|
|
||||||
|
|
||||||
_testmain.go
|
|
||||||
|
|
||||||
*.exe
|
|
21
vendor/github.com/robfig/cron/LICENSE
generated
vendored
21
vendor/github.com/robfig/cron/LICENSE
generated
vendored
|
@ -1,21 +0,0 @@
|
||||||
Copyright (C) 2012 Rob Figueiredo
|
|
||||||
All Rights Reserved.
|
|
||||||
|
|
||||||
MIT LICENSE
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
this software and associated documentation files (the "Software"), to deal in
|
|
||||||
the Software without restriction, including without limitation the rights to
|
|
||||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
||||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
||||||
subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
||||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
||||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
||||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
||||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
1
vendor/github.com/robfig/cron/README.md
generated
vendored
1
vendor/github.com/robfig/cron/README.md
generated
vendored
|
@ -1 +0,0 @@
|
||||||
[![GoDoc](http://godoc.org/github.com/robfig/cron?status.png)](http://godoc.org/github.com/robfig/cron)
|
|
27
vendor/github.com/robfig/cron/constantdelay.go
generated
vendored
27
vendor/github.com/robfig/cron/constantdelay.go
generated
vendored
|
@ -1,27 +0,0 @@
|
||||||
package cron
|
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
// ConstantDelaySchedule represents a simple recurring duty cycle, e.g. "Every 5 minutes".
|
|
||||||
// It does not support jobs more frequent than once a second.
|
|
||||||
type ConstantDelaySchedule struct {
|
|
||||||
Delay time.Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
// Every returns a crontab Schedule that activates once every duration.
|
|
||||||
// Delays of less than a second are not supported (will round up to 1 second).
|
|
||||||
// Any fields less than a Second are truncated.
|
|
||||||
func Every(duration time.Duration) ConstantDelaySchedule {
|
|
||||||
if duration < time.Second {
|
|
||||||
duration = time.Second
|
|
||||||
}
|
|
||||||
return ConstantDelaySchedule{
|
|
||||||
Delay: duration - time.Duration(duration.Nanoseconds())%time.Second,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next returns the next time this should be run.
|
|
||||||
// This rounds so that the next activation time will be on the second.
|
|
||||||
func (schedule ConstantDelaySchedule) Next(t time.Time) time.Time {
|
|
||||||
return t.Add(schedule.Delay - time.Duration(t.Nanosecond())*time.Nanosecond)
|
|
||||||
}
|
|
54
vendor/github.com/robfig/cron/constantdelay_test.go
generated
vendored
54
vendor/github.com/robfig/cron/constantdelay_test.go
generated
vendored
|
@ -1,54 +0,0 @@
|
||||||
package cron
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestConstantDelayNext(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
time string
|
|
||||||
delay time.Duration
|
|
||||||
expected string
|
|
||||||
}{
|
|
||||||
// Simple cases
|
|
||||||
{"Mon Jul 9 14:45 2012", 15*time.Minute + 50*time.Nanosecond, "Mon Jul 9 15:00 2012"},
|
|
||||||
{"Mon Jul 9 14:59 2012", 15 * time.Minute, "Mon Jul 9 15:14 2012"},
|
|
||||||
{"Mon Jul 9 14:59:59 2012", 15 * time.Minute, "Mon Jul 9 15:14:59 2012"},
|
|
||||||
|
|
||||||
// Wrap around hours
|
|
||||||
{"Mon Jul 9 15:45 2012", 35 * time.Minute, "Mon Jul 9 16:20 2012"},
|
|
||||||
|
|
||||||
// Wrap around days
|
|
||||||
{"Mon Jul 9 23:46 2012", 14 * time.Minute, "Tue Jul 10 00:00 2012"},
|
|
||||||
{"Mon Jul 9 23:45 2012", 35 * time.Minute, "Tue Jul 10 00:20 2012"},
|
|
||||||
{"Mon Jul 9 23:35:51 2012", 44*time.Minute + 24*time.Second, "Tue Jul 10 00:20:15 2012"},
|
|
||||||
{"Mon Jul 9 23:35:51 2012", 25*time.Hour + 44*time.Minute + 24*time.Second, "Thu Jul 11 01:20:15 2012"},
|
|
||||||
|
|
||||||
// Wrap around months
|
|
||||||
{"Mon Jul 9 23:35 2012", 91*24*time.Hour + 25*time.Minute, "Thu Oct 9 00:00 2012"},
|
|
||||||
|
|
||||||
// Wrap around minute, hour, day, month, and year
|
|
||||||
{"Mon Dec 31 23:59:45 2012", 15 * time.Second, "Tue Jan 1 00:00:00 2013"},
|
|
||||||
|
|
||||||
// Round to nearest second on the delay
|
|
||||||
{"Mon Jul 9 14:45 2012", 15*time.Minute + 50*time.Nanosecond, "Mon Jul 9 15:00 2012"},
|
|
||||||
|
|
||||||
// Round up to 1 second if the duration is less.
|
|
||||||
{"Mon Jul 9 14:45:00 2012", 15 * time.Millisecond, "Mon Jul 9 14:45:01 2012"},
|
|
||||||
|
|
||||||
// Round to nearest second when calculating the next time.
|
|
||||||
{"Mon Jul 9 14:45:00.005 2012", 15 * time.Minute, "Mon Jul 9 15:00 2012"},
|
|
||||||
|
|
||||||
// Round to nearest second for both.
|
|
||||||
{"Mon Jul 9 14:45:00.005 2012", 15*time.Minute + 50*time.Nanosecond, "Mon Jul 9 15:00 2012"},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, c := range tests {
|
|
||||||
actual := Every(c.delay).Next(getTime(c.time))
|
|
||||||
expected := getTime(c.expected)
|
|
||||||
if actual != expected {
|
|
||||||
t.Errorf("%s, \"%s\": (expected) %v != %v (actual)", c.time, c.delay, expected, actual)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
199
vendor/github.com/robfig/cron/cron.go
generated
vendored
199
vendor/github.com/robfig/cron/cron.go
generated
vendored
|
@ -1,199 +0,0 @@
|
||||||
// This library implements a cron spec parser and runner. See the README for
|
|
||||||
// more details.
|
|
||||||
package cron
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sort"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Cron keeps track of any number of entries, invoking the associated func as
|
|
||||||
// specified by the schedule. It may be started, stopped, and the entries may
|
|
||||||
// be inspected while running.
|
|
||||||
type Cron struct {
|
|
||||||
entries []*Entry
|
|
||||||
stop chan struct{}
|
|
||||||
add chan *Entry
|
|
||||||
snapshot chan []*Entry
|
|
||||||
running bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Job is an interface for submitted cron jobs.
|
|
||||||
type Job interface {
|
|
||||||
Run()
|
|
||||||
}
|
|
||||||
|
|
||||||
// The Schedule describes a job's duty cycle.
|
|
||||||
type Schedule interface {
|
|
||||||
// Return the next activation time, later than the given time.
|
|
||||||
// Next is invoked initially, and then each time the job is run.
|
|
||||||
Next(time.Time) time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
// Entry consists of a schedule and the func to execute on that schedule.
|
|
||||||
type Entry struct {
|
|
||||||
// The schedule on which this job should be run.
|
|
||||||
Schedule Schedule
|
|
||||||
|
|
||||||
// The next time the job will run. This is the zero time if Cron has not been
|
|
||||||
// started or this entry's schedule is unsatisfiable
|
|
||||||
Next time.Time
|
|
||||||
|
|
||||||
// The last time this job was run. This is the zero time if the job has never
|
|
||||||
// been run.
|
|
||||||
Prev time.Time
|
|
||||||
|
|
||||||
// The Job to run.
|
|
||||||
Job Job
|
|
||||||
}
|
|
||||||
|
|
||||||
// byTime is a wrapper for sorting the entry array by time
|
|
||||||
// (with zero time at the end).
|
|
||||||
type byTime []*Entry
|
|
||||||
|
|
||||||
func (s byTime) Len() int { return len(s) }
|
|
||||||
func (s byTime) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
|
||||||
func (s byTime) Less(i, j int) bool {
|
|
||||||
// Two zero times should return false.
|
|
||||||
// Otherwise, zero is "greater" than any other time.
|
|
||||||
// (To sort it at the end of the list.)
|
|
||||||
if s[i].Next.IsZero() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if s[j].Next.IsZero() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return s[i].Next.Before(s[j].Next)
|
|
||||||
}
|
|
||||||
|
|
||||||
// New returns a new Cron job runner.
|
|
||||||
func New() *Cron {
|
|
||||||
return &Cron{
|
|
||||||
entries: nil,
|
|
||||||
add: make(chan *Entry),
|
|
||||||
stop: make(chan struct{}),
|
|
||||||
snapshot: make(chan []*Entry),
|
|
||||||
running: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A wrapper that turns a func() into a cron.Job
|
|
||||||
type FuncJob func()
|
|
||||||
|
|
||||||
func (f FuncJob) Run() { f() }
|
|
||||||
|
|
||||||
// AddFunc adds a func to the Cron to be run on the given schedule.
|
|
||||||
func (c *Cron) AddFunc(spec string, cmd func()) error {
|
|
||||||
return c.AddJob(spec, FuncJob(cmd))
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddFunc adds a Job to the Cron to be run on the given schedule.
|
|
||||||
func (c *Cron) AddJob(spec string, cmd Job) error {
|
|
||||||
schedule, err := Parse(spec)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
c.Schedule(schedule, cmd)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Schedule adds a Job to the Cron to be run on the given schedule.
|
|
||||||
func (c *Cron) Schedule(schedule Schedule, cmd Job) {
|
|
||||||
entry := &Entry{
|
|
||||||
Schedule: schedule,
|
|
||||||
Job: cmd,
|
|
||||||
}
|
|
||||||
if !c.running {
|
|
||||||
c.entries = append(c.entries, entry)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.add <- entry
|
|
||||||
}
|
|
||||||
|
|
||||||
// Entries returns a snapshot of the cron entries.
|
|
||||||
func (c *Cron) Entries() []*Entry {
|
|
||||||
if c.running {
|
|
||||||
c.snapshot <- nil
|
|
||||||
x := <-c.snapshot
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
return c.entrySnapshot()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start the cron scheduler in its own go-routine.
|
|
||||||
func (c *Cron) Start() {
|
|
||||||
c.running = true
|
|
||||||
go c.run()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run the scheduler.. this is private just due to the need to synchronize
|
|
||||||
// access to the 'running' state variable.
|
|
||||||
func (c *Cron) run() {
|
|
||||||
// Figure out the next activation times for each entry.
|
|
||||||
now := time.Now().Local()
|
|
||||||
for _, entry := range c.entries {
|
|
||||||
entry.Next = entry.Schedule.Next(now)
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
|
||||||
// Determine the next entry to run.
|
|
||||||
sort.Sort(byTime(c.entries))
|
|
||||||
|
|
||||||
var effective time.Time
|
|
||||||
if len(c.entries) == 0 || c.entries[0].Next.IsZero() {
|
|
||||||
// If there are no entries yet, just sleep - it still handles new entries
|
|
||||||
// and stop requests.
|
|
||||||
effective = now.AddDate(10, 0, 0)
|
|
||||||
} else {
|
|
||||||
effective = c.entries[0].Next
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
case now = <-time.After(effective.Sub(now)):
|
|
||||||
// Run every entry whose next time was this effective time.
|
|
||||||
for _, e := range c.entries {
|
|
||||||
if e.Next != effective {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
go e.Job.Run()
|
|
||||||
e.Prev = e.Next
|
|
||||||
e.Next = e.Schedule.Next(effective)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
|
|
||||||
case newEntry := <-c.add:
|
|
||||||
c.entries = append(c.entries, newEntry)
|
|
||||||
newEntry.Next = newEntry.Schedule.Next(now)
|
|
||||||
|
|
||||||
case <-c.snapshot:
|
|
||||||
c.snapshot <- c.entrySnapshot()
|
|
||||||
|
|
||||||
case <-c.stop:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 'now' should be updated after newEntry and snapshot cases.
|
|
||||||
now = time.Now().Local()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop the cron scheduler.
|
|
||||||
func (c *Cron) Stop() {
|
|
||||||
c.stop <- struct{}{}
|
|
||||||
c.running = false
|
|
||||||
}
|
|
||||||
|
|
||||||
// entrySnapshot returns a copy of the current cron entry list.
|
|
||||||
func (c *Cron) entrySnapshot() []*Entry {
|
|
||||||
entries := []*Entry{}
|
|
||||||
for _, e := range c.entries {
|
|
||||||
entries = append(entries, &Entry{
|
|
||||||
Schedule: e.Schedule,
|
|
||||||
Next: e.Next,
|
|
||||||
Prev: e.Prev,
|
|
||||||
Job: e.Job,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return entries
|
|
||||||
}
|
|
255
vendor/github.com/robfig/cron/cron_test.go
generated
vendored
255
vendor/github.com/robfig/cron/cron_test.go
generated
vendored
|
@ -1,255 +0,0 @@
|
||||||
package cron
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"sync"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Many tests schedule a job for every second, and then wait at most a second
|
|
||||||
// for it to run. This amount is just slightly larger than 1 second to
|
|
||||||
// compensate for a few milliseconds of runtime.
|
|
||||||
const ONE_SECOND = 1*time.Second + 10*time.Millisecond
|
|
||||||
|
|
||||||
// Start and stop cron with no entries.
|
|
||||||
func TestNoEntries(t *testing.T) {
|
|
||||||
cron := New()
|
|
||||||
cron.Start()
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-time.After(ONE_SECOND):
|
|
||||||
t.FailNow()
|
|
||||||
case <-stop(cron):
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start, stop, then add an entry. Verify entry doesn't run.
|
|
||||||
func TestStopCausesJobsToNotRun(t *testing.T) {
|
|
||||||
wg := &sync.WaitGroup{}
|
|
||||||
wg.Add(1)
|
|
||||||
|
|
||||||
cron := New()
|
|
||||||
cron.Start()
|
|
||||||
cron.Stop()
|
|
||||||
cron.AddFunc("* * * * * ?", func() { wg.Done() })
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-time.After(ONE_SECOND):
|
|
||||||
// No job ran!
|
|
||||||
case <-wait(wg):
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a job, start cron, expect it runs.
|
|
||||||
func TestAddBeforeRunning(t *testing.T) {
|
|
||||||
wg := &sync.WaitGroup{}
|
|
||||||
wg.Add(1)
|
|
||||||
|
|
||||||
cron := New()
|
|
||||||
cron.AddFunc("* * * * * ?", func() { wg.Done() })
|
|
||||||
cron.Start()
|
|
||||||
defer cron.Stop()
|
|
||||||
|
|
||||||
// Give cron 2 seconds to run our job (which is always activated).
|
|
||||||
select {
|
|
||||||
case <-time.After(ONE_SECOND):
|
|
||||||
t.FailNow()
|
|
||||||
case <-wait(wg):
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start cron, add a job, expect it runs.
|
|
||||||
func TestAddWhileRunning(t *testing.T) {
|
|
||||||
wg := &sync.WaitGroup{}
|
|
||||||
wg.Add(1)
|
|
||||||
|
|
||||||
cron := New()
|
|
||||||
cron.Start()
|
|
||||||
defer cron.Stop()
|
|
||||||
cron.AddFunc("* * * * * ?", func() { wg.Done() })
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-time.After(ONE_SECOND):
|
|
||||||
t.FailNow()
|
|
||||||
case <-wait(wg):
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test timing with Entries.
|
|
||||||
func TestSnapshotEntries(t *testing.T) {
|
|
||||||
wg := &sync.WaitGroup{}
|
|
||||||
wg.Add(1)
|
|
||||||
|
|
||||||
cron := New()
|
|
||||||
cron.AddFunc("@every 2s", func() { wg.Done() })
|
|
||||||
cron.Start()
|
|
||||||
defer cron.Stop()
|
|
||||||
|
|
||||||
// Cron should fire in 2 seconds. After 1 second, call Entries.
|
|
||||||
select {
|
|
||||||
case <-time.After(ONE_SECOND):
|
|
||||||
cron.Entries()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Even though Entries was called, the cron should fire at the 2 second mark.
|
|
||||||
select {
|
|
||||||
case <-time.After(ONE_SECOND):
|
|
||||||
t.FailNow()
|
|
||||||
case <-wait(wg):
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test that the entries are correctly sorted.
|
|
||||||
// Add a bunch of long-in-the-future entries, and an immediate entry, and ensure
|
|
||||||
// that the immediate entry runs immediately.
|
|
||||||
// Also: Test that multiple jobs run in the same instant.
|
|
||||||
func TestMultipleEntries(t *testing.T) {
|
|
||||||
wg := &sync.WaitGroup{}
|
|
||||||
wg.Add(2)
|
|
||||||
|
|
||||||
cron := New()
|
|
||||||
cron.AddFunc("0 0 0 1 1 ?", func() {})
|
|
||||||
cron.AddFunc("* * * * * ?", func() { wg.Done() })
|
|
||||||
cron.AddFunc("0 0 0 31 12 ?", func() {})
|
|
||||||
cron.AddFunc("* * * * * ?", func() { wg.Done() })
|
|
||||||
|
|
||||||
cron.Start()
|
|
||||||
defer cron.Stop()
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-time.After(ONE_SECOND):
|
|
||||||
t.FailNow()
|
|
||||||
case <-wait(wg):
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test running the same job twice.
|
|
||||||
func TestRunningJobTwice(t *testing.T) {
|
|
||||||
wg := &sync.WaitGroup{}
|
|
||||||
wg.Add(2)
|
|
||||||
|
|
||||||
cron := New()
|
|
||||||
cron.AddFunc("0 0 0 1 1 ?", func() {})
|
|
||||||
cron.AddFunc("0 0 0 31 12 ?", func() {})
|
|
||||||
cron.AddFunc("* * * * * ?", func() { wg.Done() })
|
|
||||||
|
|
||||||
cron.Start()
|
|
||||||
defer cron.Stop()
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-time.After(2 * ONE_SECOND):
|
|
||||||
t.FailNow()
|
|
||||||
case <-wait(wg):
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRunningMultipleSchedules(t *testing.T) {
|
|
||||||
wg := &sync.WaitGroup{}
|
|
||||||
wg.Add(2)
|
|
||||||
|
|
||||||
cron := New()
|
|
||||||
cron.AddFunc("0 0 0 1 1 ?", func() {})
|
|
||||||
cron.AddFunc("0 0 0 31 12 ?", func() {})
|
|
||||||
cron.AddFunc("* * * * * ?", func() { wg.Done() })
|
|
||||||
cron.Schedule(Every(time.Minute), FuncJob(func() {}))
|
|
||||||
cron.Schedule(Every(time.Second), FuncJob(func() { wg.Done() }))
|
|
||||||
cron.Schedule(Every(time.Hour), FuncJob(func() {}))
|
|
||||||
|
|
||||||
cron.Start()
|
|
||||||
defer cron.Stop()
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-time.After(2 * ONE_SECOND):
|
|
||||||
t.FailNow()
|
|
||||||
case <-wait(wg):
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test that the cron is run in the local time zone (as opposed to UTC).
|
|
||||||
func TestLocalTimezone(t *testing.T) {
|
|
||||||
wg := &sync.WaitGroup{}
|
|
||||||
wg.Add(1)
|
|
||||||
|
|
||||||
now := time.Now().Local()
|
|
||||||
spec := fmt.Sprintf("%d %d %d %d %d ?",
|
|
||||||
now.Second()+1, now.Minute(), now.Hour(), now.Day(), now.Month())
|
|
||||||
|
|
||||||
cron := New()
|
|
||||||
cron.AddFunc(spec, func() { wg.Done() })
|
|
||||||
cron.Start()
|
|
||||||
defer cron.Stop()
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-time.After(ONE_SECOND):
|
|
||||||
t.FailNow()
|
|
||||||
case <-wait(wg):
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type testJob struct {
|
|
||||||
wg *sync.WaitGroup
|
|
||||||
name string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t testJob) Run() {
|
|
||||||
t.wg.Done()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Simple test using Runnables.
|
|
||||||
func TestJob(t *testing.T) {
|
|
||||||
wg := &sync.WaitGroup{}
|
|
||||||
wg.Add(1)
|
|
||||||
|
|
||||||
cron := New()
|
|
||||||
cron.AddJob("0 0 0 30 Feb ?", testJob{wg, "job0"})
|
|
||||||
cron.AddJob("0 0 0 1 1 ?", testJob{wg, "job1"})
|
|
||||||
cron.AddJob("* * * * * ?", testJob{wg, "job2"})
|
|
||||||
cron.AddJob("1 0 0 1 1 ?", testJob{wg, "job3"})
|
|
||||||
cron.Schedule(Every(5*time.Second+5*time.Nanosecond), testJob{wg, "job4"})
|
|
||||||
cron.Schedule(Every(5*time.Minute), testJob{wg, "job5"})
|
|
||||||
|
|
||||||
cron.Start()
|
|
||||||
defer cron.Stop()
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-time.After(ONE_SECOND):
|
|
||||||
t.FailNow()
|
|
||||||
case <-wait(wg):
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure the entries are in the right order.
|
|
||||||
expecteds := []string{"job2", "job4", "job5", "job1", "job3", "job0"}
|
|
||||||
|
|
||||||
var actuals []string
|
|
||||||
for _, entry := range cron.Entries() {
|
|
||||||
actuals = append(actuals, entry.Job.(testJob).name)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, expected := range expecteds {
|
|
||||||
if actuals[i] != expected {
|
|
||||||
t.Errorf("Jobs not in the right order. (expected) %s != %s (actual)", expecteds, actuals)
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func wait(wg *sync.WaitGroup) chan bool {
|
|
||||||
ch := make(chan bool)
|
|
||||||
go func() {
|
|
||||||
wg.Wait()
|
|
||||||
ch <- true
|
|
||||||
}()
|
|
||||||
return ch
|
|
||||||
}
|
|
||||||
|
|
||||||
func stop(cron *Cron) chan bool {
|
|
||||||
ch := make(chan bool)
|
|
||||||
go func() {
|
|
||||||
cron.Stop()
|
|
||||||
ch <- true
|
|
||||||
}()
|
|
||||||
return ch
|
|
||||||
}
|
|
129
vendor/github.com/robfig/cron/doc.go
generated
vendored
129
vendor/github.com/robfig/cron/doc.go
generated
vendored
|
@ -1,129 +0,0 @@
|
||||||
/*
|
|
||||||
Package cron implements a cron spec parser and job runner.
|
|
||||||
|
|
||||||
Usage
|
|
||||||
|
|
||||||
Callers may register Funcs to be invoked on a given schedule. Cron will run
|
|
||||||
them in their own goroutines.
|
|
||||||
|
|
||||||
c := cron.New()
|
|
||||||
c.AddFunc("0 30 * * * *", func() { fmt.Println("Every hour on the half hour") })
|
|
||||||
c.AddFunc("@hourly", func() { fmt.Println("Every hour") })
|
|
||||||
c.AddFunc("@every 1h30m", func() { fmt.Println("Every hour thirty") })
|
|
||||||
c.Start()
|
|
||||||
..
|
|
||||||
// Funcs are invoked in their own goroutine, asynchronously.
|
|
||||||
...
|
|
||||||
// Funcs may also be added to a running Cron
|
|
||||||
c.AddFunc("@daily", func() { fmt.Println("Every day") })
|
|
||||||
..
|
|
||||||
// Inspect the cron job entries' next and previous run times.
|
|
||||||
inspect(c.Entries())
|
|
||||||
..
|
|
||||||
c.Stop() // Stop the scheduler (does not stop any jobs already running).
|
|
||||||
|
|
||||||
CRON Expression Format
|
|
||||||
|
|
||||||
A cron expression represents a set of times, using 6 space-separated fields.
|
|
||||||
|
|
||||||
Field name | Mandatory? | Allowed values | Allowed special characters
|
|
||||||
---------- | ---------- | -------------- | --------------------------
|
|
||||||
Seconds | Yes | 0-59 | * / , -
|
|
||||||
Minutes | Yes | 0-59 | * / , -
|
|
||||||
Hours | Yes | 0-23 | * / , -
|
|
||||||
Day of month | Yes | 1-31 | * / , - ?
|
|
||||||
Month | Yes | 1-12 or JAN-DEC | * / , -
|
|
||||||
Day of week | Yes | 0-6 or SUN-SAT | * / , - ?
|
|
||||||
|
|
||||||
Note: Month and Day-of-week field values are case insensitive. "SUN", "Sun",
|
|
||||||
and "sun" are equally accepted.
|
|
||||||
|
|
||||||
Special Characters
|
|
||||||
|
|
||||||
Asterisk ( * )
|
|
||||||
|
|
||||||
The asterisk indicates that the cron expression will match for all values of the
|
|
||||||
field; e.g., using an asterisk in the 5th field (month) would indicate every
|
|
||||||
month.
|
|
||||||
|
|
||||||
Slash ( / )
|
|
||||||
|
|
||||||
Slashes are used to describe increments of ranges. For example 3-59/15 in the
|
|
||||||
1st field (minutes) would indicate the 3rd minute of the hour and every 15
|
|
||||||
minutes thereafter. The form "*\/..." is equivalent to the form "first-last/...",
|
|
||||||
that is, an increment over the largest possible range of the field. The form
|
|
||||||
"N/..." is accepted as meaning "N-MAX/...", that is, starting at N, use the
|
|
||||||
increment until the end of that specific range. It does not wrap around.
|
|
||||||
|
|
||||||
Comma ( , )
|
|
||||||
|
|
||||||
Commas are used to separate items of a list. For example, using "MON,WED,FRI" in
|
|
||||||
the 5th field (day of week) would mean Mondays, Wednesdays and Fridays.
|
|
||||||
|
|
||||||
Hyphen ( - )
|
|
||||||
|
|
||||||
Hyphens are used to define ranges. For example, 9-17 would indicate every
|
|
||||||
hour between 9am and 5pm inclusive.
|
|
||||||
|
|
||||||
Question mark ( ? )
|
|
||||||
|
|
||||||
Question mark may be used instead of '*' for leaving either day-of-month or
|
|
||||||
day-of-week blank.
|
|
||||||
|
|
||||||
Predefined schedules
|
|
||||||
|
|
||||||
You may use one of several pre-defined schedules in place of a cron expression.
|
|
||||||
|
|
||||||
Entry | Description | Equivalent To
|
|
||||||
----- | ----------- | -------------
|
|
||||||
@yearly (or @annually) | Run once a year, midnight, Jan. 1st | 0 0 0 1 1 *
|
|
||||||
@monthly | Run once a month, midnight, first of month | 0 0 0 1 * *
|
|
||||||
@weekly | Run once a week, midnight on Sunday | 0 0 0 * * 0
|
|
||||||
@daily (or @midnight) | Run once a day, midnight | 0 0 0 * * *
|
|
||||||
@hourly | Run once an hour, beginning of hour | 0 0 * * * *
|
|
||||||
|
|
||||||
Intervals
|
|
||||||
|
|
||||||
You may also schedule a job to execute at fixed intervals. This is supported by
|
|
||||||
formatting the cron spec like this:
|
|
||||||
|
|
||||||
@every <duration>
|
|
||||||
|
|
||||||
where "duration" is a string accepted by time.ParseDuration
|
|
||||||
(http://golang.org/pkg/time/#ParseDuration).
|
|
||||||
|
|
||||||
For example, "@every 1h30m10s" would indicate a schedule that activates every
|
|
||||||
1 hour, 30 minutes, 10 seconds.
|
|
||||||
|
|
||||||
Note: The interval does not take the job runtime into account. For example,
|
|
||||||
if a job takes 3 minutes to run, and it is scheduled to run every 5 minutes,
|
|
||||||
it will have only 2 minutes of idle time between each run.
|
|
||||||
|
|
||||||
Time zones
|
|
||||||
|
|
||||||
All interpretation and scheduling is done in the machine's local time zone (as
|
|
||||||
provided by the Go time package (http://www.golang.org/pkg/time).
|
|
||||||
|
|
||||||
Be aware that jobs scheduled during daylight-savings leap-ahead transitions will
|
|
||||||
not be run!
|
|
||||||
|
|
||||||
Thread safety
|
|
||||||
|
|
||||||
Since the Cron service runs concurrently with the calling code, some amount of
|
|
||||||
care must be taken to ensure proper synchronization.
|
|
||||||
|
|
||||||
All cron methods are designed to be correctly synchronized as long as the caller
|
|
||||||
ensures that invocations have a clear happens-before ordering between them.
|
|
||||||
|
|
||||||
Implementation
|
|
||||||
|
|
||||||
Cron entries are stored in an array, sorted by their next activation time. Cron
|
|
||||||
sleeps until the next job is due to be run.
|
|
||||||
|
|
||||||
Upon waking:
|
|
||||||
- it runs each entry that is active on that second
|
|
||||||
- it calculates the next run times for the jobs that were run
|
|
||||||
- it re-sorts the array of entries by next activation time.
|
|
||||||
- it goes to sleep until the soonest job.
|
|
||||||
*/
|
|
||||||
package cron
|
|
231
vendor/github.com/robfig/cron/parser.go
generated
vendored
231
vendor/github.com/robfig/cron/parser.go
generated
vendored
|
@ -1,231 +0,0 @@
|
||||||
package cron
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"math"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Parse returns a new crontab schedule representing the given spec.
|
|
||||||
// It returns a descriptive error if the spec is not valid.
|
|
||||||
//
|
|
||||||
// It accepts
|
|
||||||
// - Full crontab specs, e.g. "* * * * * ?"
|
|
||||||
// - Descriptors, e.g. "@midnight", "@every 1h30m"
|
|
||||||
func Parse(spec string) (_ Schedule, err error) {
|
|
||||||
// Convert panics into errors
|
|
||||||
defer func() {
|
|
||||||
if recovered := recover(); recovered != nil {
|
|
||||||
err = fmt.Errorf("%v", recovered)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
if spec[0] == '@' {
|
|
||||||
return parseDescriptor(spec), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Split on whitespace. We require 5 or 6 fields.
|
|
||||||
// (second) (minute) (hour) (day of month) (month) (day of week, optional)
|
|
||||||
fields := strings.Fields(spec)
|
|
||||||
if len(fields) != 5 && len(fields) != 6 {
|
|
||||||
log.Panicf("Expected 5 or 6 fields, found %d: %s", len(fields), spec)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If a sixth field is not provided (DayOfWeek), then it is equivalent to star.
|
|
||||||
if len(fields) == 5 {
|
|
||||||
fields = append(fields, "*")
|
|
||||||
}
|
|
||||||
|
|
||||||
schedule := &SpecSchedule{
|
|
||||||
Second: getField(fields[0], seconds),
|
|
||||||
Minute: getField(fields[1], minutes),
|
|
||||||
Hour: getField(fields[2], hours),
|
|
||||||
Dom: getField(fields[3], dom),
|
|
||||||
Month: getField(fields[4], months),
|
|
||||||
Dow: getField(fields[5], dow),
|
|
||||||
}
|
|
||||||
|
|
||||||
return schedule, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// getField returns an Int with the bits set representing all of the times that
|
|
||||||
// the field represents. A "field" is a comma-separated list of "ranges".
|
|
||||||
func getField(field string, r bounds) uint64 {
|
|
||||||
// list = range {"," range}
|
|
||||||
var bits uint64
|
|
||||||
ranges := strings.FieldsFunc(field, func(r rune) bool { return r == ',' })
|
|
||||||
for _, expr := range ranges {
|
|
||||||
bits |= getRange(expr, r)
|
|
||||||
}
|
|
||||||
return bits
|
|
||||||
}
|
|
||||||
|
|
||||||
// getRange returns the bits indicated by the given expression:
|
|
||||||
// number | number "-" number [ "/" number ]
|
|
||||||
func getRange(expr string, r bounds) uint64 {
|
|
||||||
|
|
||||||
var (
|
|
||||||
start, end, step uint
|
|
||||||
rangeAndStep = strings.Split(expr, "/")
|
|
||||||
lowAndHigh = strings.Split(rangeAndStep[0], "-")
|
|
||||||
singleDigit = len(lowAndHigh) == 1
|
|
||||||
)
|
|
||||||
|
|
||||||
var extra_star uint64
|
|
||||||
if lowAndHigh[0] == "*" || lowAndHigh[0] == "?" {
|
|
||||||
start = r.min
|
|
||||||
end = r.max
|
|
||||||
extra_star = starBit
|
|
||||||
} else {
|
|
||||||
start = parseIntOrName(lowAndHigh[0], r.names)
|
|
||||||
switch len(lowAndHigh) {
|
|
||||||
case 1:
|
|
||||||
end = start
|
|
||||||
case 2:
|
|
||||||
end = parseIntOrName(lowAndHigh[1], r.names)
|
|
||||||
default:
|
|
||||||
log.Panicf("Too many hyphens: %s", expr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch len(rangeAndStep) {
|
|
||||||
case 1:
|
|
||||||
step = 1
|
|
||||||
case 2:
|
|
||||||
step = mustParseInt(rangeAndStep[1])
|
|
||||||
|
|
||||||
// Special handling: "N/step" means "N-max/step".
|
|
||||||
if singleDigit {
|
|
||||||
end = r.max
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
log.Panicf("Too many slashes: %s", expr)
|
|
||||||
}
|
|
||||||
|
|
||||||
if start < r.min {
|
|
||||||
log.Panicf("Beginning of range (%d) below minimum (%d): %s", start, r.min, expr)
|
|
||||||
}
|
|
||||||
if end > r.max {
|
|
||||||
log.Panicf("End of range (%d) above maximum (%d): %s", end, r.max, expr)
|
|
||||||
}
|
|
||||||
if start > end {
|
|
||||||
log.Panicf("Beginning of range (%d) beyond end of range (%d): %s", start, end, expr)
|
|
||||||
}
|
|
||||||
|
|
||||||
return getBits(start, end, step) | extra_star
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseIntOrName returns the (possibly-named) integer contained in expr.
|
|
||||||
func parseIntOrName(expr string, names map[string]uint) uint {
|
|
||||||
if names != nil {
|
|
||||||
if namedInt, ok := names[strings.ToLower(expr)]; ok {
|
|
||||||
return namedInt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mustParseInt(expr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// mustParseInt parses the given expression as an int or panics.
|
|
||||||
func mustParseInt(expr string) uint {
|
|
||||||
num, err := strconv.Atoi(expr)
|
|
||||||
if err != nil {
|
|
||||||
log.Panicf("Failed to parse int from %s: %s", expr, err)
|
|
||||||
}
|
|
||||||
if num < 0 {
|
|
||||||
log.Panicf("Negative number (%d) not allowed: %s", num, expr)
|
|
||||||
}
|
|
||||||
|
|
||||||
return uint(num)
|
|
||||||
}
|
|
||||||
|
|
||||||
// getBits sets all bits in the range [min, max], modulo the given step size.
|
|
||||||
func getBits(min, max, step uint) uint64 {
|
|
||||||
var bits uint64
|
|
||||||
|
|
||||||
// If step is 1, use shifts.
|
|
||||||
if step == 1 {
|
|
||||||
return ^(math.MaxUint64 << (max + 1)) & (math.MaxUint64 << min)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Else, use a simple loop.
|
|
||||||
for i := min; i <= max; i += step {
|
|
||||||
bits |= 1 << i
|
|
||||||
}
|
|
||||||
return bits
|
|
||||||
}
|
|
||||||
|
|
||||||
// all returns all bits within the given bounds. (plus the star bit)
|
|
||||||
func all(r bounds) uint64 {
|
|
||||||
return getBits(r.min, r.max, 1) | starBit
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseDescriptor returns a pre-defined schedule for the expression, or panics
|
|
||||||
// if none matches.
|
|
||||||
func parseDescriptor(spec string) Schedule {
|
|
||||||
switch spec {
|
|
||||||
case "@yearly", "@annually":
|
|
||||||
return &SpecSchedule{
|
|
||||||
Second: 1 << seconds.min,
|
|
||||||
Minute: 1 << minutes.min,
|
|
||||||
Hour: 1 << hours.min,
|
|
||||||
Dom: 1 << dom.min,
|
|
||||||
Month: 1 << months.min,
|
|
||||||
Dow: all(dow),
|
|
||||||
}
|
|
||||||
|
|
||||||
case "@monthly":
|
|
||||||
return &SpecSchedule{
|
|
||||||
Second: 1 << seconds.min,
|
|
||||||
Minute: 1 << minutes.min,
|
|
||||||
Hour: 1 << hours.min,
|
|
||||||
Dom: 1 << dom.min,
|
|
||||||
Month: all(months),
|
|
||||||
Dow: all(dow),
|
|
||||||
}
|
|
||||||
|
|
||||||
case "@weekly":
|
|
||||||
return &SpecSchedule{
|
|
||||||
Second: 1 << seconds.min,
|
|
||||||
Minute: 1 << minutes.min,
|
|
||||||
Hour: 1 << hours.min,
|
|
||||||
Dom: all(dom),
|
|
||||||
Month: all(months),
|
|
||||||
Dow: 1 << dow.min,
|
|
||||||
}
|
|
||||||
|
|
||||||
case "@daily", "@midnight":
|
|
||||||
return &SpecSchedule{
|
|
||||||
Second: 1 << seconds.min,
|
|
||||||
Minute: 1 << minutes.min,
|
|
||||||
Hour: 1 << hours.min,
|
|
||||||
Dom: all(dom),
|
|
||||||
Month: all(months),
|
|
||||||
Dow: all(dow),
|
|
||||||
}
|
|
||||||
|
|
||||||
case "@hourly":
|
|
||||||
return &SpecSchedule{
|
|
||||||
Second: 1 << seconds.min,
|
|
||||||
Minute: 1 << minutes.min,
|
|
||||||
Hour: all(hours),
|
|
||||||
Dom: all(dom),
|
|
||||||
Month: all(months),
|
|
||||||
Dow: all(dow),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const every = "@every "
|
|
||||||
if strings.HasPrefix(spec, every) {
|
|
||||||
duration, err := time.ParseDuration(spec[len(every):])
|
|
||||||
if err != nil {
|
|
||||||
log.Panicf("Failed to parse duration %s: %s", spec, err)
|
|
||||||
}
|
|
||||||
return Every(duration)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Panicf("Unrecognized descriptor: %s", spec)
|
|
||||||
return nil
|
|
||||||
}
|
|
117
vendor/github.com/robfig/cron/parser_test.go
generated
vendored
117
vendor/github.com/robfig/cron/parser_test.go
generated
vendored
|
@ -1,117 +0,0 @@
|
||||||
package cron
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestRange(t *testing.T) {
|
|
||||||
ranges := []struct {
|
|
||||||
expr string
|
|
||||||
min, max uint
|
|
||||||
expected uint64
|
|
||||||
}{
|
|
||||||
{"5", 0, 7, 1 << 5},
|
|
||||||
{"0", 0, 7, 1 << 0},
|
|
||||||
{"7", 0, 7, 1 << 7},
|
|
||||||
|
|
||||||
{"5-5", 0, 7, 1 << 5},
|
|
||||||
{"5-6", 0, 7, 1<<5 | 1<<6},
|
|
||||||
{"5-7", 0, 7, 1<<5 | 1<<6 | 1<<7},
|
|
||||||
|
|
||||||
{"5-6/2", 0, 7, 1 << 5},
|
|
||||||
{"5-7/2", 0, 7, 1<<5 | 1<<7},
|
|
||||||
{"5-7/1", 0, 7, 1<<5 | 1<<6 | 1<<7},
|
|
||||||
|
|
||||||
{"*", 1, 3, 1<<1 | 1<<2 | 1<<3 | starBit},
|
|
||||||
{"*/2", 1, 3, 1<<1 | 1<<3 | starBit},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, c := range ranges {
|
|
||||||
actual := getRange(c.expr, bounds{c.min, c.max, nil})
|
|
||||||
if actual != c.expected {
|
|
||||||
t.Errorf("%s => (expected) %d != %d (actual)", c.expr, c.expected, actual)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestField(t *testing.T) {
|
|
||||||
fields := []struct {
|
|
||||||
expr string
|
|
||||||
min, max uint
|
|
||||||
expected uint64
|
|
||||||
}{
|
|
||||||
{"5", 1, 7, 1 << 5},
|
|
||||||
{"5,6", 1, 7, 1<<5 | 1<<6},
|
|
||||||
{"5,6,7", 1, 7, 1<<5 | 1<<6 | 1<<7},
|
|
||||||
{"1,5-7/2,3", 1, 7, 1<<1 | 1<<5 | 1<<7 | 1<<3},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, c := range fields {
|
|
||||||
actual := getField(c.expr, bounds{c.min, c.max, nil})
|
|
||||||
if actual != c.expected {
|
|
||||||
t.Errorf("%s => (expected) %d != %d (actual)", c.expr, c.expected, actual)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBits(t *testing.T) {
|
|
||||||
allBits := []struct {
|
|
||||||
r bounds
|
|
||||||
expected uint64
|
|
||||||
}{
|
|
||||||
{minutes, 0xfffffffffffffff}, // 0-59: 60 ones
|
|
||||||
{hours, 0xffffff}, // 0-23: 24 ones
|
|
||||||
{dom, 0xfffffffe}, // 1-31: 31 ones, 1 zero
|
|
||||||
{months, 0x1ffe}, // 1-12: 12 ones, 1 zero
|
|
||||||
{dow, 0x7f}, // 0-6: 7 ones
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, c := range allBits {
|
|
||||||
actual := all(c.r) // all() adds the starBit, so compensate for that..
|
|
||||||
if c.expected|starBit != actual {
|
|
||||||
t.Errorf("%d-%d/%d => (expected) %b != %b (actual)",
|
|
||||||
c.r.min, c.r.max, 1, c.expected|starBit, actual)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bits := []struct {
|
|
||||||
min, max, step uint
|
|
||||||
expected uint64
|
|
||||||
}{
|
|
||||||
|
|
||||||
{0, 0, 1, 0x1},
|
|
||||||
{1, 1, 1, 0x2},
|
|
||||||
{1, 5, 2, 0x2a}, // 101010
|
|
||||||
{1, 4, 2, 0xa}, // 1010
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, c := range bits {
|
|
||||||
actual := getBits(c.min, c.max, c.step)
|
|
||||||
if c.expected != actual {
|
|
||||||
t.Errorf("%d-%d/%d => (expected) %b != %b (actual)",
|
|
||||||
c.min, c.max, c.step, c.expected, actual)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSpecSchedule(t *testing.T) {
|
|
||||||
entries := []struct {
|
|
||||||
expr string
|
|
||||||
expected Schedule
|
|
||||||
}{
|
|
||||||
{"* 5 * * * *", &SpecSchedule{all(seconds), 1 << 5, all(hours), all(dom), all(months), all(dow)}},
|
|
||||||
{"@every 5m", ConstantDelaySchedule{time.Duration(5) * time.Minute}},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, c := range entries {
|
|
||||||
actual, err := Parse(c.expr)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(actual, c.expected) {
|
|
||||||
t.Errorf("%s => (expected) %b != %b (actual)", c.expr, c.expected, actual)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
161
vendor/github.com/robfig/cron/spec.go
generated
vendored
161
vendor/github.com/robfig/cron/spec.go
generated
vendored
|
@ -1,161 +0,0 @@
|
||||||
package cron
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SpecSchedule specifies a duty cycle (to the second granularity), based on a
|
|
||||||
// traditional crontab specification. It is computed initially and stored as bit sets.
|
|
||||||
type SpecSchedule struct {
|
|
||||||
Second, Minute, Hour, Dom, Month, Dow uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
// bounds provides a range of acceptable values (plus a map of name to value).
|
|
||||||
type bounds struct {
|
|
||||||
min, max uint
|
|
||||||
names map[string]uint
|
|
||||||
}
|
|
||||||
|
|
||||||
// The bounds for each field.
|
|
||||||
var (
|
|
||||||
seconds = bounds{0, 59, nil}
|
|
||||||
minutes = bounds{0, 59, nil}
|
|
||||||
hours = bounds{0, 23, nil}
|
|
||||||
dom = bounds{1, 31, nil}
|
|
||||||
months = bounds{1, 12, map[string]uint{
|
|
||||||
"jan": 1,
|
|
||||||
"feb": 2,
|
|
||||||
"mar": 3,
|
|
||||||
"apr": 4,
|
|
||||||
"may": 5,
|
|
||||||
"jun": 6,
|
|
||||||
"jul": 7,
|
|
||||||
"aug": 8,
|
|
||||||
"sep": 9,
|
|
||||||
"oct": 10,
|
|
||||||
"nov": 11,
|
|
||||||
"dec": 12,
|
|
||||||
}}
|
|
||||||
dow = bounds{0, 6, map[string]uint{
|
|
||||||
"sun": 0,
|
|
||||||
"mon": 1,
|
|
||||||
"tue": 2,
|
|
||||||
"wed": 3,
|
|
||||||
"thu": 4,
|
|
||||||
"fri": 5,
|
|
||||||
"sat": 6,
|
|
||||||
}}
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Set the top bit if a star was included in the expression.
|
|
||||||
starBit = 1 << 63
|
|
||||||
)
|
|
||||||
|
|
||||||
// Next returns the next time this schedule is activated, greater than the given
|
|
||||||
// time. If no time can be found to satisfy the schedule, return the zero time.
|
|
||||||
func (s *SpecSchedule) Next(t time.Time) time.Time {
|
|
||||||
// General approach:
|
|
||||||
// For Month, Day, Hour, Minute, Second:
|
|
||||||
// Check if the time value matches. If yes, continue to the next field.
|
|
||||||
// If the field doesn't match the schedule, then increment the field until it matches.
|
|
||||||
// While incrementing the field, a wrap-around brings it back to the beginning
|
|
||||||
// of the field list (since it is necessary to re-verify previous field
|
|
||||||
// values)
|
|
||||||
|
|
||||||
// Start at the earliest possible time (the upcoming second).
|
|
||||||
t = t.Add(1*time.Second - time.Duration(t.Nanosecond())*time.Nanosecond)
|
|
||||||
|
|
||||||
// This flag indicates whether a field has been incremented.
|
|
||||||
added := false
|
|
||||||
|
|
||||||
// If no time is found within five years, return zero.
|
|
||||||
yearLimit := t.Year() + 5
|
|
||||||
|
|
||||||
WRAP:
|
|
||||||
if t.Year() > yearLimit {
|
|
||||||
return time.Time{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the first applicable month.
|
|
||||||
// If it's this month, then do nothing.
|
|
||||||
for 1<<uint(t.Month())&s.Month == 0 {
|
|
||||||
// If we have to add a month, reset the other parts to 0.
|
|
||||||
if !added {
|
|
||||||
added = true
|
|
||||||
// Otherwise, set the date at the beginning (since the current time is irrelevant).
|
|
||||||
t = time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, t.Location())
|
|
||||||
}
|
|
||||||
t = t.AddDate(0, 1, 0)
|
|
||||||
|
|
||||||
// Wrapped around.
|
|
||||||
if t.Month() == time.January {
|
|
||||||
goto WRAP
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now get a day in that month.
|
|
||||||
for !dayMatches(s, t) {
|
|
||||||
if !added {
|
|
||||||
added = true
|
|
||||||
t = time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
|
|
||||||
}
|
|
||||||
t = t.AddDate(0, 0, 1)
|
|
||||||
|
|
||||||
if t.Day() == 1 {
|
|
||||||
goto WRAP
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for 1<<uint(t.Hour())&s.Hour == 0 {
|
|
||||||
if !added {
|
|
||||||
added = true
|
|
||||||
t = time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), 0, 0, 0, t.Location())
|
|
||||||
}
|
|
||||||
t = t.Add(1 * time.Hour)
|
|
||||||
|
|
||||||
if t.Hour() == 0 {
|
|
||||||
goto WRAP
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for 1<<uint(t.Minute())&s.Minute == 0 {
|
|
||||||
if !added {
|
|
||||||
added = true
|
|
||||||
t = time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), 0, 0, t.Location())
|
|
||||||
}
|
|
||||||
t = t.Add(1 * time.Minute)
|
|
||||||
|
|
||||||
if t.Minute() == 0 {
|
|
||||||
goto WRAP
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for 1<<uint(t.Second())&s.Second == 0 {
|
|
||||||
if !added {
|
|
||||||
added = true
|
|
||||||
t = time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), 0, t.Location())
|
|
||||||
}
|
|
||||||
t = t.Add(1 * time.Second)
|
|
||||||
|
|
||||||
if t.Second() == 0 {
|
|
||||||
goto WRAP
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
// dayMatches returns true if the schedule's day-of-week and day-of-month
|
|
||||||
// restrictions are satisfied by the given time.
|
|
||||||
func dayMatches(s *SpecSchedule, t time.Time) bool {
|
|
||||||
var (
|
|
||||||
domMatch bool = 1<<uint(t.Day())&s.Dom > 0
|
|
||||||
dowMatch bool = 1<<uint(t.Weekday())&s.Dow > 0
|
|
||||||
)
|
|
||||||
|
|
||||||
if s.Dom&starBit > 0 || s.Dow&starBit > 0 {
|
|
||||||
return domMatch && dowMatch
|
|
||||||
}
|
|
||||||
return domMatch || dowMatch
|
|
||||||
}
|
|
173
vendor/github.com/robfig/cron/spec_test.go
generated
vendored
173
vendor/github.com/robfig/cron/spec_test.go
generated
vendored
|
@ -1,173 +0,0 @@
|
||||||
package cron
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestActivation(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
time, spec string
|
|
||||||
expected bool
|
|
||||||
}{
|
|
||||||
// Every fifteen minutes.
|
|
||||||
{"Mon Jul 9 15:00 2012", "0 0/15 * * *", true},
|
|
||||||
{"Mon Jul 9 15:45 2012", "0 0/15 * * *", true},
|
|
||||||
{"Mon Jul 9 15:40 2012", "0 0/15 * * *", false},
|
|
||||||
|
|
||||||
// Every fifteen minutes, starting at 5 minutes.
|
|
||||||
{"Mon Jul 9 15:05 2012", "0 5/15 * * *", true},
|
|
||||||
{"Mon Jul 9 15:20 2012", "0 5/15 * * *", true},
|
|
||||||
{"Mon Jul 9 15:50 2012", "0 5/15 * * *", true},
|
|
||||||
|
|
||||||
// Named months
|
|
||||||
{"Sun Jul 15 15:00 2012", "0 0/15 * * Jul", true},
|
|
||||||
{"Sun Jul 15 15:00 2012", "0 0/15 * * Jun", false},
|
|
||||||
|
|
||||||
// Everything set.
|
|
||||||
{"Sun Jul 15 08:30 2012", "0 30 08 ? Jul Sun", true},
|
|
||||||
{"Sun Jul 15 08:30 2012", "0 30 08 15 Jul ?", true},
|
|
||||||
{"Mon Jul 16 08:30 2012", "0 30 08 ? Jul Sun", false},
|
|
||||||
{"Mon Jul 16 08:30 2012", "0 30 08 15 Jul ?", false},
|
|
||||||
|
|
||||||
// Predefined schedules
|
|
||||||
{"Mon Jul 9 15:00 2012", "@hourly", true},
|
|
||||||
{"Mon Jul 9 15:04 2012", "@hourly", false},
|
|
||||||
{"Mon Jul 9 15:00 2012", "@daily", false},
|
|
||||||
{"Mon Jul 9 00:00 2012", "@daily", true},
|
|
||||||
{"Mon Jul 9 00:00 2012", "@weekly", false},
|
|
||||||
{"Sun Jul 8 00:00 2012", "@weekly", true},
|
|
||||||
{"Sun Jul 8 01:00 2012", "@weekly", false},
|
|
||||||
{"Sun Jul 8 00:00 2012", "@monthly", false},
|
|
||||||
{"Sun Jul 1 00:00 2012", "@monthly", true},
|
|
||||||
|
|
||||||
// Test interaction of DOW and DOM.
|
|
||||||
// If both are specified, then only one needs to match.
|
|
||||||
{"Sun Jul 15 00:00 2012", "0 * * 1,15 * Sun", true},
|
|
||||||
{"Fri Jun 15 00:00 2012", "0 * * 1,15 * Sun", true},
|
|
||||||
{"Wed Aug 1 00:00 2012", "0 * * 1,15 * Sun", true},
|
|
||||||
|
|
||||||
// However, if one has a star, then both need to match.
|
|
||||||
{"Sun Jul 15 00:00 2012", "0 * * * * Mon", false},
|
|
||||||
{"Sun Jul 15 00:00 2012", "0 * * */10 * Sun", false},
|
|
||||||
{"Mon Jul 9 00:00 2012", "0 * * 1,15 * *", false},
|
|
||||||
{"Sun Jul 15 00:00 2012", "0 * * 1,15 * *", true},
|
|
||||||
{"Sun Jul 15 00:00 2012", "0 * * */2 * Sun", true},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
sched, err := Parse(test.spec)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
actual := sched.Next(getTime(test.time).Add(-1 * time.Second))
|
|
||||||
expected := getTime(test.time)
|
|
||||||
if test.expected && expected != actual || !test.expected && expected == actual {
|
|
||||||
t.Errorf("Fail evaluating %s on %s: (expected) %s != %s (actual)",
|
|
||||||
test.spec, test.time, expected, actual)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNext(t *testing.T) {
|
|
||||||
runs := []struct {
|
|
||||||
time, spec string
|
|
||||||
expected string
|
|
||||||
}{
|
|
||||||
// Simple cases
|
|
||||||
{"Mon Jul 9 14:45 2012", "0 0/15 * * *", "Mon Jul 9 15:00 2012"},
|
|
||||||
{"Mon Jul 9 14:59 2012", "0 0/15 * * *", "Mon Jul 9 15:00 2012"},
|
|
||||||
{"Mon Jul 9 14:59:59 2012", "0 0/15 * * *", "Mon Jul 9 15:00 2012"},
|
|
||||||
|
|
||||||
// Wrap around hours
|
|
||||||
{"Mon Jul 9 15:45 2012", "0 20-35/15 * * *", "Mon Jul 9 16:20 2012"},
|
|
||||||
|
|
||||||
// Wrap around days
|
|
||||||
{"Mon Jul 9 23:46 2012", "0 */15 * * *", "Tue Jul 10 00:00 2012"},
|
|
||||||
{"Mon Jul 9 23:45 2012", "0 20-35/15 * * *", "Tue Jul 10 00:20 2012"},
|
|
||||||
{"Mon Jul 9 23:35:51 2012", "15/35 20-35/15 * * *", "Tue Jul 10 00:20:15 2012"},
|
|
||||||
{"Mon Jul 9 23:35:51 2012", "15/35 20-35/15 1/2 * *", "Tue Jul 10 01:20:15 2012"},
|
|
||||||
{"Mon Jul 9 23:35:51 2012", "15/35 20-35/15 10-12 * *", "Tue Jul 10 10:20:15 2012"},
|
|
||||||
|
|
||||||
{"Mon Jul 9 23:35:51 2012", "15/35 20-35/15 1/2 */2 * *", "Thu Jul 11 01:20:15 2012"},
|
|
||||||
{"Mon Jul 9 23:35:51 2012", "15/35 20-35/15 * 9-20 * *", "Wed Jul 10 00:20:15 2012"},
|
|
||||||
{"Mon Jul 9 23:35:51 2012", "15/35 20-35/15 * 9-20 Jul *", "Wed Jul 10 00:20:15 2012"},
|
|
||||||
|
|
||||||
// Wrap around months
|
|
||||||
{"Mon Jul 9 23:35 2012", "0 0 0 9 Apr-Oct ?", "Thu Aug 9 00:00 2012"},
|
|
||||||
{"Mon Jul 9 23:35 2012", "0 0 0 */5 Apr,Aug,Oct Mon", "Mon Aug 6 00:00 2012"},
|
|
||||||
{"Mon Jul 9 23:35 2012", "0 0 0 */5 Oct Mon", "Mon Oct 1 00:00 2012"},
|
|
||||||
|
|
||||||
// Wrap around years
|
|
||||||
{"Mon Jul 9 23:35 2012", "0 0 0 * Feb Mon", "Mon Feb 4 00:00 2013"},
|
|
||||||
{"Mon Jul 9 23:35 2012", "0 0 0 * Feb Mon/2", "Fri Feb 1 00:00 2013"},
|
|
||||||
|
|
||||||
// Wrap around minute, hour, day, month, and year
|
|
||||||
{"Mon Dec 31 23:59:45 2012", "0 * * * * *", "Tue Jan 1 00:00:00 2013"},
|
|
||||||
|
|
||||||
// Leap year
|
|
||||||
{"Mon Jul 9 23:35 2012", "0 0 0 29 Feb ?", "Mon Feb 29 00:00 2016"},
|
|
||||||
|
|
||||||
// Daylight savings time EST -> EDT
|
|
||||||
{"2012-03-11T00:00:00-0500", "0 30 2 11 Mar ?", "2013-03-11T02:30:00-0400"},
|
|
||||||
|
|
||||||
// Daylight savings time EDT -> EST
|
|
||||||
{"2012-11-04T00:00:00-0400", "0 30 2 04 Nov ?", "2012-11-04T02:30:00-0500"},
|
|
||||||
{"2012-11-04T01:45:00-0400", "0 30 1 04 Nov ?", "2012-11-04T01:30:00-0500"},
|
|
||||||
|
|
||||||
// Unsatisfiable
|
|
||||||
{"Mon Jul 9 23:35 2012", "0 0 0 30 Feb ?", ""},
|
|
||||||
{"Mon Jul 9 23:35 2012", "0 0 0 31 Apr ?", ""},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, c := range runs {
|
|
||||||
sched, err := Parse(c.spec)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
actual := sched.Next(getTime(c.time))
|
|
||||||
expected := getTime(c.expected)
|
|
||||||
if !actual.Equal(expected) {
|
|
||||||
t.Errorf("%s, \"%s\": (expected) %v != %v (actual)", c.time, c.spec, expected, actual)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestErrors(t *testing.T) {
|
|
||||||
invalidSpecs := []string{
|
|
||||||
"xyz",
|
|
||||||
"60 0 * * *",
|
|
||||||
"0 60 * * *",
|
|
||||||
"0 0 * * XYZ",
|
|
||||||
}
|
|
||||||
for _, spec := range invalidSpecs {
|
|
||||||
_, err := Parse(spec)
|
|
||||||
if err == nil {
|
|
||||||
t.Error("expected an error parsing: ", spec)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTime(value string) time.Time {
|
|
||||||
if value == "" {
|
|
||||||
return time.Time{}
|
|
||||||
}
|
|
||||||
t, err := time.Parse("Mon Jan 2 15:04 2006", value)
|
|
||||||
if err != nil {
|
|
||||||
t, err = time.Parse("Mon Jan 2 15:04:05 2006", value)
|
|
||||||
if err != nil {
|
|
||||||
t, err = time.Parse("2006-01-02T15:04:05-0700", value)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
// Daylight savings time tests require location
|
|
||||||
if ny, err := time.LoadLocation("America/New_York"); err == nil {
|
|
||||||
t = t.In(ny)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return t
|
|
||||||
}
|
|
2
vendor/github.com/spf13/pflag/.gitignore
generated
vendored
2
vendor/github.com/spf13/pflag/.gitignore
generated
vendored
|
@ -1,2 +0,0 @@
|
||||||
.idea/*
|
|
||||||
|
|
21
vendor/github.com/spf13/pflag/.travis.yml
generated
vendored
21
vendor/github.com/spf13/pflag/.travis.yml
generated
vendored
|
@ -1,21 +0,0 @@
|
||||||
sudo: false
|
|
||||||
|
|
||||||
language: go
|
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.7.3
|
|
||||||
- 1.8.1
|
|
||||||
- tip
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
allow_failures:
|
|
||||||
- go: tip
|
|
||||||
|
|
||||||
install:
|
|
||||||
- go get github.com/golang/lint/golint
|
|
||||||
- export PATH=$GOPATH/bin:$PATH
|
|
||||||
- go install ./...
|
|
||||||
|
|
||||||
script:
|
|
||||||
- verify/all.sh -v
|
|
||||||
- go test ./...
|
|
28
vendor/github.com/spf13/pflag/LICENSE
generated
vendored
28
vendor/github.com/spf13/pflag/LICENSE
generated
vendored
|
@ -1,28 +0,0 @@
|
||||||
Copyright (c) 2012 Alex Ogier. All rights reserved.
|
|
||||||
Copyright (c) 2012 The Go Authors. All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following disclaimer
|
|
||||||
in the documentation and/or other materials provided with the
|
|
||||||
distribution.
|
|
||||||
* Neither the name of Google Inc. nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
296
vendor/github.com/spf13/pflag/README.md
generated
vendored
296
vendor/github.com/spf13/pflag/README.md
generated
vendored
|
@ -1,296 +0,0 @@
|
||||||
[![Build Status](https://travis-ci.org/spf13/pflag.svg?branch=master)](https://travis-ci.org/spf13/pflag)
|
|
||||||
[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/pflag)](https://goreportcard.com/report/github.com/spf13/pflag)
|
|
||||||
[![GoDoc](https://godoc.org/github.com/spf13/pflag?status.svg)](https://godoc.org/github.com/spf13/pflag)
|
|
||||||
|
|
||||||
## Description
|
|
||||||
|
|
||||||
pflag is a drop-in replacement for Go's flag package, implementing
|
|
||||||
POSIX/GNU-style --flags.
|
|
||||||
|
|
||||||
pflag is compatible with the [GNU extensions to the POSIX recommendations
|
|
||||||
for command-line options][1]. For a more precise description, see the
|
|
||||||
"Command-line flag syntax" section below.
|
|
||||||
|
|
||||||
[1]: http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html
|
|
||||||
|
|
||||||
pflag is available under the same style of BSD license as the Go language,
|
|
||||||
which can be found in the LICENSE file.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
pflag is available using the standard `go get` command.
|
|
||||||
|
|
||||||
Install by running:
|
|
||||||
|
|
||||||
go get github.com/spf13/pflag
|
|
||||||
|
|
||||||
Run tests by running:
|
|
||||||
|
|
||||||
go test github.com/spf13/pflag
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
pflag is a drop-in replacement of Go's native flag package. If you import
|
|
||||||
pflag under the name "flag" then all code should continue to function
|
|
||||||
with no changes.
|
|
||||||
|
|
||||||
``` go
|
|
||||||
import flag "github.com/spf13/pflag"
|
|
||||||
```
|
|
||||||
|
|
||||||
There is one exception to this: if you directly instantiate the Flag struct
|
|
||||||
there is one more field "Shorthand" that you will need to set.
|
|
||||||
Most code never instantiates this struct directly, and instead uses
|
|
||||||
functions such as String(), BoolVar(), and Var(), and is therefore
|
|
||||||
unaffected.
|
|
||||||
|
|
||||||
Define flags using flag.String(), Bool(), Int(), etc.
|
|
||||||
|
|
||||||
This declares an integer flag, -flagname, stored in the pointer ip, with type *int.
|
|
||||||
|
|
||||||
``` go
|
|
||||||
var ip *int = flag.Int("flagname", 1234, "help message for flagname")
|
|
||||||
```
|
|
||||||
|
|
||||||
If you like, you can bind the flag to a variable using the Var() functions.
|
|
||||||
|
|
||||||
``` go
|
|
||||||
var flagvar int
|
|
||||||
func init() {
|
|
||||||
flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Or you can create custom flags that satisfy the Value interface (with
|
|
||||||
pointer receivers) and couple them to flag parsing by
|
|
||||||
|
|
||||||
``` go
|
|
||||||
flag.Var(&flagVal, "name", "help message for flagname")
|
|
||||||
```
|
|
||||||
|
|
||||||
For such flags, the default value is just the initial value of the variable.
|
|
||||||
|
|
||||||
After all flags are defined, call
|
|
||||||
|
|
||||||
``` go
|
|
||||||
flag.Parse()
|
|
||||||
```
|
|
||||||
|
|
||||||
to parse the command line into the defined flags.
|
|
||||||
|
|
||||||
Flags may then be used directly. If you're using the flags themselves,
|
|
||||||
they are all pointers; if you bind to variables, they're values.
|
|
||||||
|
|
||||||
``` go
|
|
||||||
fmt.Println("ip has value ", *ip)
|
|
||||||
fmt.Println("flagvar has value ", flagvar)
|
|
||||||
```
|
|
||||||
|
|
||||||
There are helpers function to get values later if you have the FlagSet but
|
|
||||||
it was difficult to keep up with all of the flag pointers in your code.
|
|
||||||
If you have a pflag.FlagSet with a flag called 'flagname' of type int you
|
|
||||||
can use GetInt() to get the int value. But notice that 'flagname' must exist
|
|
||||||
and it must be an int. GetString("flagname") will fail.
|
|
||||||
|
|
||||||
``` go
|
|
||||||
i, err := flagset.GetInt("flagname")
|
|
||||||
```
|
|
||||||
|
|
||||||
After parsing, the arguments after the flag are available as the
|
|
||||||
slice flag.Args() or individually as flag.Arg(i).
|
|
||||||
The arguments are indexed from 0 through flag.NArg()-1.
|
|
||||||
|
|
||||||
The pflag package also defines some new functions that are not in flag,
|
|
||||||
that give one-letter shorthands for flags. You can use these by appending
|
|
||||||
'P' to the name of any function that defines a flag.
|
|
||||||
|
|
||||||
``` go
|
|
||||||
var ip = flag.IntP("flagname", "f", 1234, "help message")
|
|
||||||
var flagvar bool
|
|
||||||
func init() {
|
|
||||||
flag.BoolVarP(&flagvar, "boolname", "b", true, "help message")
|
|
||||||
}
|
|
||||||
flag.VarP(&flagVal, "varname", "v", "help message")
|
|
||||||
```
|
|
||||||
|
|
||||||
Shorthand letters can be used with single dashes on the command line.
|
|
||||||
Boolean shorthand flags can be combined with other shorthand flags.
|
|
||||||
|
|
||||||
The default set of command-line flags is controlled by
|
|
||||||
top-level functions. The FlagSet type allows one to define
|
|
||||||
independent sets of flags, such as to implement subcommands
|
|
||||||
in a command-line interface. The methods of FlagSet are
|
|
||||||
analogous to the top-level functions for the command-line
|
|
||||||
flag set.
|
|
||||||
|
|
||||||
## Setting no option default values for flags
|
|
||||||
|
|
||||||
After you create a flag it is possible to set the pflag.NoOptDefVal for
|
|
||||||
the given flag. Doing this changes the meaning of the flag slightly. If
|
|
||||||
a flag has a NoOptDefVal and the flag is set on the command line without
|
|
||||||
an option the flag will be set to the NoOptDefVal. For example given:
|
|
||||||
|
|
||||||
``` go
|
|
||||||
var ip = flag.IntP("flagname", "f", 1234, "help message")
|
|
||||||
flag.Lookup("flagname").NoOptDefVal = "4321"
|
|
||||||
```
|
|
||||||
|
|
||||||
Would result in something like
|
|
||||||
|
|
||||||
| Parsed Arguments | Resulting Value |
|
|
||||||
| ------------- | ------------- |
|
|
||||||
| --flagname=1357 | ip=1357 |
|
|
||||||
| --flagname | ip=4321 |
|
|
||||||
| [nothing] | ip=1234 |
|
|
||||||
|
|
||||||
## Command line flag syntax
|
|
||||||
|
|
||||||
```
|
|
||||||
--flag // boolean flags, or flags with no option default values
|
|
||||||
--flag x // only on flags without a default value
|
|
||||||
--flag=x
|
|
||||||
```
|
|
||||||
|
|
||||||
Unlike the flag package, a single dash before an option means something
|
|
||||||
different than a double dash. Single dashes signify a series of shorthand
|
|
||||||
letters for flags. All but the last shorthand letter must be boolean flags
|
|
||||||
or a flag with a default value
|
|
||||||
|
|
||||||
```
|
|
||||||
// boolean or flags where the 'no option default value' is set
|
|
||||||
-f
|
|
||||||
-f=true
|
|
||||||
-abc
|
|
||||||
but
|
|
||||||
-b true is INVALID
|
|
||||||
|
|
||||||
// non-boolean and flags without a 'no option default value'
|
|
||||||
-n 1234
|
|
||||||
-n=1234
|
|
||||||
-n1234
|
|
||||||
|
|
||||||
// mixed
|
|
||||||
-abcs "hello"
|
|
||||||
-absd="hello"
|
|
||||||
-abcs1234
|
|
||||||
```
|
|
||||||
|
|
||||||
Flag parsing stops after the terminator "--". Unlike the flag package,
|
|
||||||
flags can be interspersed with arguments anywhere on the command line
|
|
||||||
before this terminator.
|
|
||||||
|
|
||||||
Integer flags accept 1234, 0664, 0x1234 and may be negative.
|
|
||||||
Boolean flags (in their long form) accept 1, 0, t, f, true, false,
|
|
||||||
TRUE, FALSE, True, False.
|
|
||||||
Duration flags accept any input valid for time.ParseDuration.
|
|
||||||
|
|
||||||
## Mutating or "Normalizing" Flag names
|
|
||||||
|
|
||||||
It is possible to set a custom flag name 'normalization function.' It allows flag names to be mutated both when created in the code and when used on the command line to some 'normalized' form. The 'normalized' form is used for comparison. Two examples of using the custom normalization func follow.
|
|
||||||
|
|
||||||
**Example #1**: You want -, _, and . in flags to compare the same. aka --my-flag == --my_flag == --my.flag
|
|
||||||
|
|
||||||
``` go
|
|
||||||
func wordSepNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName {
|
|
||||||
from := []string{"-", "_"}
|
|
||||||
to := "."
|
|
||||||
for _, sep := range from {
|
|
||||||
name = strings.Replace(name, sep, to, -1)
|
|
||||||
}
|
|
||||||
return pflag.NormalizedName(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
myFlagSet.SetNormalizeFunc(wordSepNormalizeFunc)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Example #2**: You want to alias two flags. aka --old-flag-name == --new-flag-name
|
|
||||||
|
|
||||||
``` go
|
|
||||||
func aliasNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName {
|
|
||||||
switch name {
|
|
||||||
case "old-flag-name":
|
|
||||||
name = "new-flag-name"
|
|
||||||
break
|
|
||||||
}
|
|
||||||
return pflag.NormalizedName(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
myFlagSet.SetNormalizeFunc(aliasNormalizeFunc)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Deprecating a flag or its shorthand
|
|
||||||
It is possible to deprecate a flag, or just its shorthand. Deprecating a flag/shorthand hides it from help text and prints a usage message when the deprecated flag/shorthand is used.
|
|
||||||
|
|
||||||
**Example #1**: You want to deprecate a flag named "badflag" as well as inform the users what flag they should use instead.
|
|
||||||
```go
|
|
||||||
// deprecate a flag by specifying its name and a usage message
|
|
||||||
flags.MarkDeprecated("badflag", "please use --good-flag instead")
|
|
||||||
```
|
|
||||||
This hides "badflag" from help text, and prints `Flag --badflag has been deprecated, please use --good-flag instead` when "badflag" is used.
|
|
||||||
|
|
||||||
**Example #2**: You want to keep a flag name "noshorthandflag" but deprecate its shortname "n".
|
|
||||||
```go
|
|
||||||
// deprecate a flag shorthand by specifying its flag name and a usage message
|
|
||||||
flags.MarkShorthandDeprecated("noshorthandflag", "please use --noshorthandflag only")
|
|
||||||
```
|
|
||||||
This hides the shortname "n" from help text, and prints `Flag shorthand -n has been deprecated, please use --noshorthandflag only` when the shorthand "n" is used.
|
|
||||||
|
|
||||||
Note that usage message is essential here, and it should not be empty.
|
|
||||||
|
|
||||||
## Hidden flags
|
|
||||||
It is possible to mark a flag as hidden, meaning it will still function as normal, however will not show up in usage/help text.
|
|
||||||
|
|
||||||
**Example**: You have a flag named "secretFlag" that you need for internal use only and don't want it showing up in help text, or for its usage text to be available.
|
|
||||||
```go
|
|
||||||
// hide a flag by specifying its name
|
|
||||||
flags.MarkHidden("secretFlag")
|
|
||||||
```
|
|
||||||
|
|
||||||
## Disable sorting of flags
|
|
||||||
`pflag` allows you to disable sorting of flags for help and usage message.
|
|
||||||
|
|
||||||
**Example**:
|
|
||||||
```go
|
|
||||||
flags.BoolP("verbose", "v", false, "verbose output")
|
|
||||||
flags.String("coolflag", "yeaah", "it's really cool flag")
|
|
||||||
flags.Int("usefulflag", 777, "sometimes it's very useful")
|
|
||||||
flags.SortFlags = false
|
|
||||||
flags.PrintDefaults()
|
|
||||||
```
|
|
||||||
**Output**:
|
|
||||||
```
|
|
||||||
-v, --verbose verbose output
|
|
||||||
--coolflag string it's really cool flag (default "yeaah")
|
|
||||||
--usefulflag int sometimes it's very useful (default 777)
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Supporting Go flags when using pflag
|
|
||||||
In order to support flags defined using Go's `flag` package, they must be added to the `pflag` flagset. This is usually necessary
|
|
||||||
to support flags defined by third-party dependencies (e.g. `golang/glog`).
|
|
||||||
|
|
||||||
**Example**: You want to add the Go flags to the `CommandLine` flagset
|
|
||||||
```go
|
|
||||||
import (
|
|
||||||
goflag "flag"
|
|
||||||
flag "github.com/spf13/pflag"
|
|
||||||
)
|
|
||||||
|
|
||||||
var ip *int = flag.Int("flagname", 1234, "help message for flagname")
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
flag.CommandLine.AddGoFlagSet(goflag.CommandLine)
|
|
||||||
flag.Parse()
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## More info
|
|
||||||
|
|
||||||
You can see the full reference documentation of the pflag package
|
|
||||||
[at godoc.org][3], or through go's standard documentation system by
|
|
||||||
running `godoc -http=:6060` and browsing to
|
|
||||||
[http://localhost:6060/pkg/github.com/spf13/pflag][2] after
|
|
||||||
installation.
|
|
||||||
|
|
||||||
[2]: http://localhost:6060/pkg/github.com/spf13/pflag
|
|
||||||
[3]: http://godoc.org/github.com/spf13/pflag
|
|
94
vendor/github.com/spf13/pflag/bool.go
generated
vendored
94
vendor/github.com/spf13/pflag/bool.go
generated
vendored
|
@ -1,94 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import "strconv"
|
|
||||||
|
|
||||||
// optional interface to indicate boolean flags that can be
|
|
||||||
// supplied without "=value" text
|
|
||||||
type boolFlag interface {
|
|
||||||
Value
|
|
||||||
IsBoolFlag() bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- bool Value
|
|
||||||
type boolValue bool
|
|
||||||
|
|
||||||
func newBoolValue(val bool, p *bool) *boolValue {
|
|
||||||
*p = val
|
|
||||||
return (*boolValue)(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *boolValue) Set(s string) error {
|
|
||||||
v, err := strconv.ParseBool(s)
|
|
||||||
*b = boolValue(v)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *boolValue) Type() string {
|
|
||||||
return "bool"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *boolValue) String() string { return strconv.FormatBool(bool(*b)) }
|
|
||||||
|
|
||||||
func (b *boolValue) IsBoolFlag() bool { return true }
|
|
||||||
|
|
||||||
func boolConv(sval string) (interface{}, error) {
|
|
||||||
return strconv.ParseBool(sval)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetBool return the bool value of a flag with the given name
|
|
||||||
func (f *FlagSet) GetBool(name string) (bool, error) {
|
|
||||||
val, err := f.getFlagType(name, "bool", boolConv)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return val.(bool), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoolVar defines a bool flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a bool variable in which to store the value of the flag.
|
|
||||||
func (f *FlagSet) BoolVar(p *bool, name string, value bool, usage string) {
|
|
||||||
f.BoolVarP(p, name, "", value, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoolVarP is like BoolVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) BoolVarP(p *bool, name, shorthand string, value bool, usage string) {
|
|
||||||
flag := f.VarPF(newBoolValue(value, p), name, shorthand, usage)
|
|
||||||
flag.NoOptDefVal = "true"
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoolVar defines a bool flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a bool variable in which to store the value of the flag.
|
|
||||||
func BoolVar(p *bool, name string, value bool, usage string) {
|
|
||||||
BoolVarP(p, name, "", value, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoolVarP is like BoolVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func BoolVarP(p *bool, name, shorthand string, value bool, usage string) {
|
|
||||||
flag := CommandLine.VarPF(newBoolValue(value, p), name, shorthand, usage)
|
|
||||||
flag.NoOptDefVal = "true"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bool defines a bool flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a bool variable that stores the value of the flag.
|
|
||||||
func (f *FlagSet) Bool(name string, value bool, usage string) *bool {
|
|
||||||
return f.BoolP(name, "", value, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoolP is like Bool, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) BoolP(name, shorthand string, value bool, usage string) *bool {
|
|
||||||
p := new(bool)
|
|
||||||
f.BoolVarP(p, name, shorthand, value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bool defines a bool flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a bool variable that stores the value of the flag.
|
|
||||||
func Bool(name string, value bool, usage string) *bool {
|
|
||||||
return BoolP(name, "", value, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoolP is like Bool, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func BoolP(name, shorthand string, value bool, usage string) *bool {
|
|
||||||
b := CommandLine.BoolP(name, shorthand, value, usage)
|
|
||||||
return b
|
|
||||||
}
|
|
147
vendor/github.com/spf13/pflag/bool_slice.go
generated
vendored
147
vendor/github.com/spf13/pflag/bool_slice.go
generated
vendored
|
@ -1,147 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// -- boolSlice Value
|
|
||||||
type boolSliceValue struct {
|
|
||||||
value *[]bool
|
|
||||||
changed bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func newBoolSliceValue(val []bool, p *[]bool) *boolSliceValue {
|
|
||||||
bsv := new(boolSliceValue)
|
|
||||||
bsv.value = p
|
|
||||||
*bsv.value = val
|
|
||||||
return bsv
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set converts, and assigns, the comma-separated boolean argument string representation as the []bool value of this flag.
|
|
||||||
// If Set is called on a flag that already has a []bool assigned, the newly converted values will be appended.
|
|
||||||
func (s *boolSliceValue) Set(val string) error {
|
|
||||||
|
|
||||||
// remove all quote characters
|
|
||||||
rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "")
|
|
||||||
|
|
||||||
// read flag arguments with CSV parser
|
|
||||||
boolStrSlice, err := readAsCSV(rmQuote.Replace(val))
|
|
||||||
if err != nil && err != io.EOF {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse boolean values into slice
|
|
||||||
out := make([]bool, 0, len(boolStrSlice))
|
|
||||||
for _, boolStr := range boolStrSlice {
|
|
||||||
b, err := strconv.ParseBool(strings.TrimSpace(boolStr))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
out = append(out, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !s.changed {
|
|
||||||
*s.value = out
|
|
||||||
} else {
|
|
||||||
*s.value = append(*s.value, out...)
|
|
||||||
}
|
|
||||||
|
|
||||||
s.changed = true
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type returns a string that uniquely represents this flag's type.
|
|
||||||
func (s *boolSliceValue) Type() string {
|
|
||||||
return "boolSlice"
|
|
||||||
}
|
|
||||||
|
|
||||||
// String defines a "native" format for this boolean slice flag value.
|
|
||||||
func (s *boolSliceValue) String() string {
|
|
||||||
|
|
||||||
boolStrSlice := make([]string, len(*s.value))
|
|
||||||
for i, b := range *s.value {
|
|
||||||
boolStrSlice[i] = strconv.FormatBool(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
out, _ := writeAsCSV(boolStrSlice)
|
|
||||||
|
|
||||||
return "[" + out + "]"
|
|
||||||
}
|
|
||||||
|
|
||||||
func boolSliceConv(val string) (interface{}, error) {
|
|
||||||
val = strings.Trim(val, "[]")
|
|
||||||
// Empty string would cause a slice with one (empty) entry
|
|
||||||
if len(val) == 0 {
|
|
||||||
return []bool{}, nil
|
|
||||||
}
|
|
||||||
ss := strings.Split(val, ",")
|
|
||||||
out := make([]bool, len(ss))
|
|
||||||
for i, t := range ss {
|
|
||||||
var err error
|
|
||||||
out[i], err = strconv.ParseBool(t)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetBoolSlice returns the []bool value of a flag with the given name.
|
|
||||||
func (f *FlagSet) GetBoolSlice(name string) ([]bool, error) {
|
|
||||||
val, err := f.getFlagType(name, "boolSlice", boolSliceConv)
|
|
||||||
if err != nil {
|
|
||||||
return []bool{}, err
|
|
||||||
}
|
|
||||||
return val.([]bool), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoolSliceVar defines a boolSlice flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a []bool variable in which to store the value of the flag.
|
|
||||||
func (f *FlagSet) BoolSliceVar(p *[]bool, name string, value []bool, usage string) {
|
|
||||||
f.VarP(newBoolSliceValue(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoolSliceVarP is like BoolSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) BoolSliceVarP(p *[]bool, name, shorthand string, value []bool, usage string) {
|
|
||||||
f.VarP(newBoolSliceValue(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoolSliceVar defines a []bool flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a []bool variable in which to store the value of the flag.
|
|
||||||
func BoolSliceVar(p *[]bool, name string, value []bool, usage string) {
|
|
||||||
CommandLine.VarP(newBoolSliceValue(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoolSliceVarP is like BoolSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func BoolSliceVarP(p *[]bool, name, shorthand string, value []bool, usage string) {
|
|
||||||
CommandLine.VarP(newBoolSliceValue(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoolSlice defines a []bool flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a []bool variable that stores the value of the flag.
|
|
||||||
func (f *FlagSet) BoolSlice(name string, value []bool, usage string) *[]bool {
|
|
||||||
p := []bool{}
|
|
||||||
f.BoolSliceVarP(&p, name, "", value, usage)
|
|
||||||
return &p
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoolSliceP is like BoolSlice, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) BoolSliceP(name, shorthand string, value []bool, usage string) *[]bool {
|
|
||||||
p := []bool{}
|
|
||||||
f.BoolSliceVarP(&p, name, shorthand, value, usage)
|
|
||||||
return &p
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoolSlice defines a []bool flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a []bool variable that stores the value of the flag.
|
|
||||||
func BoolSlice(name string, value []bool, usage string) *[]bool {
|
|
||||||
return CommandLine.BoolSliceP(name, "", value, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoolSliceP is like BoolSlice, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func BoolSliceP(name, shorthand string, value []bool, usage string) *[]bool {
|
|
||||||
return CommandLine.BoolSliceP(name, shorthand, value, usage)
|
|
||||||
}
|
|
215
vendor/github.com/spf13/pflag/bool_slice_test.go
generated
vendored
215
vendor/github.com/spf13/pflag/bool_slice_test.go
generated
vendored
|
@ -1,215 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func setUpBSFlagSet(bsp *[]bool) *FlagSet {
|
|
||||||
f := NewFlagSet("test", ContinueOnError)
|
|
||||||
f.BoolSliceVar(bsp, "bs", []bool{}, "Command separated list!")
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func setUpBSFlagSetWithDefault(bsp *[]bool) *FlagSet {
|
|
||||||
f := NewFlagSet("test", ContinueOnError)
|
|
||||||
f.BoolSliceVar(bsp, "bs", []bool{false, true}, "Command separated list!")
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEmptyBS(t *testing.T) {
|
|
||||||
var bs []bool
|
|
||||||
f := setUpBSFlagSet(&bs)
|
|
||||||
err := f.Parse([]string{})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
getBS, err := f.GetBoolSlice("bs")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("got an error from GetBoolSlice():", err)
|
|
||||||
}
|
|
||||||
if len(getBS) != 0 {
|
|
||||||
t.Fatalf("got bs %v with len=%d but expected length=0", getBS, len(getBS))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBS(t *testing.T) {
|
|
||||||
var bs []bool
|
|
||||||
f := setUpBSFlagSet(&bs)
|
|
||||||
|
|
||||||
vals := []string{"1", "F", "TRUE", "0"}
|
|
||||||
arg := fmt.Sprintf("--bs=%s", strings.Join(vals, ","))
|
|
||||||
err := f.Parse([]string{arg})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
for i, v := range bs {
|
|
||||||
b, err := strconv.ParseBool(vals[i])
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("got error: %v", err)
|
|
||||||
}
|
|
||||||
if b != v {
|
|
||||||
t.Fatalf("expected is[%d] to be %s but got: %t", i, vals[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
getBS, err := f.GetBoolSlice("bs")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("got error: %v", err)
|
|
||||||
}
|
|
||||||
for i, v := range getBS {
|
|
||||||
b, err := strconv.ParseBool(vals[i])
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("got error: %v", err)
|
|
||||||
}
|
|
||||||
if b != v {
|
|
||||||
t.Fatalf("expected bs[%d] to be %s but got: %t from GetBoolSlice", i, vals[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBSDefault(t *testing.T) {
|
|
||||||
var bs []bool
|
|
||||||
f := setUpBSFlagSetWithDefault(&bs)
|
|
||||||
|
|
||||||
vals := []string{"false", "T"}
|
|
||||||
|
|
||||||
err := f.Parse([]string{})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
for i, v := range bs {
|
|
||||||
b, err := strconv.ParseBool(vals[i])
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("got error: %v", err)
|
|
||||||
}
|
|
||||||
if b != v {
|
|
||||||
t.Fatalf("expected bs[%d] to be %t from GetBoolSlice but got: %t", i, b, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getBS, err := f.GetBoolSlice("bs")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("got an error from GetBoolSlice():", err)
|
|
||||||
}
|
|
||||||
for i, v := range getBS {
|
|
||||||
b, err := strconv.ParseBool(vals[i])
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("got an error from GetBoolSlice():", err)
|
|
||||||
}
|
|
||||||
if b != v {
|
|
||||||
t.Fatalf("expected bs[%d] to be %t from GetBoolSlice but got: %t", i, b, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBSWithDefault(t *testing.T) {
|
|
||||||
var bs []bool
|
|
||||||
f := setUpBSFlagSetWithDefault(&bs)
|
|
||||||
|
|
||||||
vals := []string{"FALSE", "1"}
|
|
||||||
arg := fmt.Sprintf("--bs=%s", strings.Join(vals, ","))
|
|
||||||
err := f.Parse([]string{arg})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
for i, v := range bs {
|
|
||||||
b, err := strconv.ParseBool(vals[i])
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("got error: %v", err)
|
|
||||||
}
|
|
||||||
if b != v {
|
|
||||||
t.Fatalf("expected bs[%d] to be %t but got: %t", i, b, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getBS, err := f.GetBoolSlice("bs")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("got an error from GetBoolSlice():", err)
|
|
||||||
}
|
|
||||||
for i, v := range getBS {
|
|
||||||
b, err := strconv.ParseBool(vals[i])
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("got error: %v", err)
|
|
||||||
}
|
|
||||||
if b != v {
|
|
||||||
t.Fatalf("expected bs[%d] to be %t from GetBoolSlice but got: %t", i, b, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBSCalledTwice(t *testing.T) {
|
|
||||||
var bs []bool
|
|
||||||
f := setUpBSFlagSet(&bs)
|
|
||||||
|
|
||||||
in := []string{"T,F", "T"}
|
|
||||||
expected := []bool{true, false, true}
|
|
||||||
argfmt := "--bs=%s"
|
|
||||||
arg1 := fmt.Sprintf(argfmt, in[0])
|
|
||||||
arg2 := fmt.Sprintf(argfmt, in[1])
|
|
||||||
err := f.Parse([]string{arg1, arg2})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
for i, v := range bs {
|
|
||||||
if expected[i] != v {
|
|
||||||
t.Fatalf("expected bs[%d] to be %t but got %t", i, expected[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBSBadQuoting(t *testing.T) {
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
Want []bool
|
|
||||||
FlagArg []string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
Want: []bool{true, false, true},
|
|
||||||
FlagArg: []string{"1", "0", "true"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Want: []bool{true, false},
|
|
||||||
FlagArg: []string{"True", "F"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Want: []bool{true, false},
|
|
||||||
FlagArg: []string{"T", "0"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Want: []bool{true, false},
|
|
||||||
FlagArg: []string{"1", "0"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Want: []bool{true, false, false},
|
|
||||||
FlagArg: []string{"true,false", "false"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Want: []bool{true, false, false, true, false, true, false},
|
|
||||||
FlagArg: []string{`"true,false,false,1,0, T"`, " false "},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Want: []bool{false, false, true, false, true, false, true},
|
|
||||||
FlagArg: []string{`"0, False, T,false , true,F"`, "true"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, test := range tests {
|
|
||||||
|
|
||||||
var bs []bool
|
|
||||||
f := setUpBSFlagSet(&bs)
|
|
||||||
|
|
||||||
if err := f.Parse([]string{fmt.Sprintf("--bs=%s", strings.Join(test.FlagArg, ","))}); err != nil {
|
|
||||||
t.Fatalf("flag parsing failed with error: %s\nparsing:\t%#v\nwant:\t\t%#v",
|
|
||||||
err, test.FlagArg, test.Want[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
for j, b := range bs {
|
|
||||||
if b != test.Want[j] {
|
|
||||||
t.Fatalf("bad value parsed for test %d on bool %d:\nwant:\t%t\ngot:\t%t", i, j, test.Want[j], b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
179
vendor/github.com/spf13/pflag/bool_test.go
generated
vendored
179
vendor/github.com/spf13/pflag/bool_test.go
generated
vendored
|
@ -1,179 +0,0 @@
|
||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package pflag
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"strconv"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
// This value can be a boolean ("true", "false") or "maybe"
|
|
||||||
type triStateValue int
|
|
||||||
|
|
||||||
const (
|
|
||||||
triStateFalse triStateValue = 0
|
|
||||||
triStateTrue triStateValue = 1
|
|
||||||
triStateMaybe triStateValue = 2
|
|
||||||
)
|
|
||||||
|
|
||||||
const strTriStateMaybe = "maybe"
|
|
||||||
|
|
||||||
func (v *triStateValue) IsBoolFlag() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *triStateValue) Get() interface{} {
|
|
||||||
return triStateValue(*v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *triStateValue) Set(s string) error {
|
|
||||||
if s == strTriStateMaybe {
|
|
||||||
*v = triStateMaybe
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
boolVal, err := strconv.ParseBool(s)
|
|
||||||
if boolVal {
|
|
||||||
*v = triStateTrue
|
|
||||||
} else {
|
|
||||||
*v = triStateFalse
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *triStateValue) String() string {
|
|
||||||
if *v == triStateMaybe {
|
|
||||||
return strTriStateMaybe
|
|
||||||
}
|
|
||||||
return strconv.FormatBool(*v == triStateTrue)
|
|
||||||
}
|
|
||||||
|
|
||||||
// The type of the flag as required by the pflag.Value interface
|
|
||||||
func (v *triStateValue) Type() string {
|
|
||||||
return "version"
|
|
||||||
}
|
|
||||||
|
|
||||||
func setUpFlagSet(tristate *triStateValue) *FlagSet {
|
|
||||||
f := NewFlagSet("test", ContinueOnError)
|
|
||||||
*tristate = triStateFalse
|
|
||||||
flag := f.VarPF(tristate, "tristate", "t", "tristate value (true, maybe or false)")
|
|
||||||
flag.NoOptDefVal = "true"
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestExplicitTrue(t *testing.T) {
|
|
||||||
var tristate triStateValue
|
|
||||||
f := setUpFlagSet(&tristate)
|
|
||||||
err := f.Parse([]string{"--tristate=true"})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
if tristate != triStateTrue {
|
|
||||||
t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestImplicitTrue(t *testing.T) {
|
|
||||||
var tristate triStateValue
|
|
||||||
f := setUpFlagSet(&tristate)
|
|
||||||
err := f.Parse([]string{"--tristate"})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
if tristate != triStateTrue {
|
|
||||||
t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestShortFlag(t *testing.T) {
|
|
||||||
var tristate triStateValue
|
|
||||||
f := setUpFlagSet(&tristate)
|
|
||||||
err := f.Parse([]string{"-t"})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
if tristate != triStateTrue {
|
|
||||||
t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestShortFlagExtraArgument(t *testing.T) {
|
|
||||||
var tristate triStateValue
|
|
||||||
f := setUpFlagSet(&tristate)
|
|
||||||
// The"maybe"turns into an arg, since short boolean options will only do true/false
|
|
||||||
err := f.Parse([]string{"-t", "maybe"})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
if tristate != triStateTrue {
|
|
||||||
t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead")
|
|
||||||
}
|
|
||||||
args := f.Args()
|
|
||||||
if len(args) != 1 || args[0] != "maybe" {
|
|
||||||
t.Fatal("expected an extra 'maybe' argument to stick around")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestExplicitMaybe(t *testing.T) {
|
|
||||||
var tristate triStateValue
|
|
||||||
f := setUpFlagSet(&tristate)
|
|
||||||
err := f.Parse([]string{"--tristate=maybe"})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
if tristate != triStateMaybe {
|
|
||||||
t.Fatal("expected", triStateMaybe, "(triStateMaybe) but got", tristate, "instead")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestExplicitFalse(t *testing.T) {
|
|
||||||
var tristate triStateValue
|
|
||||||
f := setUpFlagSet(&tristate)
|
|
||||||
err := f.Parse([]string{"--tristate=false"})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
if tristate != triStateFalse {
|
|
||||||
t.Fatal("expected", triStateFalse, "(triStateFalse) but got", tristate, "instead")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestImplicitFalse(t *testing.T) {
|
|
||||||
var tristate triStateValue
|
|
||||||
f := setUpFlagSet(&tristate)
|
|
||||||
err := f.Parse([]string{})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
if tristate != triStateFalse {
|
|
||||||
t.Fatal("expected", triStateFalse, "(triStateFalse) but got", tristate, "instead")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInvalidValue(t *testing.T) {
|
|
||||||
var tristate triStateValue
|
|
||||||
f := setUpFlagSet(&tristate)
|
|
||||||
var buf bytes.Buffer
|
|
||||||
f.SetOutput(&buf)
|
|
||||||
err := f.Parse([]string{"--tristate=invalid"})
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("expected an error but did not get any, tristate has value", tristate)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBoolP(t *testing.T) {
|
|
||||||
b := BoolP("bool", "b", false, "bool value in CommandLine")
|
|
||||||
c := BoolP("c", "c", false, "other bool value")
|
|
||||||
args := []string{"--bool"}
|
|
||||||
if err := CommandLine.Parse(args); err != nil {
|
|
||||||
t.Error("expected no error, got ", err)
|
|
||||||
}
|
|
||||||
if *b != true {
|
|
||||||
t.Errorf("expected b=true got b=%v", *b)
|
|
||||||
}
|
|
||||||
if *c != false {
|
|
||||||
t.Errorf("expect c=false got c=%v", *c)
|
|
||||||
}
|
|
||||||
}
|
|
96
vendor/github.com/spf13/pflag/count.go
generated
vendored
96
vendor/github.com/spf13/pflag/count.go
generated
vendored
|
@ -1,96 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import "strconv"
|
|
||||||
|
|
||||||
// -- count Value
|
|
||||||
type countValue int
|
|
||||||
|
|
||||||
func newCountValue(val int, p *int) *countValue {
|
|
||||||
*p = val
|
|
||||||
return (*countValue)(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *countValue) Set(s string) error {
|
|
||||||
v, err := strconv.ParseInt(s, 0, 64)
|
|
||||||
// -1 means that no specific value was passed, so increment
|
|
||||||
if v == -1 {
|
|
||||||
*i = countValue(*i + 1)
|
|
||||||
} else {
|
|
||||||
*i = countValue(v)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *countValue) Type() string {
|
|
||||||
return "count"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *countValue) String() string { return strconv.Itoa(int(*i)) }
|
|
||||||
|
|
||||||
func countConv(sval string) (interface{}, error) {
|
|
||||||
i, err := strconv.Atoi(sval)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return i, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetCount return the int value of a flag with the given name
|
|
||||||
func (f *FlagSet) GetCount(name string) (int, error) {
|
|
||||||
val, err := f.getFlagType(name, "count", countConv)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return val.(int), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CountVar defines a count flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to an int variable in which to store the value of the flag.
|
|
||||||
// A count flag will add 1 to its value evey time it is found on the command line
|
|
||||||
func (f *FlagSet) CountVar(p *int, name string, usage string) {
|
|
||||||
f.CountVarP(p, name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CountVarP is like CountVar only take a shorthand for the flag name.
|
|
||||||
func (f *FlagSet) CountVarP(p *int, name, shorthand string, usage string) {
|
|
||||||
flag := f.VarPF(newCountValue(0, p), name, shorthand, usage)
|
|
||||||
flag.NoOptDefVal = "-1"
|
|
||||||
}
|
|
||||||
|
|
||||||
// CountVar like CountVar only the flag is placed on the CommandLine instead of a given flag set
|
|
||||||
func CountVar(p *int, name string, usage string) {
|
|
||||||
CommandLine.CountVar(p, name, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CountVarP is like CountVar only take a shorthand for the flag name.
|
|
||||||
func CountVarP(p *int, name, shorthand string, usage string) {
|
|
||||||
CommandLine.CountVarP(p, name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Count defines a count flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of an int variable that stores the value of the flag.
|
|
||||||
// A count flag will add 1 to its value evey time it is found on the command line
|
|
||||||
func (f *FlagSet) Count(name string, usage string) *int {
|
|
||||||
p := new(int)
|
|
||||||
f.CountVarP(p, name, "", usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// CountP is like Count only takes a shorthand for the flag name.
|
|
||||||
func (f *FlagSet) CountP(name, shorthand string, usage string) *int {
|
|
||||||
p := new(int)
|
|
||||||
f.CountVarP(p, name, shorthand, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Count defines a count flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of an int variable that stores the value of the flag.
|
|
||||||
// A count flag will add 1 to its value evey time it is found on the command line
|
|
||||||
func Count(name string, usage string) *int {
|
|
||||||
return CommandLine.CountP(name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CountP is like Count only takes a shorthand for the flag name.
|
|
||||||
func CountP(name, shorthand string, usage string) *int {
|
|
||||||
return CommandLine.CountP(name, shorthand, usage)
|
|
||||||
}
|
|
52
vendor/github.com/spf13/pflag/count_test.go
generated
vendored
52
vendor/github.com/spf13/pflag/count_test.go
generated
vendored
|
@ -1,52 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func setUpCount(c *int) *FlagSet {
|
|
||||||
f := NewFlagSet("test", ContinueOnError)
|
|
||||||
f.CountVarP(c, "verbose", "v", "a counter")
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCount(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
input []string
|
|
||||||
success bool
|
|
||||||
expected int
|
|
||||||
}{
|
|
||||||
{[]string{"-vvv"}, true, 3},
|
|
||||||
{[]string{"-v", "-v", "-v"}, true, 3},
|
|
||||||
{[]string{"-v", "--verbose", "-v"}, true, 3},
|
|
||||||
{[]string{"-v=3", "-v"}, true, 4},
|
|
||||||
{[]string{"-v=a"}, false, 0},
|
|
||||||
}
|
|
||||||
|
|
||||||
devnull, _ := os.Open(os.DevNull)
|
|
||||||
os.Stderr = devnull
|
|
||||||
for i := range testCases {
|
|
||||||
var count int
|
|
||||||
f := setUpCount(&count)
|
|
||||||
|
|
||||||
tc := &testCases[i]
|
|
||||||
|
|
||||||
err := f.Parse(tc.input)
|
|
||||||
if err != nil && tc.success == true {
|
|
||||||
t.Errorf("expected success, got %q", err)
|
|
||||||
continue
|
|
||||||
} else if err == nil && tc.success == false {
|
|
||||||
t.Errorf("expected failure, got success")
|
|
||||||
continue
|
|
||||||
} else if tc.success {
|
|
||||||
c, err := f.GetCount("verbose")
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Got error trying to fetch the counter flag")
|
|
||||||
}
|
|
||||||
if c != tc.expected {
|
|
||||||
t.Errorf("expected %q, got %q", tc.expected, c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
86
vendor/github.com/spf13/pflag/duration.go
generated
vendored
86
vendor/github.com/spf13/pflag/duration.go
generated
vendored
|
@ -1,86 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// -- time.Duration Value
|
|
||||||
type durationValue time.Duration
|
|
||||||
|
|
||||||
func newDurationValue(val time.Duration, p *time.Duration) *durationValue {
|
|
||||||
*p = val
|
|
||||||
return (*durationValue)(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *durationValue) Set(s string) error {
|
|
||||||
v, err := time.ParseDuration(s)
|
|
||||||
*d = durationValue(v)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *durationValue) Type() string {
|
|
||||||
return "duration"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *durationValue) String() string { return (*time.Duration)(d).String() }
|
|
||||||
|
|
||||||
func durationConv(sval string) (interface{}, error) {
|
|
||||||
return time.ParseDuration(sval)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetDuration return the duration value of a flag with the given name
|
|
||||||
func (f *FlagSet) GetDuration(name string) (time.Duration, error) {
|
|
||||||
val, err := f.getFlagType(name, "duration", durationConv)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return val.(time.Duration), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DurationVar defines a time.Duration flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a time.Duration variable in which to store the value of the flag.
|
|
||||||
func (f *FlagSet) DurationVar(p *time.Duration, name string, value time.Duration, usage string) {
|
|
||||||
f.VarP(newDurationValue(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DurationVarP is like DurationVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) DurationVarP(p *time.Duration, name, shorthand string, value time.Duration, usage string) {
|
|
||||||
f.VarP(newDurationValue(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DurationVar defines a time.Duration flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a time.Duration variable in which to store the value of the flag.
|
|
||||||
func DurationVar(p *time.Duration, name string, value time.Duration, usage string) {
|
|
||||||
CommandLine.VarP(newDurationValue(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DurationVarP is like DurationVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func DurationVarP(p *time.Duration, name, shorthand string, value time.Duration, usage string) {
|
|
||||||
CommandLine.VarP(newDurationValue(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Duration defines a time.Duration flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a time.Duration variable that stores the value of the flag.
|
|
||||||
func (f *FlagSet) Duration(name string, value time.Duration, usage string) *time.Duration {
|
|
||||||
p := new(time.Duration)
|
|
||||||
f.DurationVarP(p, name, "", value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// DurationP is like Duration, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) DurationP(name, shorthand string, value time.Duration, usage string) *time.Duration {
|
|
||||||
p := new(time.Duration)
|
|
||||||
f.DurationVarP(p, name, shorthand, value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Duration defines a time.Duration flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a time.Duration variable that stores the value of the flag.
|
|
||||||
func Duration(name string, value time.Duration, usage string) *time.Duration {
|
|
||||||
return CommandLine.DurationP(name, "", value, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DurationP is like Duration, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func DurationP(name, shorthand string, value time.Duration, usage string) *time.Duration {
|
|
||||||
return CommandLine.DurationP(name, shorthand, value, usage)
|
|
||||||
}
|
|
36
vendor/github.com/spf13/pflag/example_test.go
generated
vendored
36
vendor/github.com/spf13/pflag/example_test.go
generated
vendored
|
@ -1,36 +0,0 @@
|
||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package pflag_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/spf13/pflag"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ExampleShorthandLookup() {
|
|
||||||
name := "verbose"
|
|
||||||
short := name[:1]
|
|
||||||
|
|
||||||
pflag.BoolP(name, short, false, "verbose output")
|
|
||||||
|
|
||||||
// len(short) must be == 1
|
|
||||||
flag := pflag.ShorthandLookup(short)
|
|
||||||
|
|
||||||
fmt.Println(flag.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleFlagSet_ShorthandLookup() {
|
|
||||||
name := "verbose"
|
|
||||||
short := name[:1]
|
|
||||||
|
|
||||||
fs := pflag.NewFlagSet("Example", pflag.ContinueOnError)
|
|
||||||
fs.BoolP(name, short, false, "verbose output")
|
|
||||||
|
|
||||||
// len(short) must be == 1
|
|
||||||
flag := fs.ShorthandLookup(short)
|
|
||||||
|
|
||||||
fmt.Println(flag.Name)
|
|
||||||
}
|
|
29
vendor/github.com/spf13/pflag/export_test.go
generated
vendored
29
vendor/github.com/spf13/pflag/export_test.go
generated
vendored
|
@ -1,29 +0,0 @@
|
||||||
// Copyright 2010 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package pflag
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Additional routines compiled into the package only during testing.
|
|
||||||
|
|
||||||
// ResetForTesting clears all flag state and sets the usage function as directed.
|
|
||||||
// After calling ResetForTesting, parse errors in flag handling will not
|
|
||||||
// exit the program.
|
|
||||||
func ResetForTesting(usage func()) {
|
|
||||||
CommandLine = &FlagSet{
|
|
||||||
name: os.Args[0],
|
|
||||||
errorHandling: ContinueOnError,
|
|
||||||
output: ioutil.Discard,
|
|
||||||
}
|
|
||||||
Usage = usage
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetCommandLine returns the default FlagSet.
|
|
||||||
func GetCommandLine() *FlagSet {
|
|
||||||
return CommandLine
|
|
||||||
}
|
|
1128
vendor/github.com/spf13/pflag/flag.go
generated
vendored
1128
vendor/github.com/spf13/pflag/flag.go
generated
vendored
File diff suppressed because it is too large
Load diff
1085
vendor/github.com/spf13/pflag/flag_test.go
generated
vendored
1085
vendor/github.com/spf13/pflag/flag_test.go
generated
vendored
File diff suppressed because it is too large
Load diff
88
vendor/github.com/spf13/pflag/float32.go
generated
vendored
88
vendor/github.com/spf13/pflag/float32.go
generated
vendored
|
@ -1,88 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import "strconv"
|
|
||||||
|
|
||||||
// -- float32 Value
|
|
||||||
type float32Value float32
|
|
||||||
|
|
||||||
func newFloat32Value(val float32, p *float32) *float32Value {
|
|
||||||
*p = val
|
|
||||||
return (*float32Value)(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *float32Value) Set(s string) error {
|
|
||||||
v, err := strconv.ParseFloat(s, 32)
|
|
||||||
*f = float32Value(v)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *float32Value) Type() string {
|
|
||||||
return "float32"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *float32Value) String() string { return strconv.FormatFloat(float64(*f), 'g', -1, 32) }
|
|
||||||
|
|
||||||
func float32Conv(sval string) (interface{}, error) {
|
|
||||||
v, err := strconv.ParseFloat(sval, 32)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return float32(v), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetFloat32 return the float32 value of a flag with the given name
|
|
||||||
func (f *FlagSet) GetFloat32(name string) (float32, error) {
|
|
||||||
val, err := f.getFlagType(name, "float32", float32Conv)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return val.(float32), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float32Var defines a float32 flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a float32 variable in which to store the value of the flag.
|
|
||||||
func (f *FlagSet) Float32Var(p *float32, name string, value float32, usage string) {
|
|
||||||
f.VarP(newFloat32Value(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float32VarP is like Float32Var, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) Float32VarP(p *float32, name, shorthand string, value float32, usage string) {
|
|
||||||
f.VarP(newFloat32Value(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float32Var defines a float32 flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a float32 variable in which to store the value of the flag.
|
|
||||||
func Float32Var(p *float32, name string, value float32, usage string) {
|
|
||||||
CommandLine.VarP(newFloat32Value(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float32VarP is like Float32Var, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func Float32VarP(p *float32, name, shorthand string, value float32, usage string) {
|
|
||||||
CommandLine.VarP(newFloat32Value(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float32 defines a float32 flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a float32 variable that stores the value of the flag.
|
|
||||||
func (f *FlagSet) Float32(name string, value float32, usage string) *float32 {
|
|
||||||
p := new(float32)
|
|
||||||
f.Float32VarP(p, name, "", value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float32P is like Float32, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) Float32P(name, shorthand string, value float32, usage string) *float32 {
|
|
||||||
p := new(float32)
|
|
||||||
f.Float32VarP(p, name, shorthand, value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float32 defines a float32 flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a float32 variable that stores the value of the flag.
|
|
||||||
func Float32(name string, value float32, usage string) *float32 {
|
|
||||||
return CommandLine.Float32P(name, "", value, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float32P is like Float32, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func Float32P(name, shorthand string, value float32, usage string) *float32 {
|
|
||||||
return CommandLine.Float32P(name, shorthand, value, usage)
|
|
||||||
}
|
|
84
vendor/github.com/spf13/pflag/float64.go
generated
vendored
84
vendor/github.com/spf13/pflag/float64.go
generated
vendored
|
@ -1,84 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import "strconv"
|
|
||||||
|
|
||||||
// -- float64 Value
|
|
||||||
type float64Value float64
|
|
||||||
|
|
||||||
func newFloat64Value(val float64, p *float64) *float64Value {
|
|
||||||
*p = val
|
|
||||||
return (*float64Value)(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *float64Value) Set(s string) error {
|
|
||||||
v, err := strconv.ParseFloat(s, 64)
|
|
||||||
*f = float64Value(v)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *float64Value) Type() string {
|
|
||||||
return "float64"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *float64Value) String() string { return strconv.FormatFloat(float64(*f), 'g', -1, 64) }
|
|
||||||
|
|
||||||
func float64Conv(sval string) (interface{}, error) {
|
|
||||||
return strconv.ParseFloat(sval, 64)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetFloat64 return the float64 value of a flag with the given name
|
|
||||||
func (f *FlagSet) GetFloat64(name string) (float64, error) {
|
|
||||||
val, err := f.getFlagType(name, "float64", float64Conv)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return val.(float64), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float64Var defines a float64 flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a float64 variable in which to store the value of the flag.
|
|
||||||
func (f *FlagSet) Float64Var(p *float64, name string, value float64, usage string) {
|
|
||||||
f.VarP(newFloat64Value(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float64VarP is like Float64Var, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) Float64VarP(p *float64, name, shorthand string, value float64, usage string) {
|
|
||||||
f.VarP(newFloat64Value(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float64Var defines a float64 flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a float64 variable in which to store the value of the flag.
|
|
||||||
func Float64Var(p *float64, name string, value float64, usage string) {
|
|
||||||
CommandLine.VarP(newFloat64Value(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float64VarP is like Float64Var, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func Float64VarP(p *float64, name, shorthand string, value float64, usage string) {
|
|
||||||
CommandLine.VarP(newFloat64Value(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float64 defines a float64 flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a float64 variable that stores the value of the flag.
|
|
||||||
func (f *FlagSet) Float64(name string, value float64, usage string) *float64 {
|
|
||||||
p := new(float64)
|
|
||||||
f.Float64VarP(p, name, "", value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float64P is like Float64, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) Float64P(name, shorthand string, value float64, usage string) *float64 {
|
|
||||||
p := new(float64)
|
|
||||||
f.Float64VarP(p, name, shorthand, value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float64 defines a float64 flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a float64 variable that stores the value of the flag.
|
|
||||||
func Float64(name string, value float64, usage string) *float64 {
|
|
||||||
return CommandLine.Float64P(name, "", value, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float64P is like Float64, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func Float64P(name, shorthand string, value float64, usage string) *float64 {
|
|
||||||
return CommandLine.Float64P(name, shorthand, value, usage)
|
|
||||||
}
|
|
101
vendor/github.com/spf13/pflag/golangflag.go
generated
vendored
101
vendor/github.com/spf13/pflag/golangflag.go
generated
vendored
|
@ -1,101 +0,0 @@
|
||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package pflag
|
|
||||||
|
|
||||||
import (
|
|
||||||
goflag "flag"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// flagValueWrapper implements pflag.Value around a flag.Value. The main
|
|
||||||
// difference here is the addition of the Type method that returns a string
|
|
||||||
// name of the type. As this is generally unknown, we approximate that with
|
|
||||||
// reflection.
|
|
||||||
type flagValueWrapper struct {
|
|
||||||
inner goflag.Value
|
|
||||||
flagType string
|
|
||||||
}
|
|
||||||
|
|
||||||
// We are just copying the boolFlag interface out of goflag as that is what
|
|
||||||
// they use to decide if a flag should get "true" when no arg is given.
|
|
||||||
type goBoolFlag interface {
|
|
||||||
goflag.Value
|
|
||||||
IsBoolFlag() bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func wrapFlagValue(v goflag.Value) Value {
|
|
||||||
// If the flag.Value happens to also be a pflag.Value, just use it directly.
|
|
||||||
if pv, ok := v.(Value); ok {
|
|
||||||
return pv
|
|
||||||
}
|
|
||||||
|
|
||||||
pv := &flagValueWrapper{
|
|
||||||
inner: v,
|
|
||||||
}
|
|
||||||
|
|
||||||
t := reflect.TypeOf(v)
|
|
||||||
if t.Kind() == reflect.Interface || t.Kind() == reflect.Ptr {
|
|
||||||
t = t.Elem()
|
|
||||||
}
|
|
||||||
|
|
||||||
pv.flagType = strings.TrimSuffix(t.Name(), "Value")
|
|
||||||
return pv
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *flagValueWrapper) String() string {
|
|
||||||
return v.inner.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *flagValueWrapper) Set(s string) error {
|
|
||||||
return v.inner.Set(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *flagValueWrapper) Type() string {
|
|
||||||
return v.flagType
|
|
||||||
}
|
|
||||||
|
|
||||||
// PFlagFromGoFlag will return a *pflag.Flag given a *flag.Flag
|
|
||||||
// If the *flag.Flag.Name was a single character (ex: `v`) it will be accessiblei
|
|
||||||
// with both `-v` and `--v` in flags. If the golang flag was more than a single
|
|
||||||
// character (ex: `verbose`) it will only be accessible via `--verbose`
|
|
||||||
func PFlagFromGoFlag(goflag *goflag.Flag) *Flag {
|
|
||||||
// Remember the default value as a string; it won't change.
|
|
||||||
flag := &Flag{
|
|
||||||
Name: goflag.Name,
|
|
||||||
Usage: goflag.Usage,
|
|
||||||
Value: wrapFlagValue(goflag.Value),
|
|
||||||
// Looks like golang flags don't set DefValue correctly :-(
|
|
||||||
//DefValue: goflag.DefValue,
|
|
||||||
DefValue: goflag.Value.String(),
|
|
||||||
}
|
|
||||||
// Ex: if the golang flag was -v, allow both -v and --v to work
|
|
||||||
if len(flag.Name) == 1 {
|
|
||||||
flag.Shorthand = flag.Name
|
|
||||||
}
|
|
||||||
if fv, ok := goflag.Value.(goBoolFlag); ok && fv.IsBoolFlag() {
|
|
||||||
flag.NoOptDefVal = "true"
|
|
||||||
}
|
|
||||||
return flag
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddGoFlag will add the given *flag.Flag to the pflag.FlagSet
|
|
||||||
func (f *FlagSet) AddGoFlag(goflag *goflag.Flag) {
|
|
||||||
if f.Lookup(goflag.Name) != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
newflag := PFlagFromGoFlag(goflag)
|
|
||||||
f.AddFlag(newflag)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddGoFlagSet will add the given *flag.FlagSet to the pflag.FlagSet
|
|
||||||
func (f *FlagSet) AddGoFlagSet(newSet *goflag.FlagSet) {
|
|
||||||
if newSet == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
newSet.VisitAll(func(goflag *goflag.Flag) {
|
|
||||||
f.AddGoFlag(goflag)
|
|
||||||
})
|
|
||||||
}
|
|
39
vendor/github.com/spf13/pflag/golangflag_test.go
generated
vendored
39
vendor/github.com/spf13/pflag/golangflag_test.go
generated
vendored
|
@ -1,39 +0,0 @@
|
||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package pflag
|
|
||||||
|
|
||||||
import (
|
|
||||||
goflag "flag"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGoflags(t *testing.T) {
|
|
||||||
goflag.String("stringFlag", "stringFlag", "stringFlag")
|
|
||||||
goflag.Bool("boolFlag", false, "boolFlag")
|
|
||||||
|
|
||||||
f := NewFlagSet("test", ContinueOnError)
|
|
||||||
|
|
||||||
f.AddGoFlagSet(goflag.CommandLine)
|
|
||||||
err := f.Parse([]string{"--stringFlag=bob", "--boolFlag"})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; get", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
getString, err := f.GetString("stringFlag")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; get", err)
|
|
||||||
}
|
|
||||||
if getString != "bob" {
|
|
||||||
t.Fatalf("expected getString=bob but got getString=%s", getString)
|
|
||||||
}
|
|
||||||
|
|
||||||
getBool, err := f.GetBool("boolFlag")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; get", err)
|
|
||||||
}
|
|
||||||
if getBool != true {
|
|
||||||
t.Fatalf("expected getBool=true but got getBool=%v", getBool)
|
|
||||||
}
|
|
||||||
}
|
|
84
vendor/github.com/spf13/pflag/int.go
generated
vendored
84
vendor/github.com/spf13/pflag/int.go
generated
vendored
|
@ -1,84 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import "strconv"
|
|
||||||
|
|
||||||
// -- int Value
|
|
||||||
type intValue int
|
|
||||||
|
|
||||||
func newIntValue(val int, p *int) *intValue {
|
|
||||||
*p = val
|
|
||||||
return (*intValue)(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *intValue) Set(s string) error {
|
|
||||||
v, err := strconv.ParseInt(s, 0, 64)
|
|
||||||
*i = intValue(v)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *intValue) Type() string {
|
|
||||||
return "int"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *intValue) String() string { return strconv.Itoa(int(*i)) }
|
|
||||||
|
|
||||||
func intConv(sval string) (interface{}, error) {
|
|
||||||
return strconv.Atoi(sval)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetInt return the int value of a flag with the given name
|
|
||||||
func (f *FlagSet) GetInt(name string) (int, error) {
|
|
||||||
val, err := f.getFlagType(name, "int", intConv)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return val.(int), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IntVar defines an int flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to an int variable in which to store the value of the flag.
|
|
||||||
func (f *FlagSet) IntVar(p *int, name string, value int, usage string) {
|
|
||||||
f.VarP(newIntValue(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IntVarP is like IntVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) IntVarP(p *int, name, shorthand string, value int, usage string) {
|
|
||||||
f.VarP(newIntValue(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IntVar defines an int flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to an int variable in which to store the value of the flag.
|
|
||||||
func IntVar(p *int, name string, value int, usage string) {
|
|
||||||
CommandLine.VarP(newIntValue(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IntVarP is like IntVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func IntVarP(p *int, name, shorthand string, value int, usage string) {
|
|
||||||
CommandLine.VarP(newIntValue(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int defines an int flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of an int variable that stores the value of the flag.
|
|
||||||
func (f *FlagSet) Int(name string, value int, usage string) *int {
|
|
||||||
p := new(int)
|
|
||||||
f.IntVarP(p, name, "", value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// IntP is like Int, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) IntP(name, shorthand string, value int, usage string) *int {
|
|
||||||
p := new(int)
|
|
||||||
f.IntVarP(p, name, shorthand, value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int defines an int flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of an int variable that stores the value of the flag.
|
|
||||||
func Int(name string, value int, usage string) *int {
|
|
||||||
return CommandLine.IntP(name, "", value, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IntP is like Int, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func IntP(name, shorthand string, value int, usage string) *int {
|
|
||||||
return CommandLine.IntP(name, shorthand, value, usage)
|
|
||||||
}
|
|
88
vendor/github.com/spf13/pflag/int32.go
generated
vendored
88
vendor/github.com/spf13/pflag/int32.go
generated
vendored
|
@ -1,88 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import "strconv"
|
|
||||||
|
|
||||||
// -- int32 Value
|
|
||||||
type int32Value int32
|
|
||||||
|
|
||||||
func newInt32Value(val int32, p *int32) *int32Value {
|
|
||||||
*p = val
|
|
||||||
return (*int32Value)(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *int32Value) Set(s string) error {
|
|
||||||
v, err := strconv.ParseInt(s, 0, 32)
|
|
||||||
*i = int32Value(v)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *int32Value) Type() string {
|
|
||||||
return "int32"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *int32Value) String() string { return strconv.FormatInt(int64(*i), 10) }
|
|
||||||
|
|
||||||
func int32Conv(sval string) (interface{}, error) {
|
|
||||||
v, err := strconv.ParseInt(sval, 0, 32)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return int32(v), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetInt32 return the int32 value of a flag with the given name
|
|
||||||
func (f *FlagSet) GetInt32(name string) (int32, error) {
|
|
||||||
val, err := f.getFlagType(name, "int32", int32Conv)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return val.(int32), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int32Var defines an int32 flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to an int32 variable in which to store the value of the flag.
|
|
||||||
func (f *FlagSet) Int32Var(p *int32, name string, value int32, usage string) {
|
|
||||||
f.VarP(newInt32Value(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int32VarP is like Int32Var, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) Int32VarP(p *int32, name, shorthand string, value int32, usage string) {
|
|
||||||
f.VarP(newInt32Value(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int32Var defines an int32 flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to an int32 variable in which to store the value of the flag.
|
|
||||||
func Int32Var(p *int32, name string, value int32, usage string) {
|
|
||||||
CommandLine.VarP(newInt32Value(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int32VarP is like Int32Var, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func Int32VarP(p *int32, name, shorthand string, value int32, usage string) {
|
|
||||||
CommandLine.VarP(newInt32Value(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int32 defines an int32 flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of an int32 variable that stores the value of the flag.
|
|
||||||
func (f *FlagSet) Int32(name string, value int32, usage string) *int32 {
|
|
||||||
p := new(int32)
|
|
||||||
f.Int32VarP(p, name, "", value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int32P is like Int32, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) Int32P(name, shorthand string, value int32, usage string) *int32 {
|
|
||||||
p := new(int32)
|
|
||||||
f.Int32VarP(p, name, shorthand, value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int32 defines an int32 flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of an int32 variable that stores the value of the flag.
|
|
||||||
func Int32(name string, value int32, usage string) *int32 {
|
|
||||||
return CommandLine.Int32P(name, "", value, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int32P is like Int32, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func Int32P(name, shorthand string, value int32, usage string) *int32 {
|
|
||||||
return CommandLine.Int32P(name, shorthand, value, usage)
|
|
||||||
}
|
|
84
vendor/github.com/spf13/pflag/int64.go
generated
vendored
84
vendor/github.com/spf13/pflag/int64.go
generated
vendored
|
@ -1,84 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import "strconv"
|
|
||||||
|
|
||||||
// -- int64 Value
|
|
||||||
type int64Value int64
|
|
||||||
|
|
||||||
func newInt64Value(val int64, p *int64) *int64Value {
|
|
||||||
*p = val
|
|
||||||
return (*int64Value)(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *int64Value) Set(s string) error {
|
|
||||||
v, err := strconv.ParseInt(s, 0, 64)
|
|
||||||
*i = int64Value(v)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *int64Value) Type() string {
|
|
||||||
return "int64"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *int64Value) String() string { return strconv.FormatInt(int64(*i), 10) }
|
|
||||||
|
|
||||||
func int64Conv(sval string) (interface{}, error) {
|
|
||||||
return strconv.ParseInt(sval, 0, 64)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetInt64 return the int64 value of a flag with the given name
|
|
||||||
func (f *FlagSet) GetInt64(name string) (int64, error) {
|
|
||||||
val, err := f.getFlagType(name, "int64", int64Conv)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return val.(int64), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int64Var defines an int64 flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to an int64 variable in which to store the value of the flag.
|
|
||||||
func (f *FlagSet) Int64Var(p *int64, name string, value int64, usage string) {
|
|
||||||
f.VarP(newInt64Value(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int64VarP is like Int64Var, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) Int64VarP(p *int64, name, shorthand string, value int64, usage string) {
|
|
||||||
f.VarP(newInt64Value(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int64Var defines an int64 flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to an int64 variable in which to store the value of the flag.
|
|
||||||
func Int64Var(p *int64, name string, value int64, usage string) {
|
|
||||||
CommandLine.VarP(newInt64Value(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int64VarP is like Int64Var, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func Int64VarP(p *int64, name, shorthand string, value int64, usage string) {
|
|
||||||
CommandLine.VarP(newInt64Value(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int64 defines an int64 flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of an int64 variable that stores the value of the flag.
|
|
||||||
func (f *FlagSet) Int64(name string, value int64, usage string) *int64 {
|
|
||||||
p := new(int64)
|
|
||||||
f.Int64VarP(p, name, "", value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int64P is like Int64, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) Int64P(name, shorthand string, value int64, usage string) *int64 {
|
|
||||||
p := new(int64)
|
|
||||||
f.Int64VarP(p, name, shorthand, value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int64 defines an int64 flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of an int64 variable that stores the value of the flag.
|
|
||||||
func Int64(name string, value int64, usage string) *int64 {
|
|
||||||
return CommandLine.Int64P(name, "", value, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int64P is like Int64, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func Int64P(name, shorthand string, value int64, usage string) *int64 {
|
|
||||||
return CommandLine.Int64P(name, shorthand, value, usage)
|
|
||||||
}
|
|
88
vendor/github.com/spf13/pflag/int8.go
generated
vendored
88
vendor/github.com/spf13/pflag/int8.go
generated
vendored
|
@ -1,88 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import "strconv"
|
|
||||||
|
|
||||||
// -- int8 Value
|
|
||||||
type int8Value int8
|
|
||||||
|
|
||||||
func newInt8Value(val int8, p *int8) *int8Value {
|
|
||||||
*p = val
|
|
||||||
return (*int8Value)(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *int8Value) Set(s string) error {
|
|
||||||
v, err := strconv.ParseInt(s, 0, 8)
|
|
||||||
*i = int8Value(v)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *int8Value) Type() string {
|
|
||||||
return "int8"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *int8Value) String() string { return strconv.FormatInt(int64(*i), 10) }
|
|
||||||
|
|
||||||
func int8Conv(sval string) (interface{}, error) {
|
|
||||||
v, err := strconv.ParseInt(sval, 0, 8)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return int8(v), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetInt8 return the int8 value of a flag with the given name
|
|
||||||
func (f *FlagSet) GetInt8(name string) (int8, error) {
|
|
||||||
val, err := f.getFlagType(name, "int8", int8Conv)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return val.(int8), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int8Var defines an int8 flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to an int8 variable in which to store the value of the flag.
|
|
||||||
func (f *FlagSet) Int8Var(p *int8, name string, value int8, usage string) {
|
|
||||||
f.VarP(newInt8Value(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int8VarP is like Int8Var, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) Int8VarP(p *int8, name, shorthand string, value int8, usage string) {
|
|
||||||
f.VarP(newInt8Value(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int8Var defines an int8 flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to an int8 variable in which to store the value of the flag.
|
|
||||||
func Int8Var(p *int8, name string, value int8, usage string) {
|
|
||||||
CommandLine.VarP(newInt8Value(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int8VarP is like Int8Var, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func Int8VarP(p *int8, name, shorthand string, value int8, usage string) {
|
|
||||||
CommandLine.VarP(newInt8Value(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int8 defines an int8 flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of an int8 variable that stores the value of the flag.
|
|
||||||
func (f *FlagSet) Int8(name string, value int8, usage string) *int8 {
|
|
||||||
p := new(int8)
|
|
||||||
f.Int8VarP(p, name, "", value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int8P is like Int8, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) Int8P(name, shorthand string, value int8, usage string) *int8 {
|
|
||||||
p := new(int8)
|
|
||||||
f.Int8VarP(p, name, shorthand, value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int8 defines an int8 flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of an int8 variable that stores the value of the flag.
|
|
||||||
func Int8(name string, value int8, usage string) *int8 {
|
|
||||||
return CommandLine.Int8P(name, "", value, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int8P is like Int8, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func Int8P(name, shorthand string, value int8, usage string) *int8 {
|
|
||||||
return CommandLine.Int8P(name, shorthand, value, usage)
|
|
||||||
}
|
|
128
vendor/github.com/spf13/pflag/int_slice.go
generated
vendored
128
vendor/github.com/spf13/pflag/int_slice.go
generated
vendored
|
@ -1,128 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// -- intSlice Value
|
|
||||||
type intSliceValue struct {
|
|
||||||
value *[]int
|
|
||||||
changed bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func newIntSliceValue(val []int, p *[]int) *intSliceValue {
|
|
||||||
isv := new(intSliceValue)
|
|
||||||
isv.value = p
|
|
||||||
*isv.value = val
|
|
||||||
return isv
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *intSliceValue) Set(val string) error {
|
|
||||||
ss := strings.Split(val, ",")
|
|
||||||
out := make([]int, len(ss))
|
|
||||||
for i, d := range ss {
|
|
||||||
var err error
|
|
||||||
out[i], err = strconv.Atoi(d)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if !s.changed {
|
|
||||||
*s.value = out
|
|
||||||
} else {
|
|
||||||
*s.value = append(*s.value, out...)
|
|
||||||
}
|
|
||||||
s.changed = true
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *intSliceValue) Type() string {
|
|
||||||
return "intSlice"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *intSliceValue) String() string {
|
|
||||||
out := make([]string, len(*s.value))
|
|
||||||
for i, d := range *s.value {
|
|
||||||
out[i] = fmt.Sprintf("%d", d)
|
|
||||||
}
|
|
||||||
return "[" + strings.Join(out, ",") + "]"
|
|
||||||
}
|
|
||||||
|
|
||||||
func intSliceConv(val string) (interface{}, error) {
|
|
||||||
val = strings.Trim(val, "[]")
|
|
||||||
// Empty string would cause a slice with one (empty) entry
|
|
||||||
if len(val) == 0 {
|
|
||||||
return []int{}, nil
|
|
||||||
}
|
|
||||||
ss := strings.Split(val, ",")
|
|
||||||
out := make([]int, len(ss))
|
|
||||||
for i, d := range ss {
|
|
||||||
var err error
|
|
||||||
out[i], err = strconv.Atoi(d)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetIntSlice return the []int value of a flag with the given name
|
|
||||||
func (f *FlagSet) GetIntSlice(name string) ([]int, error) {
|
|
||||||
val, err := f.getFlagType(name, "intSlice", intSliceConv)
|
|
||||||
if err != nil {
|
|
||||||
return []int{}, err
|
|
||||||
}
|
|
||||||
return val.([]int), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IntSliceVar defines a intSlice flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a []int variable in which to store the value of the flag.
|
|
||||||
func (f *FlagSet) IntSliceVar(p *[]int, name string, value []int, usage string) {
|
|
||||||
f.VarP(newIntSliceValue(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IntSliceVarP is like IntSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) IntSliceVarP(p *[]int, name, shorthand string, value []int, usage string) {
|
|
||||||
f.VarP(newIntSliceValue(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IntSliceVar defines a int[] flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a int[] variable in which to store the value of the flag.
|
|
||||||
func IntSliceVar(p *[]int, name string, value []int, usage string) {
|
|
||||||
CommandLine.VarP(newIntSliceValue(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IntSliceVarP is like IntSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func IntSliceVarP(p *[]int, name, shorthand string, value []int, usage string) {
|
|
||||||
CommandLine.VarP(newIntSliceValue(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IntSlice defines a []int flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a []int variable that stores the value of the flag.
|
|
||||||
func (f *FlagSet) IntSlice(name string, value []int, usage string) *[]int {
|
|
||||||
p := []int{}
|
|
||||||
f.IntSliceVarP(&p, name, "", value, usage)
|
|
||||||
return &p
|
|
||||||
}
|
|
||||||
|
|
||||||
// IntSliceP is like IntSlice, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) IntSliceP(name, shorthand string, value []int, usage string) *[]int {
|
|
||||||
p := []int{}
|
|
||||||
f.IntSliceVarP(&p, name, shorthand, value, usage)
|
|
||||||
return &p
|
|
||||||
}
|
|
||||||
|
|
||||||
// IntSlice defines a []int flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a []int variable that stores the value of the flag.
|
|
||||||
func IntSlice(name string, value []int, usage string) *[]int {
|
|
||||||
return CommandLine.IntSliceP(name, "", value, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IntSliceP is like IntSlice, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func IntSliceP(name, shorthand string, value []int, usage string) *[]int {
|
|
||||||
return CommandLine.IntSliceP(name, shorthand, value, usage)
|
|
||||||
}
|
|
165
vendor/github.com/spf13/pflag/int_slice_test.go
generated
vendored
165
vendor/github.com/spf13/pflag/int_slice_test.go
generated
vendored
|
@ -1,165 +0,0 @@
|
||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package pflag
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func setUpISFlagSet(isp *[]int) *FlagSet {
|
|
||||||
f := NewFlagSet("test", ContinueOnError)
|
|
||||||
f.IntSliceVar(isp, "is", []int{}, "Command separated list!")
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func setUpISFlagSetWithDefault(isp *[]int) *FlagSet {
|
|
||||||
f := NewFlagSet("test", ContinueOnError)
|
|
||||||
f.IntSliceVar(isp, "is", []int{0, 1}, "Command separated list!")
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEmptyIS(t *testing.T) {
|
|
||||||
var is []int
|
|
||||||
f := setUpISFlagSet(&is)
|
|
||||||
err := f.Parse([]string{})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
getIS, err := f.GetIntSlice("is")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("got an error from GetIntSlice():", err)
|
|
||||||
}
|
|
||||||
if len(getIS) != 0 {
|
|
||||||
t.Fatalf("got is %v with len=%d but expected length=0", getIS, len(getIS))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIS(t *testing.T) {
|
|
||||||
var is []int
|
|
||||||
f := setUpISFlagSet(&is)
|
|
||||||
|
|
||||||
vals := []string{"1", "2", "4", "3"}
|
|
||||||
arg := fmt.Sprintf("--is=%s", strings.Join(vals, ","))
|
|
||||||
err := f.Parse([]string{arg})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
for i, v := range is {
|
|
||||||
d, err := strconv.Atoi(vals[i])
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("got error: %v", err)
|
|
||||||
}
|
|
||||||
if d != v {
|
|
||||||
t.Fatalf("expected is[%d] to be %s but got: %d", i, vals[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
getIS, err := f.GetIntSlice("is")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("got error: %v", err)
|
|
||||||
}
|
|
||||||
for i, v := range getIS {
|
|
||||||
d, err := strconv.Atoi(vals[i])
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("got error: %v", err)
|
|
||||||
}
|
|
||||||
if d != v {
|
|
||||||
t.Fatalf("expected is[%d] to be %s but got: %d from GetIntSlice", i, vals[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestISDefault(t *testing.T) {
|
|
||||||
var is []int
|
|
||||||
f := setUpISFlagSetWithDefault(&is)
|
|
||||||
|
|
||||||
vals := []string{"0", "1"}
|
|
||||||
|
|
||||||
err := f.Parse([]string{})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
for i, v := range is {
|
|
||||||
d, err := strconv.Atoi(vals[i])
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("got error: %v", err)
|
|
||||||
}
|
|
||||||
if d != v {
|
|
||||||
t.Fatalf("expected is[%d] to be %d but got: %d", i, d, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getIS, err := f.GetIntSlice("is")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("got an error from GetIntSlice():", err)
|
|
||||||
}
|
|
||||||
for i, v := range getIS {
|
|
||||||
d, err := strconv.Atoi(vals[i])
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("got an error from GetIntSlice():", err)
|
|
||||||
}
|
|
||||||
if d != v {
|
|
||||||
t.Fatalf("expected is[%d] to be %d from GetIntSlice but got: %d", i, d, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestISWithDefault(t *testing.T) {
|
|
||||||
var is []int
|
|
||||||
f := setUpISFlagSetWithDefault(&is)
|
|
||||||
|
|
||||||
vals := []string{"1", "2"}
|
|
||||||
arg := fmt.Sprintf("--is=%s", strings.Join(vals, ","))
|
|
||||||
err := f.Parse([]string{arg})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
for i, v := range is {
|
|
||||||
d, err := strconv.Atoi(vals[i])
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("got error: %v", err)
|
|
||||||
}
|
|
||||||
if d != v {
|
|
||||||
t.Fatalf("expected is[%d] to be %d but got: %d", i, d, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getIS, err := f.GetIntSlice("is")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("got an error from GetIntSlice():", err)
|
|
||||||
}
|
|
||||||
for i, v := range getIS {
|
|
||||||
d, err := strconv.Atoi(vals[i])
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("got error: %v", err)
|
|
||||||
}
|
|
||||||
if d != v {
|
|
||||||
t.Fatalf("expected is[%d] to be %d from GetIntSlice but got: %d", i, d, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestISCalledTwice(t *testing.T) {
|
|
||||||
var is []int
|
|
||||||
f := setUpISFlagSet(&is)
|
|
||||||
|
|
||||||
in := []string{"1,2", "3"}
|
|
||||||
expected := []int{1, 2, 3}
|
|
||||||
argfmt := "--is=%s"
|
|
||||||
arg1 := fmt.Sprintf(argfmt, in[0])
|
|
||||||
arg2 := fmt.Sprintf(argfmt, in[1])
|
|
||||||
err := f.Parse([]string{arg1, arg2})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
for i, v := range is {
|
|
||||||
if expected[i] != v {
|
|
||||||
t.Fatalf("expected is[%d] to be %d but got: %d", i, expected[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
94
vendor/github.com/spf13/pflag/ip.go
generated
vendored
94
vendor/github.com/spf13/pflag/ip.go
generated
vendored
|
@ -1,94 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// -- net.IP value
|
|
||||||
type ipValue net.IP
|
|
||||||
|
|
||||||
func newIPValue(val net.IP, p *net.IP) *ipValue {
|
|
||||||
*p = val
|
|
||||||
return (*ipValue)(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *ipValue) String() string { return net.IP(*i).String() }
|
|
||||||
func (i *ipValue) Set(s string) error {
|
|
||||||
ip := net.ParseIP(strings.TrimSpace(s))
|
|
||||||
if ip == nil {
|
|
||||||
return fmt.Errorf("failed to parse IP: %q", s)
|
|
||||||
}
|
|
||||||
*i = ipValue(ip)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *ipValue) Type() string {
|
|
||||||
return "ip"
|
|
||||||
}
|
|
||||||
|
|
||||||
func ipConv(sval string) (interface{}, error) {
|
|
||||||
ip := net.ParseIP(sval)
|
|
||||||
if ip != nil {
|
|
||||||
return ip, nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("invalid string being converted to IP address: %s", sval)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetIP return the net.IP value of a flag with the given name
|
|
||||||
func (f *FlagSet) GetIP(name string) (net.IP, error) {
|
|
||||||
val, err := f.getFlagType(name, "ip", ipConv)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return val.(net.IP), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPVar defines an net.IP flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to an net.IP variable in which to store the value of the flag.
|
|
||||||
func (f *FlagSet) IPVar(p *net.IP, name string, value net.IP, usage string) {
|
|
||||||
f.VarP(newIPValue(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPVarP is like IPVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) IPVarP(p *net.IP, name, shorthand string, value net.IP, usage string) {
|
|
||||||
f.VarP(newIPValue(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPVar defines an net.IP flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to an net.IP variable in which to store the value of the flag.
|
|
||||||
func IPVar(p *net.IP, name string, value net.IP, usage string) {
|
|
||||||
CommandLine.VarP(newIPValue(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPVarP is like IPVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func IPVarP(p *net.IP, name, shorthand string, value net.IP, usage string) {
|
|
||||||
CommandLine.VarP(newIPValue(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IP defines an net.IP flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of an net.IP variable that stores the value of the flag.
|
|
||||||
func (f *FlagSet) IP(name string, value net.IP, usage string) *net.IP {
|
|
||||||
p := new(net.IP)
|
|
||||||
f.IPVarP(p, name, "", value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPP is like IP, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) IPP(name, shorthand string, value net.IP, usage string) *net.IP {
|
|
||||||
p := new(net.IP)
|
|
||||||
f.IPVarP(p, name, shorthand, value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// IP defines an net.IP flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of an net.IP variable that stores the value of the flag.
|
|
||||||
func IP(name string, value net.IP, usage string) *net.IP {
|
|
||||||
return CommandLine.IPP(name, "", value, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPP is like IP, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func IPP(name, shorthand string, value net.IP, usage string) *net.IP {
|
|
||||||
return CommandLine.IPP(name, shorthand, value, usage)
|
|
||||||
}
|
|
148
vendor/github.com/spf13/pflag/ip_slice.go
generated
vendored
148
vendor/github.com/spf13/pflag/ip_slice.go
generated
vendored
|
@ -1,148 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// -- ipSlice Value
|
|
||||||
type ipSliceValue struct {
|
|
||||||
value *[]net.IP
|
|
||||||
changed bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func newIPSliceValue(val []net.IP, p *[]net.IP) *ipSliceValue {
|
|
||||||
ipsv := new(ipSliceValue)
|
|
||||||
ipsv.value = p
|
|
||||||
*ipsv.value = val
|
|
||||||
return ipsv
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set converts, and assigns, the comma-separated IP argument string representation as the []net.IP value of this flag.
|
|
||||||
// If Set is called on a flag that already has a []net.IP assigned, the newly converted values will be appended.
|
|
||||||
func (s *ipSliceValue) Set(val string) error {
|
|
||||||
|
|
||||||
// remove all quote characters
|
|
||||||
rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "")
|
|
||||||
|
|
||||||
// read flag arguments with CSV parser
|
|
||||||
ipStrSlice, err := readAsCSV(rmQuote.Replace(val))
|
|
||||||
if err != nil && err != io.EOF {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse ip values into slice
|
|
||||||
out := make([]net.IP, 0, len(ipStrSlice))
|
|
||||||
for _, ipStr := range ipStrSlice {
|
|
||||||
ip := net.ParseIP(strings.TrimSpace(ipStr))
|
|
||||||
if ip == nil {
|
|
||||||
return fmt.Errorf("invalid string being converted to IP address: %s", ipStr)
|
|
||||||
}
|
|
||||||
out = append(out, ip)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !s.changed {
|
|
||||||
*s.value = out
|
|
||||||
} else {
|
|
||||||
*s.value = append(*s.value, out...)
|
|
||||||
}
|
|
||||||
|
|
||||||
s.changed = true
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type returns a string that uniquely represents this flag's type.
|
|
||||||
func (s *ipSliceValue) Type() string {
|
|
||||||
return "ipSlice"
|
|
||||||
}
|
|
||||||
|
|
||||||
// String defines a "native" format for this net.IP slice flag value.
|
|
||||||
func (s *ipSliceValue) String() string {
|
|
||||||
|
|
||||||
ipStrSlice := make([]string, len(*s.value))
|
|
||||||
for i, ip := range *s.value {
|
|
||||||
ipStrSlice[i] = ip.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
out, _ := writeAsCSV(ipStrSlice)
|
|
||||||
|
|
||||||
return "[" + out + "]"
|
|
||||||
}
|
|
||||||
|
|
||||||
func ipSliceConv(val string) (interface{}, error) {
|
|
||||||
val = strings.Trim(val, "[]")
|
|
||||||
// Emtpy string would cause a slice with one (empty) entry
|
|
||||||
if len(val) == 0 {
|
|
||||||
return []net.IP{}, nil
|
|
||||||
}
|
|
||||||
ss := strings.Split(val, ",")
|
|
||||||
out := make([]net.IP, len(ss))
|
|
||||||
for i, sval := range ss {
|
|
||||||
ip := net.ParseIP(strings.TrimSpace(sval))
|
|
||||||
if ip == nil {
|
|
||||||
return nil, fmt.Errorf("invalid string being converted to IP address: %s", sval)
|
|
||||||
}
|
|
||||||
out[i] = ip
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetIPSlice returns the []net.IP value of a flag with the given name
|
|
||||||
func (f *FlagSet) GetIPSlice(name string) ([]net.IP, error) {
|
|
||||||
val, err := f.getFlagType(name, "ipSlice", ipSliceConv)
|
|
||||||
if err != nil {
|
|
||||||
return []net.IP{}, err
|
|
||||||
}
|
|
||||||
return val.([]net.IP), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPSliceVar defines a ipSlice flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a []net.IP variable in which to store the value of the flag.
|
|
||||||
func (f *FlagSet) IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) {
|
|
||||||
f.VarP(newIPSliceValue(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) {
|
|
||||||
f.VarP(newIPSliceValue(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPSliceVar defines a []net.IP flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a []net.IP variable in which to store the value of the flag.
|
|
||||||
func IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) {
|
|
||||||
CommandLine.VarP(newIPSliceValue(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) {
|
|
||||||
CommandLine.VarP(newIPSliceValue(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPSlice defines a []net.IP flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a []net.IP variable that stores the value of that flag.
|
|
||||||
func (f *FlagSet) IPSlice(name string, value []net.IP, usage string) *[]net.IP {
|
|
||||||
p := []net.IP{}
|
|
||||||
f.IPSliceVarP(&p, name, "", value, usage)
|
|
||||||
return &p
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP {
|
|
||||||
p := []net.IP{}
|
|
||||||
f.IPSliceVarP(&p, name, shorthand, value, usage)
|
|
||||||
return &p
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPSlice defines a []net.IP flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a []net.IP variable that stores the value of the flag.
|
|
||||||
func IPSlice(name string, value []net.IP, usage string) *[]net.IP {
|
|
||||||
return CommandLine.IPSliceP(name, "", value, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP {
|
|
||||||
return CommandLine.IPSliceP(name, shorthand, value, usage)
|
|
||||||
}
|
|
222
vendor/github.com/spf13/pflag/ip_slice_test.go
generated
vendored
222
vendor/github.com/spf13/pflag/ip_slice_test.go
generated
vendored
|
@ -1,222 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func setUpIPSFlagSet(ipsp *[]net.IP) *FlagSet {
|
|
||||||
f := NewFlagSet("test", ContinueOnError)
|
|
||||||
f.IPSliceVar(ipsp, "ips", []net.IP{}, "Command separated list!")
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func setUpIPSFlagSetWithDefault(ipsp *[]net.IP) *FlagSet {
|
|
||||||
f := NewFlagSet("test", ContinueOnError)
|
|
||||||
f.IPSliceVar(ipsp, "ips",
|
|
||||||
[]net.IP{
|
|
||||||
net.ParseIP("192.168.1.1"),
|
|
||||||
net.ParseIP("0:0:0:0:0:0:0:1"),
|
|
||||||
},
|
|
||||||
"Command separated list!")
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEmptyIP(t *testing.T) {
|
|
||||||
var ips []net.IP
|
|
||||||
f := setUpIPSFlagSet(&ips)
|
|
||||||
err := f.Parse([]string{})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
getIPS, err := f.GetIPSlice("ips")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("got an error from GetIPSlice():", err)
|
|
||||||
}
|
|
||||||
if len(getIPS) != 0 {
|
|
||||||
t.Fatalf("got ips %v with len=%d but expected length=0", getIPS, len(getIPS))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIPS(t *testing.T) {
|
|
||||||
var ips []net.IP
|
|
||||||
f := setUpIPSFlagSet(&ips)
|
|
||||||
|
|
||||||
vals := []string{"192.168.1.1", "10.0.0.1", "0:0:0:0:0:0:0:2"}
|
|
||||||
arg := fmt.Sprintf("--ips=%s", strings.Join(vals, ","))
|
|
||||||
err := f.Parse([]string{arg})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
for i, v := range ips {
|
|
||||||
if ip := net.ParseIP(vals[i]); ip == nil {
|
|
||||||
t.Fatalf("invalid string being converted to IP address: %s", vals[i])
|
|
||||||
} else if !ip.Equal(v) {
|
|
||||||
t.Fatalf("expected ips[%d] to be %s but got: %s from GetIPSlice", i, vals[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIPSDefault(t *testing.T) {
|
|
||||||
var ips []net.IP
|
|
||||||
f := setUpIPSFlagSetWithDefault(&ips)
|
|
||||||
|
|
||||||
vals := []string{"192.168.1.1", "0:0:0:0:0:0:0:1"}
|
|
||||||
err := f.Parse([]string{})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
for i, v := range ips {
|
|
||||||
if ip := net.ParseIP(vals[i]); ip == nil {
|
|
||||||
t.Fatalf("invalid string being converted to IP address: %s", vals[i])
|
|
||||||
} else if !ip.Equal(v) {
|
|
||||||
t.Fatalf("expected ips[%d] to be %s but got: %s", i, vals[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getIPS, err := f.GetIPSlice("ips")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("got an error from GetIPSlice")
|
|
||||||
}
|
|
||||||
for i, v := range getIPS {
|
|
||||||
if ip := net.ParseIP(vals[i]); ip == nil {
|
|
||||||
t.Fatalf("invalid string being converted to IP address: %s", vals[i])
|
|
||||||
} else if !ip.Equal(v) {
|
|
||||||
t.Fatalf("expected ips[%d] to be %s but got: %s", i, vals[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIPSWithDefault(t *testing.T) {
|
|
||||||
var ips []net.IP
|
|
||||||
f := setUpIPSFlagSetWithDefault(&ips)
|
|
||||||
|
|
||||||
vals := []string{"192.168.1.1", "0:0:0:0:0:0:0:1"}
|
|
||||||
arg := fmt.Sprintf("--ips=%s", strings.Join(vals, ","))
|
|
||||||
err := f.Parse([]string{arg})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
for i, v := range ips {
|
|
||||||
if ip := net.ParseIP(vals[i]); ip == nil {
|
|
||||||
t.Fatalf("invalid string being converted to IP address: %s", vals[i])
|
|
||||||
} else if !ip.Equal(v) {
|
|
||||||
t.Fatalf("expected ips[%d] to be %s but got: %s", i, vals[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getIPS, err := f.GetIPSlice("ips")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("got an error from GetIPSlice")
|
|
||||||
}
|
|
||||||
for i, v := range getIPS {
|
|
||||||
if ip := net.ParseIP(vals[i]); ip == nil {
|
|
||||||
t.Fatalf("invalid string being converted to IP address: %s", vals[i])
|
|
||||||
} else if !ip.Equal(v) {
|
|
||||||
t.Fatalf("expected ips[%d] to be %s but got: %s", i, vals[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIPSCalledTwice(t *testing.T) {
|
|
||||||
var ips []net.IP
|
|
||||||
f := setUpIPSFlagSet(&ips)
|
|
||||||
|
|
||||||
in := []string{"192.168.1.2,0:0:0:0:0:0:0:1", "10.0.0.1"}
|
|
||||||
expected := []net.IP{net.ParseIP("192.168.1.2"), net.ParseIP("0:0:0:0:0:0:0:1"), net.ParseIP("10.0.0.1")}
|
|
||||||
argfmt := "ips=%s"
|
|
||||||
arg1 := fmt.Sprintf(argfmt, in[0])
|
|
||||||
arg2 := fmt.Sprintf(argfmt, in[1])
|
|
||||||
err := f.Parse([]string{arg1, arg2})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
for i, v := range ips {
|
|
||||||
if !expected[i].Equal(v) {
|
|
||||||
t.Fatalf("expected ips[%d] to be %s but got: %s", i, expected[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIPSBadQuoting(t *testing.T) {
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
Want []net.IP
|
|
||||||
FlagArg []string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
Want: []net.IP{
|
|
||||||
net.ParseIP("a4ab:61d:f03e:5d7d:fad7:d4c2:a1a5:568"),
|
|
||||||
net.ParseIP("203.107.49.208"),
|
|
||||||
net.ParseIP("14.57.204.90"),
|
|
||||||
},
|
|
||||||
FlagArg: []string{
|
|
||||||
"a4ab:61d:f03e:5d7d:fad7:d4c2:a1a5:568",
|
|
||||||
"203.107.49.208",
|
|
||||||
"14.57.204.90",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Want: []net.IP{
|
|
||||||
net.ParseIP("204.228.73.195"),
|
|
||||||
net.ParseIP("86.141.15.94"),
|
|
||||||
},
|
|
||||||
FlagArg: []string{
|
|
||||||
"204.228.73.195",
|
|
||||||
"86.141.15.94",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Want: []net.IP{
|
|
||||||
net.ParseIP("c70c:db36:3001:890f:c6ea:3f9b:7a39:cc3f"),
|
|
||||||
net.ParseIP("4d17:1d6e:e699:bd7a:88c5:5e7e:ac6a:4472"),
|
|
||||||
},
|
|
||||||
FlagArg: []string{
|
|
||||||
"c70c:db36:3001:890f:c6ea:3f9b:7a39:cc3f",
|
|
||||||
"4d17:1d6e:e699:bd7a:88c5:5e7e:ac6a:4472",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Want: []net.IP{
|
|
||||||
net.ParseIP("5170:f971:cfac:7be3:512a:af37:952c:bc33"),
|
|
||||||
net.ParseIP("93.21.145.140"),
|
|
||||||
net.ParseIP("2cac:61d3:c5ff:6caf:73e0:1b1a:c336:c1ca"),
|
|
||||||
},
|
|
||||||
FlagArg: []string{
|
|
||||||
" 5170:f971:cfac:7be3:512a:af37:952c:bc33 , 93.21.145.140 ",
|
|
||||||
"2cac:61d3:c5ff:6caf:73e0:1b1a:c336:c1ca",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Want: []net.IP{
|
|
||||||
net.ParseIP("2e5e:66b2:6441:848:5b74:76ea:574c:3a7b"),
|
|
||||||
net.ParseIP("2e5e:66b2:6441:848:5b74:76ea:574c:3a7b"),
|
|
||||||
net.ParseIP("2e5e:66b2:6441:848:5b74:76ea:574c:3a7b"),
|
|
||||||
net.ParseIP("2e5e:66b2:6441:848:5b74:76ea:574c:3a7b"),
|
|
||||||
},
|
|
||||||
FlagArg: []string{
|
|
||||||
`"2e5e:66b2:6441:848:5b74:76ea:574c:3a7b, 2e5e:66b2:6441:848:5b74:76ea:574c:3a7b,2e5e:66b2:6441:848:5b74:76ea:574c:3a7b "`,
|
|
||||||
" 2e5e:66b2:6441:848:5b74:76ea:574c:3a7b"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, test := range tests {
|
|
||||||
|
|
||||||
var ips []net.IP
|
|
||||||
f := setUpIPSFlagSet(&ips)
|
|
||||||
|
|
||||||
if err := f.Parse([]string{fmt.Sprintf("--ips=%s", strings.Join(test.FlagArg, ","))}); err != nil {
|
|
||||||
t.Fatalf("flag parsing failed with error: %s\nparsing:\t%#v\nwant:\t\t%s",
|
|
||||||
err, test.FlagArg, test.Want[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
for j, b := range ips {
|
|
||||||
if !b.Equal(test.Want[j]) {
|
|
||||||
t.Fatalf("bad value parsed for test %d on net.IP %d:\nwant:\t%s\ngot:\t%s", i, j, test.Want[j], b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
63
vendor/github.com/spf13/pflag/ip_test.go
generated
vendored
63
vendor/github.com/spf13/pflag/ip_test.go
generated
vendored
|
@ -1,63 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func setUpIP(ip *net.IP) *FlagSet {
|
|
||||||
f := NewFlagSet("test", ContinueOnError)
|
|
||||||
f.IPVar(ip, "address", net.ParseIP("0.0.0.0"), "IP Address")
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIP(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
input string
|
|
||||||
success bool
|
|
||||||
expected string
|
|
||||||
}{
|
|
||||||
{"0.0.0.0", true, "0.0.0.0"},
|
|
||||||
{" 0.0.0.0 ", true, "0.0.0.0"},
|
|
||||||
{"1.2.3.4", true, "1.2.3.4"},
|
|
||||||
{"127.0.0.1", true, "127.0.0.1"},
|
|
||||||
{"255.255.255.255", true, "255.255.255.255"},
|
|
||||||
{"", false, ""},
|
|
||||||
{"0", false, ""},
|
|
||||||
{"localhost", false, ""},
|
|
||||||
{"0.0.0", false, ""},
|
|
||||||
{"0.0.0.", false, ""},
|
|
||||||
{"0.0.0.0.", false, ""},
|
|
||||||
{"0.0.0.256", false, ""},
|
|
||||||
{"0 . 0 . 0 . 0", false, ""},
|
|
||||||
}
|
|
||||||
|
|
||||||
devnull, _ := os.Open(os.DevNull)
|
|
||||||
os.Stderr = devnull
|
|
||||||
for i := range testCases {
|
|
||||||
var addr net.IP
|
|
||||||
f := setUpIP(&addr)
|
|
||||||
|
|
||||||
tc := &testCases[i]
|
|
||||||
|
|
||||||
arg := fmt.Sprintf("--address=%s", tc.input)
|
|
||||||
err := f.Parse([]string{arg})
|
|
||||||
if err != nil && tc.success == true {
|
|
||||||
t.Errorf("expected success, got %q", err)
|
|
||||||
continue
|
|
||||||
} else if err == nil && tc.success == false {
|
|
||||||
t.Errorf("expected failure")
|
|
||||||
continue
|
|
||||||
} else if tc.success {
|
|
||||||
ip, err := f.GetIP("address")
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Got error trying to fetch the IP flag: %v", err)
|
|
||||||
}
|
|
||||||
if ip.String() != tc.expected {
|
|
||||||
t.Errorf("expected %q, got %q", tc.expected, ip.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
122
vendor/github.com/spf13/pflag/ipmask.go
generated
vendored
122
vendor/github.com/spf13/pflag/ipmask.go
generated
vendored
|
@ -1,122 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
// -- net.IPMask value
|
|
||||||
type ipMaskValue net.IPMask
|
|
||||||
|
|
||||||
func newIPMaskValue(val net.IPMask, p *net.IPMask) *ipMaskValue {
|
|
||||||
*p = val
|
|
||||||
return (*ipMaskValue)(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *ipMaskValue) String() string { return net.IPMask(*i).String() }
|
|
||||||
func (i *ipMaskValue) Set(s string) error {
|
|
||||||
ip := ParseIPv4Mask(s)
|
|
||||||
if ip == nil {
|
|
||||||
return fmt.Errorf("failed to parse IP mask: %q", s)
|
|
||||||
}
|
|
||||||
*i = ipMaskValue(ip)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *ipMaskValue) Type() string {
|
|
||||||
return "ipMask"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseIPv4Mask written in IP form (e.g. 255.255.255.0).
|
|
||||||
// This function should really belong to the net package.
|
|
||||||
func ParseIPv4Mask(s string) net.IPMask {
|
|
||||||
mask := net.ParseIP(s)
|
|
||||||
if mask == nil {
|
|
||||||
if len(s) != 8 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// net.IPMask.String() actually outputs things like ffffff00
|
|
||||||
// so write a horrible parser for that as well :-(
|
|
||||||
m := []int{}
|
|
||||||
for i := 0; i < 4; i++ {
|
|
||||||
b := "0x" + s[2*i:2*i+2]
|
|
||||||
d, err := strconv.ParseInt(b, 0, 0)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
m = append(m, int(d))
|
|
||||||
}
|
|
||||||
s := fmt.Sprintf("%d.%d.%d.%d", m[0], m[1], m[2], m[3])
|
|
||||||
mask = net.ParseIP(s)
|
|
||||||
if mask == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return net.IPv4Mask(mask[12], mask[13], mask[14], mask[15])
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseIPv4Mask(sval string) (interface{}, error) {
|
|
||||||
mask := ParseIPv4Mask(sval)
|
|
||||||
if mask == nil {
|
|
||||||
return nil, fmt.Errorf("unable to parse %s as net.IPMask", sval)
|
|
||||||
}
|
|
||||||
return mask, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetIPv4Mask return the net.IPv4Mask value of a flag with the given name
|
|
||||||
func (f *FlagSet) GetIPv4Mask(name string) (net.IPMask, error) {
|
|
||||||
val, err := f.getFlagType(name, "ipMask", parseIPv4Mask)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return val.(net.IPMask), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPMaskVar defines an net.IPMask flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to an net.IPMask variable in which to store the value of the flag.
|
|
||||||
func (f *FlagSet) IPMaskVar(p *net.IPMask, name string, value net.IPMask, usage string) {
|
|
||||||
f.VarP(newIPMaskValue(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPMaskVarP is like IPMaskVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) IPMaskVarP(p *net.IPMask, name, shorthand string, value net.IPMask, usage string) {
|
|
||||||
f.VarP(newIPMaskValue(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPMaskVar defines an net.IPMask flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to an net.IPMask variable in which to store the value of the flag.
|
|
||||||
func IPMaskVar(p *net.IPMask, name string, value net.IPMask, usage string) {
|
|
||||||
CommandLine.VarP(newIPMaskValue(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPMaskVarP is like IPMaskVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func IPMaskVarP(p *net.IPMask, name, shorthand string, value net.IPMask, usage string) {
|
|
||||||
CommandLine.VarP(newIPMaskValue(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPMask defines an net.IPMask flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of an net.IPMask variable that stores the value of the flag.
|
|
||||||
func (f *FlagSet) IPMask(name string, value net.IPMask, usage string) *net.IPMask {
|
|
||||||
p := new(net.IPMask)
|
|
||||||
f.IPMaskVarP(p, name, "", value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPMaskP is like IPMask, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) IPMaskP(name, shorthand string, value net.IPMask, usage string) *net.IPMask {
|
|
||||||
p := new(net.IPMask)
|
|
||||||
f.IPMaskVarP(p, name, shorthand, value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPMask defines an net.IPMask flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of an net.IPMask variable that stores the value of the flag.
|
|
||||||
func IPMask(name string, value net.IPMask, usage string) *net.IPMask {
|
|
||||||
return CommandLine.IPMaskP(name, "", value, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPMaskP is like IP, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func IPMaskP(name, shorthand string, value net.IPMask, usage string) *net.IPMask {
|
|
||||||
return CommandLine.IPMaskP(name, shorthand, value, usage)
|
|
||||||
}
|
|
98
vendor/github.com/spf13/pflag/ipnet.go
generated
vendored
98
vendor/github.com/spf13/pflag/ipnet.go
generated
vendored
|
@ -1,98 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// IPNet adapts net.IPNet for use as a flag.
|
|
||||||
type ipNetValue net.IPNet
|
|
||||||
|
|
||||||
func (ipnet ipNetValue) String() string {
|
|
||||||
n := net.IPNet(ipnet)
|
|
||||||
return n.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ipnet *ipNetValue) Set(value string) error {
|
|
||||||
_, n, err := net.ParseCIDR(strings.TrimSpace(value))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*ipnet = ipNetValue(*n)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*ipNetValue) Type() string {
|
|
||||||
return "ipNet"
|
|
||||||
}
|
|
||||||
|
|
||||||
func newIPNetValue(val net.IPNet, p *net.IPNet) *ipNetValue {
|
|
||||||
*p = val
|
|
||||||
return (*ipNetValue)(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ipNetConv(sval string) (interface{}, error) {
|
|
||||||
_, n, err := net.ParseCIDR(strings.TrimSpace(sval))
|
|
||||||
if err == nil {
|
|
||||||
return *n, nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("invalid string being converted to IPNet: %s", sval)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetIPNet return the net.IPNet value of a flag with the given name
|
|
||||||
func (f *FlagSet) GetIPNet(name string) (net.IPNet, error) {
|
|
||||||
val, err := f.getFlagType(name, "ipNet", ipNetConv)
|
|
||||||
if err != nil {
|
|
||||||
return net.IPNet{}, err
|
|
||||||
}
|
|
||||||
return val.(net.IPNet), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPNetVar defines an net.IPNet flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to an net.IPNet variable in which to store the value of the flag.
|
|
||||||
func (f *FlagSet) IPNetVar(p *net.IPNet, name string, value net.IPNet, usage string) {
|
|
||||||
f.VarP(newIPNetValue(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPNetVarP is like IPNetVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) IPNetVarP(p *net.IPNet, name, shorthand string, value net.IPNet, usage string) {
|
|
||||||
f.VarP(newIPNetValue(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPNetVar defines an net.IPNet flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to an net.IPNet variable in which to store the value of the flag.
|
|
||||||
func IPNetVar(p *net.IPNet, name string, value net.IPNet, usage string) {
|
|
||||||
CommandLine.VarP(newIPNetValue(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPNetVarP is like IPNetVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func IPNetVarP(p *net.IPNet, name, shorthand string, value net.IPNet, usage string) {
|
|
||||||
CommandLine.VarP(newIPNetValue(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPNet defines an net.IPNet flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of an net.IPNet variable that stores the value of the flag.
|
|
||||||
func (f *FlagSet) IPNet(name string, value net.IPNet, usage string) *net.IPNet {
|
|
||||||
p := new(net.IPNet)
|
|
||||||
f.IPNetVarP(p, name, "", value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPNetP is like IPNet, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) IPNetP(name, shorthand string, value net.IPNet, usage string) *net.IPNet {
|
|
||||||
p := new(net.IPNet)
|
|
||||||
f.IPNetVarP(p, name, shorthand, value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPNet defines an net.IPNet flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of an net.IPNet variable that stores the value of the flag.
|
|
||||||
func IPNet(name string, value net.IPNet, usage string) *net.IPNet {
|
|
||||||
return CommandLine.IPNetP(name, "", value, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPNetP is like IPNet, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func IPNetP(name, shorthand string, value net.IPNet, usage string) *net.IPNet {
|
|
||||||
return CommandLine.IPNetP(name, shorthand, value, usage)
|
|
||||||
}
|
|
70
vendor/github.com/spf13/pflag/ipnet_test.go
generated
vendored
70
vendor/github.com/spf13/pflag/ipnet_test.go
generated
vendored
|
@ -1,70 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func setUpIPNet(ip *net.IPNet) *FlagSet {
|
|
||||||
f := NewFlagSet("test", ContinueOnError)
|
|
||||||
_, def, _ := net.ParseCIDR("0.0.0.0/0")
|
|
||||||
f.IPNetVar(ip, "address", *def, "IP Address")
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIPNet(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
input string
|
|
||||||
success bool
|
|
||||||
expected string
|
|
||||||
}{
|
|
||||||
{"0.0.0.0/0", true, "0.0.0.0/0"},
|
|
||||||
{" 0.0.0.0/0 ", true, "0.0.0.0/0"},
|
|
||||||
{"1.2.3.4/8", true, "1.0.0.0/8"},
|
|
||||||
{"127.0.0.1/16", true, "127.0.0.0/16"},
|
|
||||||
{"255.255.255.255/19", true, "255.255.224.0/19"},
|
|
||||||
{"255.255.255.255/32", true, "255.255.255.255/32"},
|
|
||||||
{"", false, ""},
|
|
||||||
{"/0", false, ""},
|
|
||||||
{"0", false, ""},
|
|
||||||
{"0/0", false, ""},
|
|
||||||
{"localhost/0", false, ""},
|
|
||||||
{"0.0.0/4", false, ""},
|
|
||||||
{"0.0.0./8", false, ""},
|
|
||||||
{"0.0.0.0./12", false, ""},
|
|
||||||
{"0.0.0.256/16", false, ""},
|
|
||||||
{"0.0.0.0 /20", false, ""},
|
|
||||||
{"0.0.0.0/ 24", false, ""},
|
|
||||||
{"0 . 0 . 0 . 0 / 28", false, ""},
|
|
||||||
{"0.0.0.0/33", false, ""},
|
|
||||||
}
|
|
||||||
|
|
||||||
devnull, _ := os.Open(os.DevNull)
|
|
||||||
os.Stderr = devnull
|
|
||||||
for i := range testCases {
|
|
||||||
var addr net.IPNet
|
|
||||||
f := setUpIPNet(&addr)
|
|
||||||
|
|
||||||
tc := &testCases[i]
|
|
||||||
|
|
||||||
arg := fmt.Sprintf("--address=%s", tc.input)
|
|
||||||
err := f.Parse([]string{arg})
|
|
||||||
if err != nil && tc.success == true {
|
|
||||||
t.Errorf("expected success, got %q", err)
|
|
||||||
continue
|
|
||||||
} else if err == nil && tc.success == false {
|
|
||||||
t.Errorf("expected failure")
|
|
||||||
continue
|
|
||||||
} else if tc.success {
|
|
||||||
ip, err := f.GetIPNet("address")
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Got error trying to fetch the IP flag: %v", err)
|
|
||||||
}
|
|
||||||
if ip.String() != tc.expected {
|
|
||||||
t.Errorf("expected %q, got %q", tc.expected, ip.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
80
vendor/github.com/spf13/pflag/string.go
generated
vendored
80
vendor/github.com/spf13/pflag/string.go
generated
vendored
|
@ -1,80 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
// -- string Value
|
|
||||||
type stringValue string
|
|
||||||
|
|
||||||
func newStringValue(val string, p *string) *stringValue {
|
|
||||||
*p = val
|
|
||||||
return (*stringValue)(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stringValue) Set(val string) error {
|
|
||||||
*s = stringValue(val)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (s *stringValue) Type() string {
|
|
||||||
return "string"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stringValue) String() string { return string(*s) }
|
|
||||||
|
|
||||||
func stringConv(sval string) (interface{}, error) {
|
|
||||||
return sval, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetString return the string value of a flag with the given name
|
|
||||||
func (f *FlagSet) GetString(name string) (string, error) {
|
|
||||||
val, err := f.getFlagType(name, "string", stringConv)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return val.(string), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringVar defines a string flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a string variable in which to store the value of the flag.
|
|
||||||
func (f *FlagSet) StringVar(p *string, name string, value string, usage string) {
|
|
||||||
f.VarP(newStringValue(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringVarP is like StringVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) StringVarP(p *string, name, shorthand string, value string, usage string) {
|
|
||||||
f.VarP(newStringValue(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringVar defines a string flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a string variable in which to store the value of the flag.
|
|
||||||
func StringVar(p *string, name string, value string, usage string) {
|
|
||||||
CommandLine.VarP(newStringValue(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringVarP is like StringVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func StringVarP(p *string, name, shorthand string, value string, usage string) {
|
|
||||||
CommandLine.VarP(newStringValue(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// String defines a string flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a string variable that stores the value of the flag.
|
|
||||||
func (f *FlagSet) String(name string, value string, usage string) *string {
|
|
||||||
p := new(string)
|
|
||||||
f.StringVarP(p, name, "", value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringP is like String, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) StringP(name, shorthand string, value string, usage string) *string {
|
|
||||||
p := new(string)
|
|
||||||
f.StringVarP(p, name, shorthand, value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// String defines a string flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a string variable that stores the value of the flag.
|
|
||||||
func String(name string, value string, usage string) *string {
|
|
||||||
return CommandLine.StringP(name, "", value, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringP is like String, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func StringP(name, shorthand string, value string, usage string) *string {
|
|
||||||
return CommandLine.StringP(name, shorthand, value, usage)
|
|
||||||
}
|
|
103
vendor/github.com/spf13/pflag/string_array.go
generated
vendored
103
vendor/github.com/spf13/pflag/string_array.go
generated
vendored
|
@ -1,103 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
// -- stringArray Value
|
|
||||||
type stringArrayValue struct {
|
|
||||||
value *[]string
|
|
||||||
changed bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func newStringArrayValue(val []string, p *[]string) *stringArrayValue {
|
|
||||||
ssv := new(stringArrayValue)
|
|
||||||
ssv.value = p
|
|
||||||
*ssv.value = val
|
|
||||||
return ssv
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stringArrayValue) Set(val string) error {
|
|
||||||
if !s.changed {
|
|
||||||
*s.value = []string{val}
|
|
||||||
s.changed = true
|
|
||||||
} else {
|
|
||||||
*s.value = append(*s.value, val)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stringArrayValue) Type() string {
|
|
||||||
return "stringArray"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stringArrayValue) String() string {
|
|
||||||
str, _ := writeAsCSV(*s.value)
|
|
||||||
return "[" + str + "]"
|
|
||||||
}
|
|
||||||
|
|
||||||
func stringArrayConv(sval string) (interface{}, error) {
|
|
||||||
sval = sval[1 : len(sval)-1]
|
|
||||||
// An empty string would cause a array with one (empty) string
|
|
||||||
if len(sval) == 0 {
|
|
||||||
return []string{}, nil
|
|
||||||
}
|
|
||||||
return readAsCSV(sval)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetStringArray return the []string value of a flag with the given name
|
|
||||||
func (f *FlagSet) GetStringArray(name string) ([]string, error) {
|
|
||||||
val, err := f.getFlagType(name, "stringArray", stringArrayConv)
|
|
||||||
if err != nil {
|
|
||||||
return []string{}, err
|
|
||||||
}
|
|
||||||
return val.([]string), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringArrayVar defines a string flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a []string variable in which to store the values of the multiple flags.
|
|
||||||
// The value of each argument will not try to be separated by comma
|
|
||||||
func (f *FlagSet) StringArrayVar(p *[]string, name string, value []string, usage string) {
|
|
||||||
f.VarP(newStringArrayValue(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringArrayVarP is like StringArrayVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) StringArrayVarP(p *[]string, name, shorthand string, value []string, usage string) {
|
|
||||||
f.VarP(newStringArrayValue(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringArrayVar defines a string flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a []string variable in which to store the value of the flag.
|
|
||||||
// The value of each argument will not try to be separated by comma
|
|
||||||
func StringArrayVar(p *[]string, name string, value []string, usage string) {
|
|
||||||
CommandLine.VarP(newStringArrayValue(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringArrayVarP is like StringArrayVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func StringArrayVarP(p *[]string, name, shorthand string, value []string, usage string) {
|
|
||||||
CommandLine.VarP(newStringArrayValue(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringArray defines a string flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a []string variable that stores the value of the flag.
|
|
||||||
// The value of each argument will not try to be separated by comma
|
|
||||||
func (f *FlagSet) StringArray(name string, value []string, usage string) *[]string {
|
|
||||||
p := []string{}
|
|
||||||
f.StringArrayVarP(&p, name, "", value, usage)
|
|
||||||
return &p
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringArrayP is like StringArray, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) StringArrayP(name, shorthand string, value []string, usage string) *[]string {
|
|
||||||
p := []string{}
|
|
||||||
f.StringArrayVarP(&p, name, shorthand, value, usage)
|
|
||||||
return &p
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringArray defines a string flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a []string variable that stores the value of the flag.
|
|
||||||
// The value of each argument will not try to be separated by comma
|
|
||||||
func StringArray(name string, value []string, usage string) *[]string {
|
|
||||||
return CommandLine.StringArrayP(name, "", value, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringArrayP is like StringArray, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func StringArrayP(name, shorthand string, value []string, usage string) *[]string {
|
|
||||||
return CommandLine.StringArrayP(name, shorthand, value, usage)
|
|
||||||
}
|
|
233
vendor/github.com/spf13/pflag/string_array_test.go
generated
vendored
233
vendor/github.com/spf13/pflag/string_array_test.go
generated
vendored
|
@ -1,233 +0,0 @@
|
||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package pflag
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func setUpSAFlagSet(sap *[]string) *FlagSet {
|
|
||||||
f := NewFlagSet("test", ContinueOnError)
|
|
||||||
f.StringArrayVar(sap, "sa", []string{}, "Command separated list!")
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func setUpSAFlagSetWithDefault(sap *[]string) *FlagSet {
|
|
||||||
f := NewFlagSet("test", ContinueOnError)
|
|
||||||
f.StringArrayVar(sap, "sa", []string{"default", "values"}, "Command separated list!")
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEmptySA(t *testing.T) {
|
|
||||||
var sa []string
|
|
||||||
f := setUpSAFlagSet(&sa)
|
|
||||||
err := f.Parse([]string{})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
getSA, err := f.GetStringArray("sa")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("got an error from GetStringArray():", err)
|
|
||||||
}
|
|
||||||
if len(getSA) != 0 {
|
|
||||||
t.Fatalf("got sa %v with len=%d but expected length=0", getSA, len(getSA))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEmptySAValue(t *testing.T) {
|
|
||||||
var sa []string
|
|
||||||
f := setUpSAFlagSet(&sa)
|
|
||||||
err := f.Parse([]string{"--sa="})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
getSA, err := f.GetStringArray("sa")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("got an error from GetStringArray():", err)
|
|
||||||
}
|
|
||||||
if len(getSA) != 0 {
|
|
||||||
t.Fatalf("got sa %v with len=%d but expected length=0", getSA, len(getSA))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSADefault(t *testing.T) {
|
|
||||||
var sa []string
|
|
||||||
f := setUpSAFlagSetWithDefault(&sa)
|
|
||||||
|
|
||||||
vals := []string{"default", "values"}
|
|
||||||
|
|
||||||
err := f.Parse([]string{})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
for i, v := range sa {
|
|
||||||
if vals[i] != v {
|
|
||||||
t.Fatalf("expected sa[%d] to be %s but got: %s", i, vals[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getSA, err := f.GetStringArray("sa")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("got an error from GetStringArray():", err)
|
|
||||||
}
|
|
||||||
for i, v := range getSA {
|
|
||||||
if vals[i] != v {
|
|
||||||
t.Fatalf("expected sa[%d] to be %s from GetStringArray but got: %s", i, vals[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSAWithDefault(t *testing.T) {
|
|
||||||
var sa []string
|
|
||||||
f := setUpSAFlagSetWithDefault(&sa)
|
|
||||||
|
|
||||||
val := "one"
|
|
||||||
arg := fmt.Sprintf("--sa=%s", val)
|
|
||||||
err := f.Parse([]string{arg})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(sa) != 1 {
|
|
||||||
t.Fatalf("expected number of values to be %d but %d", 1, len(sa))
|
|
||||||
}
|
|
||||||
|
|
||||||
if sa[0] != val {
|
|
||||||
t.Fatalf("expected value to be %s but got: %s", sa[0], val)
|
|
||||||
}
|
|
||||||
|
|
||||||
getSA, err := f.GetStringArray("sa")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("got an error from GetStringArray():", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(getSA) != 1 {
|
|
||||||
t.Fatalf("expected number of values to be %d but %d", 1, len(getSA))
|
|
||||||
}
|
|
||||||
|
|
||||||
if getSA[0] != val {
|
|
||||||
t.Fatalf("expected value to be %s but got: %s", getSA[0], val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSACalledTwice(t *testing.T) {
|
|
||||||
var sa []string
|
|
||||||
f := setUpSAFlagSet(&sa)
|
|
||||||
|
|
||||||
in := []string{"one", "two"}
|
|
||||||
expected := []string{"one", "two"}
|
|
||||||
argfmt := "--sa=%s"
|
|
||||||
arg1 := fmt.Sprintf(argfmt, in[0])
|
|
||||||
arg2 := fmt.Sprintf(argfmt, in[1])
|
|
||||||
err := f.Parse([]string{arg1, arg2})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(expected) != len(sa) {
|
|
||||||
t.Fatalf("expected number of sa to be %d but got: %d", len(expected), len(sa))
|
|
||||||
}
|
|
||||||
for i, v := range sa {
|
|
||||||
if expected[i] != v {
|
|
||||||
t.Fatalf("expected sa[%d] to be %s but got: %s", i, expected[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
values, err := f.GetStringArray("sa")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(expected) != len(values) {
|
|
||||||
t.Fatalf("expected number of values to be %d but got: %d", len(expected), len(sa))
|
|
||||||
}
|
|
||||||
for i, v := range values {
|
|
||||||
if expected[i] != v {
|
|
||||||
t.Fatalf("expected got sa[%d] to be %s but got: %s", i, expected[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSAWithSpecialChar(t *testing.T) {
|
|
||||||
var sa []string
|
|
||||||
f := setUpSAFlagSet(&sa)
|
|
||||||
|
|
||||||
in := []string{"one,two", `"three"`, `"four,five",six`, "seven eight"}
|
|
||||||
expected := []string{"one,two", `"three"`, `"four,five",six`, "seven eight"}
|
|
||||||
argfmt := "--sa=%s"
|
|
||||||
arg1 := fmt.Sprintf(argfmt, in[0])
|
|
||||||
arg2 := fmt.Sprintf(argfmt, in[1])
|
|
||||||
arg3 := fmt.Sprintf(argfmt, in[2])
|
|
||||||
arg4 := fmt.Sprintf(argfmt, in[3])
|
|
||||||
err := f.Parse([]string{arg1, arg2, arg3, arg4})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(expected) != len(sa) {
|
|
||||||
t.Fatalf("expected number of sa to be %d but got: %d", len(expected), len(sa))
|
|
||||||
}
|
|
||||||
for i, v := range sa {
|
|
||||||
if expected[i] != v {
|
|
||||||
t.Fatalf("expected sa[%d] to be %s but got: %s", i, expected[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
values, err := f.GetStringArray("sa")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(expected) != len(values) {
|
|
||||||
t.Fatalf("expected number of values to be %d but got: %d", len(expected), len(values))
|
|
||||||
}
|
|
||||||
for i, v := range values {
|
|
||||||
if expected[i] != v {
|
|
||||||
t.Fatalf("expected got sa[%d] to be %s but got: %s", i, expected[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSAWithSquareBrackets(t *testing.T) {
|
|
||||||
var sa []string
|
|
||||||
f := setUpSAFlagSet(&sa)
|
|
||||||
|
|
||||||
in := []string{"][]-[", "[a-z]", "[a-z]+"}
|
|
||||||
expected := []string{"][]-[", "[a-z]", "[a-z]+"}
|
|
||||||
argfmt := "--sa=%s"
|
|
||||||
arg1 := fmt.Sprintf(argfmt, in[0])
|
|
||||||
arg2 := fmt.Sprintf(argfmt, in[1])
|
|
||||||
arg3 := fmt.Sprintf(argfmt, in[2])
|
|
||||||
err := f.Parse([]string{arg1, arg2, arg3})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(expected) != len(sa) {
|
|
||||||
t.Fatalf("expected number of sa to be %d but got: %d", len(expected), len(sa))
|
|
||||||
}
|
|
||||||
for i, v := range sa {
|
|
||||||
if expected[i] != v {
|
|
||||||
t.Fatalf("expected sa[%d] to be %s but got: %s", i, expected[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
values, err := f.GetStringArray("sa")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(expected) != len(values) {
|
|
||||||
t.Fatalf("expected number of values to be %d but got: %d", len(expected), len(values))
|
|
||||||
}
|
|
||||||
for i, v := range values {
|
|
||||||
if expected[i] != v {
|
|
||||||
t.Fatalf("expected got sa[%d] to be %s but got: %s", i, expected[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
129
vendor/github.com/spf13/pflag/string_slice.go
generated
vendored
129
vendor/github.com/spf13/pflag/string_slice.go
generated
vendored
|
@ -1,129 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/csv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// -- stringSlice Value
|
|
||||||
type stringSliceValue struct {
|
|
||||||
value *[]string
|
|
||||||
changed bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func newStringSliceValue(val []string, p *[]string) *stringSliceValue {
|
|
||||||
ssv := new(stringSliceValue)
|
|
||||||
ssv.value = p
|
|
||||||
*ssv.value = val
|
|
||||||
return ssv
|
|
||||||
}
|
|
||||||
|
|
||||||
func readAsCSV(val string) ([]string, error) {
|
|
||||||
if val == "" {
|
|
||||||
return []string{}, nil
|
|
||||||
}
|
|
||||||
stringReader := strings.NewReader(val)
|
|
||||||
csvReader := csv.NewReader(stringReader)
|
|
||||||
return csvReader.Read()
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeAsCSV(vals []string) (string, error) {
|
|
||||||
b := &bytes.Buffer{}
|
|
||||||
w := csv.NewWriter(b)
|
|
||||||
err := w.Write(vals)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
w.Flush()
|
|
||||||
return strings.TrimSuffix(b.String(), "\n"), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stringSliceValue) Set(val string) error {
|
|
||||||
v, err := readAsCSV(val)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !s.changed {
|
|
||||||
*s.value = v
|
|
||||||
} else {
|
|
||||||
*s.value = append(*s.value, v...)
|
|
||||||
}
|
|
||||||
s.changed = true
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stringSliceValue) Type() string {
|
|
||||||
return "stringSlice"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stringSliceValue) String() string {
|
|
||||||
str, _ := writeAsCSV(*s.value)
|
|
||||||
return "[" + str + "]"
|
|
||||||
}
|
|
||||||
|
|
||||||
func stringSliceConv(sval string) (interface{}, error) {
|
|
||||||
sval = sval[1 : len(sval)-1]
|
|
||||||
// An empty string would cause a slice with one (empty) string
|
|
||||||
if len(sval) == 0 {
|
|
||||||
return []string{}, nil
|
|
||||||
}
|
|
||||||
return readAsCSV(sval)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetStringSlice return the []string value of a flag with the given name
|
|
||||||
func (f *FlagSet) GetStringSlice(name string) ([]string, error) {
|
|
||||||
val, err := f.getFlagType(name, "stringSlice", stringSliceConv)
|
|
||||||
if err != nil {
|
|
||||||
return []string{}, err
|
|
||||||
}
|
|
||||||
return val.([]string), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringSliceVar defines a string flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a []string variable in which to store the value of the flag.
|
|
||||||
func (f *FlagSet) StringSliceVar(p *[]string, name string, value []string, usage string) {
|
|
||||||
f.VarP(newStringSliceValue(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringSliceVarP is like StringSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) StringSliceVarP(p *[]string, name, shorthand string, value []string, usage string) {
|
|
||||||
f.VarP(newStringSliceValue(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringSliceVar defines a string flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a []string variable in which to store the value of the flag.
|
|
||||||
func StringSliceVar(p *[]string, name string, value []string, usage string) {
|
|
||||||
CommandLine.VarP(newStringSliceValue(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringSliceVarP is like StringSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func StringSliceVarP(p *[]string, name, shorthand string, value []string, usage string) {
|
|
||||||
CommandLine.VarP(newStringSliceValue(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringSlice defines a string flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a []string variable that stores the value of the flag.
|
|
||||||
func (f *FlagSet) StringSlice(name string, value []string, usage string) *[]string {
|
|
||||||
p := []string{}
|
|
||||||
f.StringSliceVarP(&p, name, "", value, usage)
|
|
||||||
return &p
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringSliceP is like StringSlice, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) StringSliceP(name, shorthand string, value []string, usage string) *[]string {
|
|
||||||
p := []string{}
|
|
||||||
f.StringSliceVarP(&p, name, shorthand, value, usage)
|
|
||||||
return &p
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringSlice defines a string flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a []string variable that stores the value of the flag.
|
|
||||||
func StringSlice(name string, value []string, usage string) *[]string {
|
|
||||||
return CommandLine.StringSliceP(name, "", value, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringSliceP is like StringSlice, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func StringSliceP(name, shorthand string, value []string, usage string) *[]string {
|
|
||||||
return CommandLine.StringSliceP(name, shorthand, value, usage)
|
|
||||||
}
|
|
253
vendor/github.com/spf13/pflag/string_slice_test.go
generated
vendored
253
vendor/github.com/spf13/pflag/string_slice_test.go
generated
vendored
|
@ -1,253 +0,0 @@
|
||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package pflag
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func setUpSSFlagSet(ssp *[]string) *FlagSet {
|
|
||||||
f := NewFlagSet("test", ContinueOnError)
|
|
||||||
f.StringSliceVar(ssp, "ss", []string{}, "Command separated list!")
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func setUpSSFlagSetWithDefault(ssp *[]string) *FlagSet {
|
|
||||||
f := NewFlagSet("test", ContinueOnError)
|
|
||||||
f.StringSliceVar(ssp, "ss", []string{"default", "values"}, "Command separated list!")
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEmptySS(t *testing.T) {
|
|
||||||
var ss []string
|
|
||||||
f := setUpSSFlagSet(&ss)
|
|
||||||
err := f.Parse([]string{})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
getSS, err := f.GetStringSlice("ss")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("got an error from GetStringSlice():", err)
|
|
||||||
}
|
|
||||||
if len(getSS) != 0 {
|
|
||||||
t.Fatalf("got ss %v with len=%d but expected length=0", getSS, len(getSS))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEmptySSValue(t *testing.T) {
|
|
||||||
var ss []string
|
|
||||||
f := setUpSSFlagSet(&ss)
|
|
||||||
err := f.Parse([]string{"--ss="})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
getSS, err := f.GetStringSlice("ss")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("got an error from GetStringSlice():", err)
|
|
||||||
}
|
|
||||||
if len(getSS) != 0 {
|
|
||||||
t.Fatalf("got ss %v with len=%d but expected length=0", getSS, len(getSS))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSS(t *testing.T) {
|
|
||||||
var ss []string
|
|
||||||
f := setUpSSFlagSet(&ss)
|
|
||||||
|
|
||||||
vals := []string{"one", "two", "4", "3"}
|
|
||||||
arg := fmt.Sprintf("--ss=%s", strings.Join(vals, ","))
|
|
||||||
err := f.Parse([]string{arg})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
for i, v := range ss {
|
|
||||||
if vals[i] != v {
|
|
||||||
t.Fatalf("expected ss[%d] to be %s but got: %s", i, vals[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getSS, err := f.GetStringSlice("ss")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("got an error from GetStringSlice():", err)
|
|
||||||
}
|
|
||||||
for i, v := range getSS {
|
|
||||||
if vals[i] != v {
|
|
||||||
t.Fatalf("expected ss[%d] to be %s from GetStringSlice but got: %s", i, vals[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSSDefault(t *testing.T) {
|
|
||||||
var ss []string
|
|
||||||
f := setUpSSFlagSetWithDefault(&ss)
|
|
||||||
|
|
||||||
vals := []string{"default", "values"}
|
|
||||||
|
|
||||||
err := f.Parse([]string{})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
for i, v := range ss {
|
|
||||||
if vals[i] != v {
|
|
||||||
t.Fatalf("expected ss[%d] to be %s but got: %s", i, vals[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getSS, err := f.GetStringSlice("ss")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("got an error from GetStringSlice():", err)
|
|
||||||
}
|
|
||||||
for i, v := range getSS {
|
|
||||||
if vals[i] != v {
|
|
||||||
t.Fatalf("expected ss[%d] to be %s from GetStringSlice but got: %s", i, vals[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSSWithDefault(t *testing.T) {
|
|
||||||
var ss []string
|
|
||||||
f := setUpSSFlagSetWithDefault(&ss)
|
|
||||||
|
|
||||||
vals := []string{"one", "two", "4", "3"}
|
|
||||||
arg := fmt.Sprintf("--ss=%s", strings.Join(vals, ","))
|
|
||||||
err := f.Parse([]string{arg})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
for i, v := range ss {
|
|
||||||
if vals[i] != v {
|
|
||||||
t.Fatalf("expected ss[%d] to be %s but got: %s", i, vals[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getSS, err := f.GetStringSlice("ss")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("got an error from GetStringSlice():", err)
|
|
||||||
}
|
|
||||||
for i, v := range getSS {
|
|
||||||
if vals[i] != v {
|
|
||||||
t.Fatalf("expected ss[%d] to be %s from GetStringSlice but got: %s", i, vals[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSSCalledTwice(t *testing.T) {
|
|
||||||
var ss []string
|
|
||||||
f := setUpSSFlagSet(&ss)
|
|
||||||
|
|
||||||
in := []string{"one,two", "three"}
|
|
||||||
expected := []string{"one", "two", "three"}
|
|
||||||
argfmt := "--ss=%s"
|
|
||||||
arg1 := fmt.Sprintf(argfmt, in[0])
|
|
||||||
arg2 := fmt.Sprintf(argfmt, in[1])
|
|
||||||
err := f.Parse([]string{arg1, arg2})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(expected) != len(ss) {
|
|
||||||
t.Fatalf("expected number of ss to be %d but got: %d", len(expected), len(ss))
|
|
||||||
}
|
|
||||||
for i, v := range ss {
|
|
||||||
if expected[i] != v {
|
|
||||||
t.Fatalf("expected ss[%d] to be %s but got: %s", i, expected[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
values, err := f.GetStringSlice("ss")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(expected) != len(values) {
|
|
||||||
t.Fatalf("expected number of values to be %d but got: %d", len(expected), len(ss))
|
|
||||||
}
|
|
||||||
for i, v := range values {
|
|
||||||
if expected[i] != v {
|
|
||||||
t.Fatalf("expected got ss[%d] to be %s but got: %s", i, expected[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSSWithComma(t *testing.T) {
|
|
||||||
var ss []string
|
|
||||||
f := setUpSSFlagSet(&ss)
|
|
||||||
|
|
||||||
in := []string{`"one,two"`, `"three"`, `"four,five",six`}
|
|
||||||
expected := []string{"one,two", "three", "four,five", "six"}
|
|
||||||
argfmt := "--ss=%s"
|
|
||||||
arg1 := fmt.Sprintf(argfmt, in[0])
|
|
||||||
arg2 := fmt.Sprintf(argfmt, in[1])
|
|
||||||
arg3 := fmt.Sprintf(argfmt, in[2])
|
|
||||||
err := f.Parse([]string{arg1, arg2, arg3})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(expected) != len(ss) {
|
|
||||||
t.Fatalf("expected number of ss to be %d but got: %d", len(expected), len(ss))
|
|
||||||
}
|
|
||||||
for i, v := range ss {
|
|
||||||
if expected[i] != v {
|
|
||||||
t.Fatalf("expected ss[%d] to be %s but got: %s", i, expected[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
values, err := f.GetStringSlice("ss")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(expected) != len(values) {
|
|
||||||
t.Fatalf("expected number of values to be %d but got: %d", len(expected), len(values))
|
|
||||||
}
|
|
||||||
for i, v := range values {
|
|
||||||
if expected[i] != v {
|
|
||||||
t.Fatalf("expected got ss[%d] to be %s but got: %s", i, expected[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSSWithSquareBrackets(t *testing.T) {
|
|
||||||
var ss []string
|
|
||||||
f := setUpSSFlagSet(&ss)
|
|
||||||
|
|
||||||
in := []string{`"[a-z]"`, `"[a-z]+"`}
|
|
||||||
expected := []string{"[a-z]", "[a-z]+"}
|
|
||||||
argfmt := "--ss=%s"
|
|
||||||
arg1 := fmt.Sprintf(argfmt, in[0])
|
|
||||||
arg2 := fmt.Sprintf(argfmt, in[1])
|
|
||||||
err := f.Parse([]string{arg1, arg2})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(expected) != len(ss) {
|
|
||||||
t.Fatalf("expected number of ss to be %d but got: %d", len(expected), len(ss))
|
|
||||||
}
|
|
||||||
for i, v := range ss {
|
|
||||||
if expected[i] != v {
|
|
||||||
t.Fatalf("expected ss[%d] to be %s but got: %s", i, expected[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
values, err := f.GetStringSlice("ss")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(expected) != len(values) {
|
|
||||||
t.Fatalf("expected number of values to be %d but got: %d", len(expected), len(values))
|
|
||||||
}
|
|
||||||
for i, v := range values {
|
|
||||||
if expected[i] != v {
|
|
||||||
t.Fatalf("expected got ss[%d] to be %s but got: %s", i, expected[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
88
vendor/github.com/spf13/pflag/uint.go
generated
vendored
88
vendor/github.com/spf13/pflag/uint.go
generated
vendored
|
@ -1,88 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import "strconv"
|
|
||||||
|
|
||||||
// -- uint Value
|
|
||||||
type uintValue uint
|
|
||||||
|
|
||||||
func newUintValue(val uint, p *uint) *uintValue {
|
|
||||||
*p = val
|
|
||||||
return (*uintValue)(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *uintValue) Set(s string) error {
|
|
||||||
v, err := strconv.ParseUint(s, 0, 64)
|
|
||||||
*i = uintValue(v)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *uintValue) Type() string {
|
|
||||||
return "uint"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *uintValue) String() string { return strconv.FormatUint(uint64(*i), 10) }
|
|
||||||
|
|
||||||
func uintConv(sval string) (interface{}, error) {
|
|
||||||
v, err := strconv.ParseUint(sval, 0, 0)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return uint(v), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUint return the uint value of a flag with the given name
|
|
||||||
func (f *FlagSet) GetUint(name string) (uint, error) {
|
|
||||||
val, err := f.getFlagType(name, "uint", uintConv)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return val.(uint), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UintVar defines a uint flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a uint variable in which to store the value of the flag.
|
|
||||||
func (f *FlagSet) UintVar(p *uint, name string, value uint, usage string) {
|
|
||||||
f.VarP(newUintValue(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UintVarP is like UintVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) UintVarP(p *uint, name, shorthand string, value uint, usage string) {
|
|
||||||
f.VarP(newUintValue(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UintVar defines a uint flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a uint variable in which to store the value of the flag.
|
|
||||||
func UintVar(p *uint, name string, value uint, usage string) {
|
|
||||||
CommandLine.VarP(newUintValue(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UintVarP is like UintVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func UintVarP(p *uint, name, shorthand string, value uint, usage string) {
|
|
||||||
CommandLine.VarP(newUintValue(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint defines a uint flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a uint variable that stores the value of the flag.
|
|
||||||
func (f *FlagSet) Uint(name string, value uint, usage string) *uint {
|
|
||||||
p := new(uint)
|
|
||||||
f.UintVarP(p, name, "", value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// UintP is like Uint, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) UintP(name, shorthand string, value uint, usage string) *uint {
|
|
||||||
p := new(uint)
|
|
||||||
f.UintVarP(p, name, shorthand, value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint defines a uint flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a uint variable that stores the value of the flag.
|
|
||||||
func Uint(name string, value uint, usage string) *uint {
|
|
||||||
return CommandLine.UintP(name, "", value, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UintP is like Uint, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func UintP(name, shorthand string, value uint, usage string) *uint {
|
|
||||||
return CommandLine.UintP(name, shorthand, value, usage)
|
|
||||||
}
|
|
88
vendor/github.com/spf13/pflag/uint16.go
generated
vendored
88
vendor/github.com/spf13/pflag/uint16.go
generated
vendored
|
@ -1,88 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import "strconv"
|
|
||||||
|
|
||||||
// -- uint16 value
|
|
||||||
type uint16Value uint16
|
|
||||||
|
|
||||||
func newUint16Value(val uint16, p *uint16) *uint16Value {
|
|
||||||
*p = val
|
|
||||||
return (*uint16Value)(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *uint16Value) Set(s string) error {
|
|
||||||
v, err := strconv.ParseUint(s, 0, 16)
|
|
||||||
*i = uint16Value(v)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *uint16Value) Type() string {
|
|
||||||
return "uint16"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *uint16Value) String() string { return strconv.FormatUint(uint64(*i), 10) }
|
|
||||||
|
|
||||||
func uint16Conv(sval string) (interface{}, error) {
|
|
||||||
v, err := strconv.ParseUint(sval, 0, 16)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return uint16(v), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUint16 return the uint16 value of a flag with the given name
|
|
||||||
func (f *FlagSet) GetUint16(name string) (uint16, error) {
|
|
||||||
val, err := f.getFlagType(name, "uint16", uint16Conv)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return val.(uint16), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint16Var defines a uint flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a uint variable in which to store the value of the flag.
|
|
||||||
func (f *FlagSet) Uint16Var(p *uint16, name string, value uint16, usage string) {
|
|
||||||
f.VarP(newUint16Value(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint16VarP is like Uint16Var, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) Uint16VarP(p *uint16, name, shorthand string, value uint16, usage string) {
|
|
||||||
f.VarP(newUint16Value(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint16Var defines a uint flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a uint variable in which to store the value of the flag.
|
|
||||||
func Uint16Var(p *uint16, name string, value uint16, usage string) {
|
|
||||||
CommandLine.VarP(newUint16Value(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint16VarP is like Uint16Var, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func Uint16VarP(p *uint16, name, shorthand string, value uint16, usage string) {
|
|
||||||
CommandLine.VarP(newUint16Value(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint16 defines a uint flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a uint variable that stores the value of the flag.
|
|
||||||
func (f *FlagSet) Uint16(name string, value uint16, usage string) *uint16 {
|
|
||||||
p := new(uint16)
|
|
||||||
f.Uint16VarP(p, name, "", value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint16P is like Uint16, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) Uint16P(name, shorthand string, value uint16, usage string) *uint16 {
|
|
||||||
p := new(uint16)
|
|
||||||
f.Uint16VarP(p, name, shorthand, value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint16 defines a uint flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a uint variable that stores the value of the flag.
|
|
||||||
func Uint16(name string, value uint16, usage string) *uint16 {
|
|
||||||
return CommandLine.Uint16P(name, "", value, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint16P is like Uint16, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func Uint16P(name, shorthand string, value uint16, usage string) *uint16 {
|
|
||||||
return CommandLine.Uint16P(name, shorthand, value, usage)
|
|
||||||
}
|
|
88
vendor/github.com/spf13/pflag/uint32.go
generated
vendored
88
vendor/github.com/spf13/pflag/uint32.go
generated
vendored
|
@ -1,88 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import "strconv"
|
|
||||||
|
|
||||||
// -- uint32 value
|
|
||||||
type uint32Value uint32
|
|
||||||
|
|
||||||
func newUint32Value(val uint32, p *uint32) *uint32Value {
|
|
||||||
*p = val
|
|
||||||
return (*uint32Value)(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *uint32Value) Set(s string) error {
|
|
||||||
v, err := strconv.ParseUint(s, 0, 32)
|
|
||||||
*i = uint32Value(v)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *uint32Value) Type() string {
|
|
||||||
return "uint32"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *uint32Value) String() string { return strconv.FormatUint(uint64(*i), 10) }
|
|
||||||
|
|
||||||
func uint32Conv(sval string) (interface{}, error) {
|
|
||||||
v, err := strconv.ParseUint(sval, 0, 32)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return uint32(v), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUint32 return the uint32 value of a flag with the given name
|
|
||||||
func (f *FlagSet) GetUint32(name string) (uint32, error) {
|
|
||||||
val, err := f.getFlagType(name, "uint32", uint32Conv)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return val.(uint32), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint32Var defines a uint32 flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a uint32 variable in which to store the value of the flag.
|
|
||||||
func (f *FlagSet) Uint32Var(p *uint32, name string, value uint32, usage string) {
|
|
||||||
f.VarP(newUint32Value(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint32VarP is like Uint32Var, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) Uint32VarP(p *uint32, name, shorthand string, value uint32, usage string) {
|
|
||||||
f.VarP(newUint32Value(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint32Var defines a uint32 flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a uint32 variable in which to store the value of the flag.
|
|
||||||
func Uint32Var(p *uint32, name string, value uint32, usage string) {
|
|
||||||
CommandLine.VarP(newUint32Value(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint32VarP is like Uint32Var, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func Uint32VarP(p *uint32, name, shorthand string, value uint32, usage string) {
|
|
||||||
CommandLine.VarP(newUint32Value(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint32 defines a uint32 flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a uint32 variable that stores the value of the flag.
|
|
||||||
func (f *FlagSet) Uint32(name string, value uint32, usage string) *uint32 {
|
|
||||||
p := new(uint32)
|
|
||||||
f.Uint32VarP(p, name, "", value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint32P is like Uint32, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) Uint32P(name, shorthand string, value uint32, usage string) *uint32 {
|
|
||||||
p := new(uint32)
|
|
||||||
f.Uint32VarP(p, name, shorthand, value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint32 defines a uint32 flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a uint32 variable that stores the value of the flag.
|
|
||||||
func Uint32(name string, value uint32, usage string) *uint32 {
|
|
||||||
return CommandLine.Uint32P(name, "", value, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint32P is like Uint32, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func Uint32P(name, shorthand string, value uint32, usage string) *uint32 {
|
|
||||||
return CommandLine.Uint32P(name, shorthand, value, usage)
|
|
||||||
}
|
|
88
vendor/github.com/spf13/pflag/uint64.go
generated
vendored
88
vendor/github.com/spf13/pflag/uint64.go
generated
vendored
|
@ -1,88 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import "strconv"
|
|
||||||
|
|
||||||
// -- uint64 Value
|
|
||||||
type uint64Value uint64
|
|
||||||
|
|
||||||
func newUint64Value(val uint64, p *uint64) *uint64Value {
|
|
||||||
*p = val
|
|
||||||
return (*uint64Value)(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *uint64Value) Set(s string) error {
|
|
||||||
v, err := strconv.ParseUint(s, 0, 64)
|
|
||||||
*i = uint64Value(v)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *uint64Value) Type() string {
|
|
||||||
return "uint64"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *uint64Value) String() string { return strconv.FormatUint(uint64(*i), 10) }
|
|
||||||
|
|
||||||
func uint64Conv(sval string) (interface{}, error) {
|
|
||||||
v, err := strconv.ParseUint(sval, 0, 64)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return uint64(v), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUint64 return the uint64 value of a flag with the given name
|
|
||||||
func (f *FlagSet) GetUint64(name string) (uint64, error) {
|
|
||||||
val, err := f.getFlagType(name, "uint64", uint64Conv)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return val.(uint64), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint64Var defines a uint64 flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a uint64 variable in which to store the value of the flag.
|
|
||||||
func (f *FlagSet) Uint64Var(p *uint64, name string, value uint64, usage string) {
|
|
||||||
f.VarP(newUint64Value(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint64VarP is like Uint64Var, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) Uint64VarP(p *uint64, name, shorthand string, value uint64, usage string) {
|
|
||||||
f.VarP(newUint64Value(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint64Var defines a uint64 flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a uint64 variable in which to store the value of the flag.
|
|
||||||
func Uint64Var(p *uint64, name string, value uint64, usage string) {
|
|
||||||
CommandLine.VarP(newUint64Value(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint64VarP is like Uint64Var, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func Uint64VarP(p *uint64, name, shorthand string, value uint64, usage string) {
|
|
||||||
CommandLine.VarP(newUint64Value(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint64 defines a uint64 flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a uint64 variable that stores the value of the flag.
|
|
||||||
func (f *FlagSet) Uint64(name string, value uint64, usage string) *uint64 {
|
|
||||||
p := new(uint64)
|
|
||||||
f.Uint64VarP(p, name, "", value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint64P is like Uint64, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) Uint64P(name, shorthand string, value uint64, usage string) *uint64 {
|
|
||||||
p := new(uint64)
|
|
||||||
f.Uint64VarP(p, name, shorthand, value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint64 defines a uint64 flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a uint64 variable that stores the value of the flag.
|
|
||||||
func Uint64(name string, value uint64, usage string) *uint64 {
|
|
||||||
return CommandLine.Uint64P(name, "", value, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint64P is like Uint64, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func Uint64P(name, shorthand string, value uint64, usage string) *uint64 {
|
|
||||||
return CommandLine.Uint64P(name, shorthand, value, usage)
|
|
||||||
}
|
|
88
vendor/github.com/spf13/pflag/uint8.go
generated
vendored
88
vendor/github.com/spf13/pflag/uint8.go
generated
vendored
|
@ -1,88 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import "strconv"
|
|
||||||
|
|
||||||
// -- uint8 Value
|
|
||||||
type uint8Value uint8
|
|
||||||
|
|
||||||
func newUint8Value(val uint8, p *uint8) *uint8Value {
|
|
||||||
*p = val
|
|
||||||
return (*uint8Value)(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *uint8Value) Set(s string) error {
|
|
||||||
v, err := strconv.ParseUint(s, 0, 8)
|
|
||||||
*i = uint8Value(v)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *uint8Value) Type() string {
|
|
||||||
return "uint8"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *uint8Value) String() string { return strconv.FormatUint(uint64(*i), 10) }
|
|
||||||
|
|
||||||
func uint8Conv(sval string) (interface{}, error) {
|
|
||||||
v, err := strconv.ParseUint(sval, 0, 8)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return uint8(v), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUint8 return the uint8 value of a flag with the given name
|
|
||||||
func (f *FlagSet) GetUint8(name string) (uint8, error) {
|
|
||||||
val, err := f.getFlagType(name, "uint8", uint8Conv)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return val.(uint8), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint8Var defines a uint8 flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a uint8 variable in which to store the value of the flag.
|
|
||||||
func (f *FlagSet) Uint8Var(p *uint8, name string, value uint8, usage string) {
|
|
||||||
f.VarP(newUint8Value(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint8VarP is like Uint8Var, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) Uint8VarP(p *uint8, name, shorthand string, value uint8, usage string) {
|
|
||||||
f.VarP(newUint8Value(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint8Var defines a uint8 flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a uint8 variable in which to store the value of the flag.
|
|
||||||
func Uint8Var(p *uint8, name string, value uint8, usage string) {
|
|
||||||
CommandLine.VarP(newUint8Value(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint8VarP is like Uint8Var, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func Uint8VarP(p *uint8, name, shorthand string, value uint8, usage string) {
|
|
||||||
CommandLine.VarP(newUint8Value(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint8 defines a uint8 flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a uint8 variable that stores the value of the flag.
|
|
||||||
func (f *FlagSet) Uint8(name string, value uint8, usage string) *uint8 {
|
|
||||||
p := new(uint8)
|
|
||||||
f.Uint8VarP(p, name, "", value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint8P is like Uint8, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) Uint8P(name, shorthand string, value uint8, usage string) *uint8 {
|
|
||||||
p := new(uint8)
|
|
||||||
f.Uint8VarP(p, name, shorthand, value, usage)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint8 defines a uint8 flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a uint8 variable that stores the value of the flag.
|
|
||||||
func Uint8(name string, value uint8, usage string) *uint8 {
|
|
||||||
return CommandLine.Uint8P(name, "", value, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint8P is like Uint8, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func Uint8P(name, shorthand string, value uint8, usage string) *uint8 {
|
|
||||||
return CommandLine.Uint8P(name, shorthand, value, usage)
|
|
||||||
}
|
|
126
vendor/github.com/spf13/pflag/uint_slice.go
generated
vendored
126
vendor/github.com/spf13/pflag/uint_slice.go
generated
vendored
|
@ -1,126 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// -- uintSlice Value
|
|
||||||
type uintSliceValue struct {
|
|
||||||
value *[]uint
|
|
||||||
changed bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func newUintSliceValue(val []uint, p *[]uint) *uintSliceValue {
|
|
||||||
uisv := new(uintSliceValue)
|
|
||||||
uisv.value = p
|
|
||||||
*uisv.value = val
|
|
||||||
return uisv
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *uintSliceValue) Set(val string) error {
|
|
||||||
ss := strings.Split(val, ",")
|
|
||||||
out := make([]uint, len(ss))
|
|
||||||
for i, d := range ss {
|
|
||||||
u, err := strconv.ParseUint(d, 10, 0)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
out[i] = uint(u)
|
|
||||||
}
|
|
||||||
if !s.changed {
|
|
||||||
*s.value = out
|
|
||||||
} else {
|
|
||||||
*s.value = append(*s.value, out...)
|
|
||||||
}
|
|
||||||
s.changed = true
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *uintSliceValue) Type() string {
|
|
||||||
return "uintSlice"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *uintSliceValue) String() string {
|
|
||||||
out := make([]string, len(*s.value))
|
|
||||||
for i, d := range *s.value {
|
|
||||||
out[i] = fmt.Sprintf("%d", d)
|
|
||||||
}
|
|
||||||
return "[" + strings.Join(out, ",") + "]"
|
|
||||||
}
|
|
||||||
|
|
||||||
func uintSliceConv(val string) (interface{}, error) {
|
|
||||||
val = strings.Trim(val, "[]")
|
|
||||||
// Empty string would cause a slice with one (empty) entry
|
|
||||||
if len(val) == 0 {
|
|
||||||
return []uint{}, nil
|
|
||||||
}
|
|
||||||
ss := strings.Split(val, ",")
|
|
||||||
out := make([]uint, len(ss))
|
|
||||||
for i, d := range ss {
|
|
||||||
u, err := strconv.ParseUint(d, 10, 0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
out[i] = uint(u)
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUintSlice returns the []uint value of a flag with the given name.
|
|
||||||
func (f *FlagSet) GetUintSlice(name string) ([]uint, error) {
|
|
||||||
val, err := f.getFlagType(name, "uintSlice", uintSliceConv)
|
|
||||||
if err != nil {
|
|
||||||
return []uint{}, err
|
|
||||||
}
|
|
||||||
return val.([]uint), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UintSliceVar defines a uintSlice flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a []uint variable in which to store the value of the flag.
|
|
||||||
func (f *FlagSet) UintSliceVar(p *[]uint, name string, value []uint, usage string) {
|
|
||||||
f.VarP(newUintSliceValue(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UintSliceVarP is like UintSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) UintSliceVarP(p *[]uint, name, shorthand string, value []uint, usage string) {
|
|
||||||
f.VarP(newUintSliceValue(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UintSliceVar defines a uint[] flag with specified name, default value, and usage string.
|
|
||||||
// The argument p points to a uint[] variable in which to store the value of the flag.
|
|
||||||
func UintSliceVar(p *[]uint, name string, value []uint, usage string) {
|
|
||||||
CommandLine.VarP(newUintSliceValue(value, p), name, "", usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UintSliceVarP is like the UintSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func UintSliceVarP(p *[]uint, name, shorthand string, value []uint, usage string) {
|
|
||||||
CommandLine.VarP(newUintSliceValue(value, p), name, shorthand, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UintSlice defines a []uint flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a []uint variable that stores the value of the flag.
|
|
||||||
func (f *FlagSet) UintSlice(name string, value []uint, usage string) *[]uint {
|
|
||||||
p := []uint{}
|
|
||||||
f.UintSliceVarP(&p, name, "", value, usage)
|
|
||||||
return &p
|
|
||||||
}
|
|
||||||
|
|
||||||
// UintSliceP is like UintSlice, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func (f *FlagSet) UintSliceP(name, shorthand string, value []uint, usage string) *[]uint {
|
|
||||||
p := []uint{}
|
|
||||||
f.UintSliceVarP(&p, name, shorthand, value, usage)
|
|
||||||
return &p
|
|
||||||
}
|
|
||||||
|
|
||||||
// UintSlice defines a []uint flag with specified name, default value, and usage string.
|
|
||||||
// The return value is the address of a []uint variable that stores the value of the flag.
|
|
||||||
func UintSlice(name string, value []uint, usage string) *[]uint {
|
|
||||||
return CommandLine.UintSliceP(name, "", value, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UintSliceP is like UintSlice, but accepts a shorthand letter that can be used after a single dash.
|
|
||||||
func UintSliceP(name, shorthand string, value []uint, usage string) *[]uint {
|
|
||||||
return CommandLine.UintSliceP(name, shorthand, value, usage)
|
|
||||||
}
|
|
161
vendor/github.com/spf13/pflag/uint_slice_test.go
generated
vendored
161
vendor/github.com/spf13/pflag/uint_slice_test.go
generated
vendored
|
@ -1,161 +0,0 @@
|
||||||
package pflag
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func setUpUISFlagSet(uisp *[]uint) *FlagSet {
|
|
||||||
f := NewFlagSet("test", ContinueOnError)
|
|
||||||
f.UintSliceVar(uisp, "uis", []uint{}, "Command separated list!")
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func setUpUISFlagSetWithDefault(uisp *[]uint) *FlagSet {
|
|
||||||
f := NewFlagSet("test", ContinueOnError)
|
|
||||||
f.UintSliceVar(uisp, "uis", []uint{0, 1}, "Command separated list!")
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEmptyUIS(t *testing.T) {
|
|
||||||
var uis []uint
|
|
||||||
f := setUpUISFlagSet(&uis)
|
|
||||||
err := f.Parse([]string{})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
getUIS, err := f.GetUintSlice("uis")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("got an error from GetUintSlice():", err)
|
|
||||||
}
|
|
||||||
if len(getUIS) != 0 {
|
|
||||||
t.Fatalf("got is %v with len=%d but expected length=0", getUIS, len(getUIS))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUIS(t *testing.T) {
|
|
||||||
var uis []uint
|
|
||||||
f := setUpUISFlagSet(&uis)
|
|
||||||
|
|
||||||
vals := []string{"1", "2", "4", "3"}
|
|
||||||
arg := fmt.Sprintf("--uis=%s", strings.Join(vals, ","))
|
|
||||||
err := f.Parse([]string{arg})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
for i, v := range uis {
|
|
||||||
u, err := strconv.ParseUint(vals[i], 10, 0)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("got error: %v", err)
|
|
||||||
}
|
|
||||||
if uint(u) != v {
|
|
||||||
t.Fatalf("expected uis[%d] to be %s but got %d", i, vals[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
getUIS, err := f.GetUintSlice("uis")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("got error: %v", err)
|
|
||||||
}
|
|
||||||
for i, v := range getUIS {
|
|
||||||
u, err := strconv.ParseUint(vals[i], 10, 0)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("got error: %v", err)
|
|
||||||
}
|
|
||||||
if uint(u) != v {
|
|
||||||
t.Fatalf("expected uis[%d] to be %s but got: %d from GetUintSlice", i, vals[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUISDefault(t *testing.T) {
|
|
||||||
var uis []uint
|
|
||||||
f := setUpUISFlagSetWithDefault(&uis)
|
|
||||||
|
|
||||||
vals := []string{"0", "1"}
|
|
||||||
|
|
||||||
err := f.Parse([]string{})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
for i, v := range uis {
|
|
||||||
u, err := strconv.ParseUint(vals[i], 10, 0)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("got error: %v", err)
|
|
||||||
}
|
|
||||||
if uint(u) != v {
|
|
||||||
t.Fatalf("expect uis[%d] to be %d but got: %d", i, u, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getUIS, err := f.GetUintSlice("uis")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("got an error from GetUintSlice():", err)
|
|
||||||
}
|
|
||||||
for i, v := range getUIS {
|
|
||||||
u, err := strconv.ParseUint(vals[i], 10, 0)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("got an error from GetIntSlice():", err)
|
|
||||||
}
|
|
||||||
if uint(u) != v {
|
|
||||||
t.Fatalf("expected uis[%d] to be %d from GetUintSlice but got: %d", i, u, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUISWithDefault(t *testing.T) {
|
|
||||||
var uis []uint
|
|
||||||
f := setUpUISFlagSetWithDefault(&uis)
|
|
||||||
|
|
||||||
vals := []string{"1", "2"}
|
|
||||||
arg := fmt.Sprintf("--uis=%s", strings.Join(vals, ","))
|
|
||||||
err := f.Parse([]string{arg})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
for i, v := range uis {
|
|
||||||
u, err := strconv.ParseUint(vals[i], 10, 0)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("got error: %v", err)
|
|
||||||
}
|
|
||||||
if uint(u) != v {
|
|
||||||
t.Fatalf("expected uis[%d] to be %d from GetUintSlice but got: %d", i, u, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getUIS, err := f.GetUintSlice("uis")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("got an error from GetUintSlice():", err)
|
|
||||||
}
|
|
||||||
for i, v := range getUIS {
|
|
||||||
u, err := strconv.ParseUint(vals[i], 10, 0)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("got error: %v", err)
|
|
||||||
}
|
|
||||||
if uint(u) != v {
|
|
||||||
t.Fatalf("expected uis[%d] to be %d from GetUintSlice but got: %d", i, u, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUISCalledTwice(t *testing.T) {
|
|
||||||
var uis []uint
|
|
||||||
f := setUpUISFlagSet(&uis)
|
|
||||||
|
|
||||||
in := []string{"1,2", "3"}
|
|
||||||
expected := []int{1, 2, 3}
|
|
||||||
argfmt := "--uis=%s"
|
|
||||||
arg1 := fmt.Sprintf(argfmt, in[0])
|
|
||||||
arg2 := fmt.Sprintf(argfmt, in[1])
|
|
||||||
err := f.Parse([]string{arg1, arg2})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected no error; got", err)
|
|
||||||
}
|
|
||||||
for i, v := range uis {
|
|
||||||
if uint(expected[i]) != v {
|
|
||||||
t.Fatalf("expected uis[%d] to be %d but got: %d", i, expected[i], v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
69
vendor/github.com/spf13/pflag/verify/all.sh
generated
vendored
69
vendor/github.com/spf13/pflag/verify/all.sh
generated
vendored
|
@ -1,69 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -o errexit
|
|
||||||
set -o nounset
|
|
||||||
set -o pipefail
|
|
||||||
|
|
||||||
ROOT=$(dirname "${BASH_SOURCE}")/..
|
|
||||||
|
|
||||||
# Some useful colors.
|
|
||||||
if [[ -z "${color_start-}" ]]; then
|
|
||||||
declare -r color_start="\033["
|
|
||||||
declare -r color_red="${color_start}0;31m"
|
|
||||||
declare -r color_yellow="${color_start}0;33m"
|
|
||||||
declare -r color_green="${color_start}0;32m"
|
|
||||||
declare -r color_norm="${color_start}0m"
|
|
||||||
fi
|
|
||||||
|
|
||||||
SILENT=true
|
|
||||||
|
|
||||||
function is-excluded {
|
|
||||||
for e in $EXCLUDE; do
|
|
||||||
if [[ $1 -ef ${BASH_SOURCE} ]]; then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
if [[ $1 -ef "$ROOT/hack/$e" ]]; then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
while getopts ":v" opt; do
|
|
||||||
case $opt in
|
|
||||||
v)
|
|
||||||
SILENT=false
|
|
||||||
;;
|
|
||||||
\?)
|
|
||||||
echo "Invalid flag: -$OPTARG" >&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
if $SILENT ; then
|
|
||||||
echo "Running in the silent mode, run with -v if you want to see script logs."
|
|
||||||
fi
|
|
||||||
|
|
||||||
EXCLUDE="all.sh"
|
|
||||||
|
|
||||||
ret=0
|
|
||||||
for t in `ls $ROOT/verify/*.sh`
|
|
||||||
do
|
|
||||||
if is-excluded $t ; then
|
|
||||||
echo "Skipping $t"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
if $SILENT ; then
|
|
||||||
echo -e "Verifying $t"
|
|
||||||
if bash "$t" &> /dev/null; then
|
|
||||||
echo -e "${color_green}SUCCESS${color_norm}"
|
|
||||||
else
|
|
||||||
echo -e "${color_red}FAILED${color_norm}"
|
|
||||||
ret=1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
bash "$t" || ret=1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
exit $ret
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue