├── cmd
└── assh
│ ├── main_test.go
│ └── main.go
├── .godir
├── pkg
├── config
│ ├── utils_test.go
│ ├── utils.go
│ ├── host_test.go
│ ├── host.go
│ ├── config_test.go
│ └── config.go
├── commands
│ ├── proxy_test.go
│ ├── stats_test.go
│ ├── commands_test.go
│ ├── stats.go
│ ├── commands.go
│ └── proxy.go
└── version
│ ├── version_test.go
│ └── version.go
├── .gitignore
├── vendor
├── github.com
│ ├── flynn
│ │ └── go-shlex
│ │ │ ├── README.md
│ │ │ ├── Makefile
│ │ │ └── shlex_test.go
│ ├── Sirupsen
│ │ └── logrus
│ │ │ ├── terminal_bsd.go
│ │ │ ├── terminal_linux.go
│ │ │ ├── terminal_notwindows.go
│ │ │ ├── writer.go
│ │ │ ├── terminal_windows.go
│ │ │ ├── CHANGELOG.md
│ │ │ ├── json_formatter.go
│ │ │ ├── LICENSE
│ │ │ ├── hooks.go
│ │ │ ├── entry_test.go
│ │ │ ├── formatter.go
│ │ │ ├── text_formatter_test.go
│ │ │ ├── formatter_bench_test.go
│ │ │ ├── logrus.go
│ │ │ ├── hook_test.go
│ │ │ ├── json_formatter_test.go
│ │ │ ├── text_formatter.go
│ │ │ ├── exported.go
│ │ │ ├── logger.go
│ │ │ ├── entry.go
│ │ │ └── logrus_test.go
│ ├── stretchr
│ │ └── testify
│ │ │ └── assert
│ │ │ ├── errors.go
│ │ │ ├── http_assertions_test.go
│ │ │ ├── doc.go
│ │ │ ├── http_assertions.go
│ │ │ └── forward_assertions.go
│ └── codegangsta
│ │ └── cli
│ │ ├── helpers_test.go
│ │ ├── help_test.go
│ │ ├── cli.go
│ │ ├── LICENSE
│ │ ├── command_test.go
│ │ ├── cli_test.go
│ │ ├── context_test.go
│ │ ├── command.go
│ │ ├── help.go
│ │ ├── app.go
│ │ ├── README.md
│ │ └── context.go
└── gopkg.in
│ └── yaml.v2
│ ├── suite_test.go
│ ├── LICENSE.libyaml
│ ├── writerc.go
│ ├── sorter.go
│ ├── README.md
│ ├── yamlprivateh.go
│ ├── resolve.go
│ ├── encode.go
│ ├── LICENSE
│ └── yaml.go
├── README.md
├── .travis.yml
└── Makefile
/cmd/assh/main_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
--------------------------------------------------------------------------------
/.godir:
--------------------------------------------------------------------------------
1 | github.com/moul/advanced-ssh-config
--------------------------------------------------------------------------------
/pkg/config/utils_test.go:
--------------------------------------------------------------------------------
1 | package config
2 |
--------------------------------------------------------------------------------
/pkg/commands/proxy_test.go:
--------------------------------------------------------------------------------
1 | package commands
2 |
--------------------------------------------------------------------------------
/pkg/commands/stats_test.go:
--------------------------------------------------------------------------------
1 | package commands
2 |
--------------------------------------------------------------------------------
/pkg/version/version_test.go:
--------------------------------------------------------------------------------
1 | package version
2 |
--------------------------------------------------------------------------------
/pkg/commands/commands_test.go:
--------------------------------------------------------------------------------
1 | package commands
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /advanced-ssh-config
2 | /assh
3 | /cmd/assh/assh
4 | profile.out
--------------------------------------------------------------------------------
/vendor/github.com/flynn/go-shlex/README.md:
--------------------------------------------------------------------------------
1 | go-shlex is a simple lexer for go that supports shell-style quoting,
2 | commenting, and escaping.
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Advanced SSH config
2 | ===================
3 |
4 | Golang version of [advanced-ssh-config](https://github.com/moul/advanced-ssh-config) (Python).
5 |
6 | ## License
7 |
8 | © 2009-2015 Manfred Touron - MIT License
9 |
--------------------------------------------------------------------------------
/vendor/github.com/Sirupsen/logrus/terminal_bsd.go:
--------------------------------------------------------------------------------
1 | // +build darwin freebsd openbsd netbsd dragonfly
2 |
3 | package logrus
4 |
5 | import "syscall"
6 |
7 | const ioctlReadTermios = syscall.TIOCGETA
8 |
9 | type Termios syscall.Termios
10 |
--------------------------------------------------------------------------------
/pkg/version/version.go:
--------------------------------------------------------------------------------
1 | package version
2 |
3 | var (
4 | // Version should be updated by hand at each release
5 | Version = "2.0.0-dev"
6 |
7 | // GitCommit will be overwritten automatically by the build system
8 | GitCommit = "HEAD"
9 | )
10 |
--------------------------------------------------------------------------------
/vendor/gopkg.in/yaml.v2/suite_test.go:
--------------------------------------------------------------------------------
1 | package yaml_test
2 |
3 | import (
4 | . "github.com/moul/advanced-ssh-config/vendor/gopkg.in/check.v1"
5 | "testing"
6 | )
7 |
8 | func Test(t *testing.T) { TestingT(t) }
9 |
10 | type S struct{}
11 |
12 | var _ = Suite(&S{})
13 |
--------------------------------------------------------------------------------
/vendor/github.com/Sirupsen/logrus/terminal_linux.go:
--------------------------------------------------------------------------------
1 | // Based on ssh/terminal:
2 | // Copyright 2013 The Go Authors. All rights reserved.
3 | // Use of this source code is governed by a BSD-style
4 | // license that can be found in the LICENSE file.
5 |
6 | package logrus
7 |
8 | import "syscall"
9 |
10 | const ioctlReadTermios = syscall.TCGETS
11 |
12 | type Termios syscall.Termios
13 |
--------------------------------------------------------------------------------
/pkg/commands/stats.go:
--------------------------------------------------------------------------------
1 | package commands
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/moul/advanced-ssh-config/vendor/github.com/codegangsta/cli"
7 |
8 | "github.com/moul/advanced-ssh-config/pkg/config"
9 | )
10 |
11 | func cmdStats(c *cli.Context) {
12 | conf, err := config.Open()
13 | if err != nil {
14 | panic(err)
15 | }
16 |
17 | fmt.Printf("%d hosts\n", len(conf.Hosts))
18 | }
19 |
--------------------------------------------------------------------------------
/vendor/github.com/stretchr/testify/assert/errors.go:
--------------------------------------------------------------------------------
1 | package assert
2 |
3 | import (
4 | "errors"
5 | )
6 |
7 | // AnError is an error instance useful for testing. If the code does not care
8 | // about error specifics, and only needs to return the error for example, this
9 | // error should be used to make the test code more readable.
10 | var AnError = errors.New("assert.AnError general error for testing")
11 |
--------------------------------------------------------------------------------
/pkg/config/utils.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import (
4 | "errors"
5 | "os"
6 | "strings"
7 | )
8 |
9 | func expandUser(path string) (string, error) {
10 | if path[:2] == "~/" {
11 | homeDir := os.Getenv("HOME") // *nix
12 | if homeDir == "" { // Windows
13 | homeDir = os.Getenv("USERPROFILE")
14 | }
15 | if homeDir == "" {
16 | return "", errors.New("user home directory not found")
17 | }
18 |
19 | return strings.Replace(path, "~", homeDir, 1), nil
20 | }
21 | return path, nil
22 | }
23 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: go
2 |
3 | go:
4 | - 1.3
5 | - 1.4
6 | - tip
7 |
8 | before_install:
9 | - go get -u github.com/axw/gocov/gocov
10 | - go get -u github.com/mattn/goveralls
11 | - go get golang.org/x/tools/cmd/cover
12 |
13 | matrix:
14 | allow_failures:
15 | - go: tip
16 |
17 | install:
18 | - go get -d -v ./...
19 |
20 | script:
21 | - go build -v $(go list ./... | grep -v vendor)
22 | - go test -v $(go list ./... | grep -v vendor)
23 | - make cover
24 | - goveralls -service=travis-ci -v -coverprofile=profile.out
--------------------------------------------------------------------------------
/vendor/github.com/codegangsta/cli/helpers_test.go:
--------------------------------------------------------------------------------
1 | package cli_test
2 |
3 | import (
4 | "reflect"
5 | "testing"
6 | )
7 |
8 | /* Test Helpers */
9 | func expect(t *testing.T, a interface{}, b interface{}) {
10 | if a != b {
11 | t.Errorf("Expected %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
12 | }
13 | }
14 |
15 | func refute(t *testing.T, a interface{}, b interface{}) {
16 | if a == b {
17 | t.Errorf("Did not expect %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/vendor/github.com/Sirupsen/logrus/terminal_notwindows.go:
--------------------------------------------------------------------------------
1 | // Based on ssh/terminal:
2 | // Copyright 2011 The Go Authors. All rights reserved.
3 | // Use of this source code is governed by a BSD-style
4 | // license that can be found in the LICENSE file.
5 |
6 | // +build linux darwin freebsd openbsd netbsd dragonfly
7 |
8 | package logrus
9 |
10 | import (
11 | "syscall"
12 | "unsafe"
13 | )
14 |
15 | // IsTerminal returns true if the given file descriptor is a terminal.
16 | func IsTerminal() bool {
17 | fd := syscall.Stdout
18 | var termios Termios
19 | _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
20 | return err == 0
21 | }
22 |
--------------------------------------------------------------------------------
/vendor/github.com/Sirupsen/logrus/writer.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | import (
4 | "bufio"
5 | "io"
6 | "runtime"
7 | )
8 |
9 | func (logger *Logger) Writer() *io.PipeWriter {
10 | reader, writer := io.Pipe()
11 |
12 | go logger.writerScanner(reader)
13 | runtime.SetFinalizer(writer, writerFinalizer)
14 |
15 | return writer
16 | }
17 |
18 | func (logger *Logger) writerScanner(reader *io.PipeReader) {
19 | scanner := bufio.NewScanner(reader)
20 | for scanner.Scan() {
21 | logger.Print(scanner.Text())
22 | }
23 | if err := scanner.Err(); err != nil {
24 | logger.Errorf("Error while reading from Writer: %s", err)
25 | }
26 | reader.Close()
27 | }
28 |
29 | func writerFinalizer(writer *io.PipeWriter) {
30 | writer.Close()
31 | }
32 |
--------------------------------------------------------------------------------
/vendor/github.com/Sirupsen/logrus/terminal_windows.go:
--------------------------------------------------------------------------------
1 | // Based on ssh/terminal:
2 | // Copyright 2011 The Go Authors. All rights reserved.
3 | // Use of this source code is governed by a BSD-style
4 | // license that can be found in the LICENSE file.
5 |
6 | // +build windows
7 |
8 | package logrus
9 |
10 | import (
11 | "syscall"
12 | "unsafe"
13 | )
14 |
15 | var kernel32 = syscall.NewLazyDLL("kernel32.dll")
16 |
17 | var (
18 | procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
19 | )
20 |
21 | // IsTerminal returns true if the given file descriptor is a terminal.
22 | func IsTerminal() bool {
23 | fd := syscall.Stdout
24 | var st uint32
25 | r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
26 | return r != 0 && e == 0
27 | }
28 |
--------------------------------------------------------------------------------
/vendor/github.com/flynn/go-shlex/Makefile:
--------------------------------------------------------------------------------
1 | # Copyright 2011 Google Inc. All Rights Reserved.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | include $(GOROOT)/src/Make.inc
16 |
17 | TARG=shlex
18 | GOFILES=\
19 | shlex.go\
20 |
21 | include $(GOROOT)/src/Make.pkg
22 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | PACKAGES := $(addprefix ./,$(wildcard pkg/*))
2 | COMMANDS := $(addprefix ./,$(wildcard cmd/*))
3 |
4 | all: build
5 |
6 | build:
7 | go get ./...
8 | gofmt -w $(PACKAGES) $(COMMANDS)
9 | go test -i $(PACKAGES) $(COMMANDS)
10 | for command in $(COMMANDS); do \
11 | go build -o `basename $$command` $$command; \
12 | done
13 |
14 | test:
15 | go get ./...
16 | go test -i $(PACKAGES) $(COMMANDS)
17 | go test -v $(PACKAGES) $(COMMANDS)
18 |
19 | install:
20 | go install $(COMMANDS)
21 |
22 | cover:
23 | rm -f profile.out file-profile.out
24 | for package in $(PACKAGES); do \
25 | go test -coverprofile=file-profile.out $$package; \
26 | if [ -f file-profile.out ]; then cat file-profile.out | grep -v "mode: set" >> profile.out || true; rm -f file-profile.out; fi \
27 | done
28 | echo "mode: set" | cat - profile.out > profile.out.tmp && mv profile.out.tmp profile.out
29 |
--------------------------------------------------------------------------------
/vendor/github.com/codegangsta/cli/help_test.go:
--------------------------------------------------------------------------------
1 | package cli_test
2 |
3 | import (
4 | "bytes"
5 | "testing"
6 |
7 | "github.com/moul/advanced-ssh-config/vendor/github.com/codegangsta/cli"
8 | )
9 |
10 | func Test_ShowAppHelp_NoAuthor(t *testing.T) {
11 | output := new(bytes.Buffer)
12 | app := cli.NewApp()
13 | app.Writer = output
14 |
15 | c := cli.NewContext(app, nil, nil)
16 |
17 | cli.ShowAppHelp(c)
18 |
19 | if bytes.Index(output.Bytes(), []byte("AUTHOR(S):")) != -1 {
20 | t.Errorf("expected\n%snot to include %s", output.String(), "AUTHOR(S):")
21 | }
22 | }
23 |
24 | func Test_ShowAppHelp_NoVersion(t *testing.T) {
25 | output := new(bytes.Buffer)
26 | app := cli.NewApp()
27 | app.Writer = output
28 |
29 | app.Version = ""
30 |
31 | c := cli.NewContext(app, nil, nil)
32 |
33 | cli.ShowAppHelp(c)
34 |
35 | if bytes.Index(output.Bytes(), []byte("VERSION:")) != -1 {
36 | t.Errorf("expected\n%snot to include %s", output.String(), "VERSION:")
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/vendor/github.com/Sirupsen/logrus/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # 0.8.6
2 |
3 | * hooks/raven: allow passing an initialized client
4 |
5 | # 0.8.5
6 |
7 | * logrus/core: revert #208
8 |
9 | # 0.8.4
10 |
11 | * formatter/text: fix data race (#218)
12 |
13 | # 0.8.3
14 |
15 | * logrus/core: fix entry log level (#208)
16 | * logrus/core: improve performance of text formatter by 40%
17 | * logrus/core: expose `LevelHooks` type
18 | * logrus/core: add support for DragonflyBSD and NetBSD
19 | * formatter/text: print structs more verbosely
20 |
21 | # 0.8.2
22 |
23 | * logrus: fix more Fatal family functions
24 |
25 | # 0.8.1
26 |
27 | * logrus: fix not exiting on `Fatalf` and `Fatalln`
28 |
29 | # 0.8.0
30 |
31 | * logrus: defaults to stderr instead of stdout
32 | * hooks/sentry: add special field for `*http.Request`
33 | * formatter/text: ignore Windows for colors
34 |
35 | # 0.7.3
36 |
37 | * formatter/\*: allow configuration of timestamp layout
38 |
39 | # 0.7.2
40 |
41 | * formatter/text: Add configuration option for time format (#158)
42 |
--------------------------------------------------------------------------------
/vendor/github.com/codegangsta/cli/cli.go:
--------------------------------------------------------------------------------
1 | // Package cli provides a minimal framework for creating and organizing command line
2 | // Go applications. cli is designed to be easy to understand and write, the most simple
3 | // cli application can be written as follows:
4 | // func main() {
5 | // cli.NewApp().Run(os.Args)
6 | // }
7 | //
8 | // Of course this application does not do much, so let's make this an actual application:
9 | // func main() {
10 | // app := cli.NewApp()
11 | // app.Name = "greet"
12 | // app.Usage = "say a greeting"
13 | // app.Action = func(c *cli.Context) {
14 | // println("Greetings")
15 | // }
16 | //
17 | // app.Run(os.Args)
18 | // }
19 | package cli
20 |
21 | import (
22 | "strings"
23 | )
24 |
25 | type MultiError struct {
26 | Errors []error
27 | }
28 |
29 | func NewMultiError(err ...error) MultiError {
30 | return MultiError{Errors: err}
31 | }
32 |
33 | func (m MultiError) Error() string {
34 | errs := make([]string, len(m.Errors))
35 | for i, err := range m.Errors {
36 | errs[i] = err.Error()
37 | }
38 |
39 | return strings.Join(errs, "\n")
40 | }
41 |
--------------------------------------------------------------------------------
/vendor/github.com/Sirupsen/logrus/json_formatter.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | )
7 |
8 | type JSONFormatter struct {
9 | // TimestampFormat sets the format used for marshaling timestamps.
10 | TimestampFormat string
11 | }
12 |
13 | func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
14 | data := make(Fields, len(entry.Data)+3)
15 | for k, v := range entry.Data {
16 | switch v := v.(type) {
17 | case error:
18 | // Otherwise errors are ignored by `encoding/json`
19 | // https://github.com/Sirupsen/logrus/issues/137
20 | data[k] = v.Error()
21 | default:
22 | data[k] = v
23 | }
24 | }
25 | prefixFieldClashes(data)
26 |
27 | timestampFormat := f.TimestampFormat
28 | if timestampFormat == "" {
29 | timestampFormat = DefaultTimestampFormat
30 | }
31 |
32 | data["time"] = entry.Time.Format(timestampFormat)
33 | data["msg"] = entry.Message
34 | data["level"] = entry.Level.String()
35 |
36 | serialized, err := json.Marshal(data)
37 | if err != nil {
38 | return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
39 | }
40 | return append(serialized, '\n'), nil
41 | }
42 |
--------------------------------------------------------------------------------
/vendor/github.com/Sirupsen/logrus/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Simon Eskildsen
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/vendor/github.com/codegangsta/cli/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (C) 2013 Jeremy Saenz
2 | All Rights Reserved.
3 |
4 | MIT LICENSE
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | this software and associated documentation files (the "Software"), to deal in
8 | the Software without restriction, including without limitation the rights to
9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | the Software, and to permit persons to whom the Software is furnished to do so,
11 | subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/vendor/github.com/Sirupsen/logrus/hooks.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | // A hook to be fired when logging on the logging levels returned from
4 | // `Levels()` on your implementation of the interface. Note that this is not
5 | // fired in a goroutine or a channel with workers, you should handle such
6 | // functionality yourself if your call is non-blocking and you don't wish for
7 | // the logging calls for levels returned from `Levels()` to block.
8 | type Hook interface {
9 | Levels() []Level
10 | Fire(*Entry) error
11 | }
12 |
13 | // Internal type for storing the hooks on a logger instance.
14 | type LevelHooks map[Level][]Hook
15 |
16 | // Add a hook to an instance of logger. This is called with
17 | // `log.Hooks.Add(new(MyHook))` where `MyHook` implements the `Hook` interface.
18 | func (hooks LevelHooks) Add(hook Hook) {
19 | for _, level := range hook.Levels() {
20 | hooks[level] = append(hooks[level], hook)
21 | }
22 | }
23 |
24 | // Fire all the hooks for the passed level. Used by `entry.log` to fire
25 | // appropriate hooks for a log entry.
26 | func (hooks LevelHooks) Fire(level Level, entry *Entry) error {
27 | for _, hook := range hooks[level] {
28 | if err := hook.Fire(entry); err != nil {
29 | return err
30 | }
31 | }
32 |
33 | return nil
34 | }
35 |
--------------------------------------------------------------------------------
/vendor/github.com/codegangsta/cli/command_test.go:
--------------------------------------------------------------------------------
1 | package cli_test
2 |
3 | import (
4 | "flag"
5 | "testing"
6 |
7 | "github.com/moul/advanced-ssh-config/vendor/github.com/codegangsta/cli"
8 | )
9 |
10 | func TestCommandDoNotIgnoreFlags(t *testing.T) {
11 | app := cli.NewApp()
12 | set := flag.NewFlagSet("test", 0)
13 | test := []string{"blah", "blah", "-break"}
14 | set.Parse(test)
15 |
16 | c := cli.NewContext(app, set, nil)
17 |
18 | command := cli.Command{
19 | Name: "test-cmd",
20 | Aliases: []string{"tc"},
21 | Usage: "this is for testing",
22 | Description: "testing",
23 | Action: func(_ *cli.Context) {},
24 | }
25 | err := command.Run(c)
26 |
27 | expect(t, err.Error(), "flag provided but not defined: -break")
28 | }
29 |
30 | func TestCommandIgnoreFlags(t *testing.T) {
31 | app := cli.NewApp()
32 | set := flag.NewFlagSet("test", 0)
33 | test := []string{"blah", "blah"}
34 | set.Parse(test)
35 |
36 | c := cli.NewContext(app, set, nil)
37 |
38 | command := cli.Command{
39 | Name: "test-cmd",
40 | Aliases: []string{"tc"},
41 | Usage: "this is for testing",
42 | Description: "testing",
43 | Action: func(_ *cli.Context) {},
44 | SkipFlagParsing: true,
45 | }
46 | err := command.Run(c)
47 |
48 | expect(t, err, nil)
49 | }
50 |
--------------------------------------------------------------------------------
/cmd/assh/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "os"
5 | "path"
6 |
7 | "github.com/moul/advanced-ssh-config/vendor/github.com/Sirupsen/logrus"
8 | "github.com/moul/advanced-ssh-config/vendor/github.com/codegangsta/cli"
9 |
10 | "github.com/moul/advanced-ssh-config/pkg/commands"
11 | "github.com/moul/advanced-ssh-config/pkg/version"
12 | )
13 |
14 | func main() {
15 | app := cli.NewApp()
16 | app.Name = path.Base(os.Args[0])
17 | app.Author = "Manfred Touron"
18 | app.Email = "https://github.com/moul/advanced-ssh-config"
19 | app.Version = version.Version + " (" + version.GitCommit + ")"
20 | app.Usage = "advanced ssh config"
21 |
22 | app.Flags = []cli.Flag{
23 | cli.BoolFlag{
24 | Name: "debug, D",
25 | Usage: "Enable debug mode",
26 | },
27 | cli.BoolFlag{
28 | Name: "verbose, V",
29 | Usage: "Enable verbose mode",
30 | },
31 | }
32 |
33 | app.Before = hookBefore
34 |
35 | app.Commands = commands.Commands
36 |
37 | app.Run(os.Args)
38 | }
39 |
40 | func hookBefore(c *cli.Context) error {
41 | initLogging(c.Bool("debug"), c.Bool("verbose"))
42 | return nil
43 | }
44 |
45 | func initLogging(debug bool, verbose bool) {
46 | if debug {
47 | logrus.SetLevel(logrus.DebugLevel)
48 | } else if verbose {
49 | logrus.SetLevel(logrus.InfoLevel)
50 | } else {
51 | logrus.SetLevel(logrus.WarnLevel)
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/pkg/config/host_test.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/moul/advanced-ssh-config/vendor/github.com/stretchr/testify/assert"
7 | )
8 |
9 | func TestHostApplyDefaults(t *testing.T) {
10 | host := &Host{
11 | Name: "example",
12 | Host: "example.com",
13 | User: "root",
14 | }
15 | defaults := &Host{
16 | User: "bobby",
17 | Port: 42,
18 | }
19 | host.ApplyDefaults(defaults)
20 | assert.Equal(t, host.Port, uint(42))
21 | assert.Equal(t, host.Name, "example")
22 | assert.Equal(t, host.Host, "example.com")
23 | assert.Equal(t, host.User, "root")
24 | assert.Equal(t, len(host.Gateways), 0)
25 | assert.Equal(t, host.ProxyCommand, "")
26 | assert.Equal(t, len(host.ResolveNameservers), 0)
27 | assert.Equal(t, host.ResolveCommand, "")
28 | assert.Equal(t, host.ControlPath, "")
29 | }
30 |
31 | func TestHostApplyDefaults_empty(t *testing.T) {
32 | host := &Host{}
33 | defaults := &Host{}
34 | host.ApplyDefaults(defaults)
35 | assert.Equal(t, host.Port, uint(22))
36 | assert.Equal(t, host.Name, "")
37 | assert.Equal(t, host.Host, "")
38 | assert.Equal(t, host.User, "")
39 | assert.Equal(t, len(host.Gateways), 0)
40 | assert.Equal(t, host.ProxyCommand, "")
41 | assert.Equal(t, len(host.ResolveNameservers), 0)
42 | assert.Equal(t, host.ResolveCommand, "")
43 | assert.Equal(t, host.ControlPath, "")
44 | }
45 |
--------------------------------------------------------------------------------
/vendor/github.com/Sirupsen/logrus/entry_test.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | import (
4 | "bytes"
5 | "fmt"
6 | "testing"
7 |
8 | "github.com/moul/advanced-ssh-config/vendor/github.com/stretchr/testify/assert"
9 | )
10 |
11 | func TestEntryPanicln(t *testing.T) {
12 | errBoom := fmt.Errorf("boom time")
13 |
14 | defer func() {
15 | p := recover()
16 | assert.NotNil(t, p)
17 |
18 | switch pVal := p.(type) {
19 | case *Entry:
20 | assert.Equal(t, "kaboom", pVal.Message)
21 | assert.Equal(t, errBoom, pVal.Data["err"])
22 | default:
23 | t.Fatalf("want type *Entry, got %T: %#v", pVal, pVal)
24 | }
25 | }()
26 |
27 | logger := New()
28 | logger.Out = &bytes.Buffer{}
29 | entry := NewEntry(logger)
30 | entry.WithField("err", errBoom).Panicln("kaboom")
31 | }
32 |
33 | func TestEntryPanicf(t *testing.T) {
34 | errBoom := fmt.Errorf("boom again")
35 |
36 | defer func() {
37 | p := recover()
38 | assert.NotNil(t, p)
39 |
40 | switch pVal := p.(type) {
41 | case *Entry:
42 | assert.Equal(t, "kaboom true", pVal.Message)
43 | assert.Equal(t, errBoom, pVal.Data["err"])
44 | default:
45 | t.Fatalf("want type *Entry, got %T: %#v", pVal, pVal)
46 | }
47 | }()
48 |
49 | logger := New()
50 | logger.Out = &bytes.Buffer{}
51 | entry := NewEntry(logger)
52 | entry.WithField("err", errBoom).Panicf("kaboom %v", true)
53 | }
54 |
--------------------------------------------------------------------------------
/vendor/gopkg.in/yaml.v2/LICENSE.libyaml:
--------------------------------------------------------------------------------
1 | The following files were ported to Go from C files of libyaml, and thus
2 | are still covered by their original copyright and license:
3 |
4 | apic.go
5 | emitterc.go
6 | parserc.go
7 | readerc.go
8 | scannerc.go
9 | writerc.go
10 | yamlh.go
11 | yamlprivateh.go
12 |
13 | Copyright (c) 2006 Kirill Simonov
14 |
15 | Permission is hereby granted, free of charge, to any person obtaining a copy of
16 | this software and associated documentation files (the "Software"), to deal in
17 | the Software without restriction, including without limitation the rights to
18 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
19 | of the Software, and to permit persons to whom the Software is furnished to do
20 | so, subject to the following conditions:
21 |
22 | The above copyright notice and this permission notice shall be included in all
23 | copies or substantial portions of the Software.
24 |
25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 | SOFTWARE.
32 |
--------------------------------------------------------------------------------
/pkg/commands/commands.go:
--------------------------------------------------------------------------------
1 | package commands
2 |
3 | import "github.com/moul/advanced-ssh-config/vendor/github.com/codegangsta/cli"
4 |
5 | // Commands is the list of cli commands
6 | var Commands = []cli.Command{
7 | {
8 | Name: "proxy",
9 | Usage: "Connect to host SSH socket, used by ProxyCommand",
10 | Description: "Argument is a host.",
11 | Action: cmdProxy,
12 | Flags: []cli.Flag{
13 | cli.IntFlag{
14 | Name: "port, p",
15 | Value: 0,
16 | Usage: "SSH destination port",
17 | },
18 | },
19 | },
20 | /*
21 | {
22 | Name: "info",
23 | Usage: "Print the connection config for host",
24 | Description: "Argument is a host.",
25 | Action: cmdInfo,
26 | },
27 | */
28 | /*
29 | {
30 | Name: "init",
31 | Usage: "Configure SSH to use assh",
32 | Description: "Build a .ssh/config.advanced file based on .ssh/config and update .ssh/config to use assh as ProxyCommand.",
33 | Action: cmdInit,
34 | },
35 | */
36 | /*
37 | {
38 | Name: "build",
39 | Usage: "Build .ssh/config",
40 | Action: cmdBuild,
41 | },
42 | */
43 | /*
44 | {
45 | Name: "etc-hosts",
46 | Usage: "Generate a /etc/hosts file with assh hosts",
47 | Description: "Build a .ssh/config.advanced file based on .ssh/config and update .ssh/config to use assh as ProxyCommand.",
48 | Action: cmdEtcHosts,
49 | },
50 | */
51 | {
52 | Name: "stats",
53 | Usage: "Print statistics",
54 | Action: cmdStats,
55 | },
56 | }
57 |
--------------------------------------------------------------------------------
/vendor/github.com/Sirupsen/logrus/formatter.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | import "time"
4 |
5 | const DefaultTimestampFormat = time.RFC3339
6 |
7 | // The Formatter interface is used to implement a custom Formatter. It takes an
8 | // `Entry`. It exposes all the fields, including the default ones:
9 | //
10 | // * `entry.Data["msg"]`. The message passed from Info, Warn, Error ..
11 | // * `entry.Data["time"]`. The timestamp.
12 | // * `entry.Data["level"]. The level the entry was logged at.
13 | //
14 | // Any additional fields added with `WithField` or `WithFields` are also in
15 | // `entry.Data`. Format is expected to return an array of bytes which are then
16 | // logged to `logger.Out`.
17 | type Formatter interface {
18 | Format(*Entry) ([]byte, error)
19 | }
20 |
21 | // This is to not silently overwrite `time`, `msg` and `level` fields when
22 | // dumping it. If this code wasn't there doing:
23 | //
24 | // logrus.WithField("level", 1).Info("hello")
25 | //
26 | // Would just silently drop the user provided level. Instead with this code
27 | // it'll logged as:
28 | //
29 | // {"level": "info", "fields.level": 1, "msg": "hello", "time": "..."}
30 | //
31 | // It's not exported because it's still using Data in an opinionated way. It's to
32 | // avoid code duplication between the two default formatters.
33 | func prefixFieldClashes(data Fields) {
34 | _, ok := data["time"]
35 | if ok {
36 | data["fields.time"] = data["time"]
37 | }
38 |
39 | _, ok = data["msg"]
40 | if ok {
41 | data["fields.msg"] = data["msg"]
42 | }
43 |
44 | _, ok = data["level"]
45 | if ok {
46 | data["fields.level"] = data["level"]
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/pkg/config/host.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | // Host defines the configuration flags of a host
4 | type Host struct {
5 | Name string `yaml:-`
6 | Host string `yaml:"host,omitempty,flow" json:"host,omitempty"`
7 | User string `yaml:"user,omitempty,flow" json:"user,omitempty"`
8 | Port uint `yaml:"port,omitempty,flow" json:"port,omitempty"`
9 | ProxyCommand string `yaml:"proxycommand,omitempty,flow" json:"proxycommand,omitempty"`
10 | ControlPath string `yaml:"controlpath,omitempty,flow" json:"controlpath,omitempty"`
11 | Gateways []string `yaml:"gateways,omitempty,flow" json:"gateways,omitempty"`
12 | ResolveNameservers []string `yaml:"resolve_nameservers,omitempty,flow" json:"resolve_nameservers,omitempty"`
13 | ResolveCommand string `yaml:"resolve_command,omitempty,flow" json:"resolve_command,omitempty"`
14 | }
15 |
16 | // ApplyDefaults ensures a Host is valid by filling the missing fields with defaults
17 | func (h *Host) ApplyDefaults(defaults *Host) {
18 | if h.Host == "" {
19 | h.Host = defaults.Host
20 | }
21 | if h.User == "" {
22 | h.User = defaults.User
23 | }
24 | if h.Port == 0 {
25 | h.Port = defaults.Port
26 | }
27 | if len(h.Gateways) == 0 {
28 | h.Gateways = defaults.Gateways
29 | }
30 | if h.ProxyCommand == "" {
31 | h.ProxyCommand = defaults.ProxyCommand
32 | }
33 | if len(h.ResolveNameservers) == 0 {
34 | h.ResolveNameservers = defaults.ResolveNameservers
35 | }
36 | if h.ResolveCommand == "" {
37 | h.ResolveCommand = defaults.ResolveCommand
38 | }
39 | if h.ControlPath == "" {
40 | h.ControlPath = defaults.ControlPath
41 | }
42 |
43 | // Extra defaults
44 | if h.Port == 0 {
45 | h.Port = 22
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/vendor/github.com/Sirupsen/logrus/text_formatter_test.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | import (
4 | "bytes"
5 | "errors"
6 | "testing"
7 | "time"
8 | )
9 |
10 | func TestQuoting(t *testing.T) {
11 | tf := &TextFormatter{DisableColors: true}
12 |
13 | checkQuoting := func(q bool, value interface{}) {
14 | b, _ := tf.Format(WithField("test", value))
15 | idx := bytes.Index(b, ([]byte)("test="))
16 | cont := bytes.Contains(b[idx+5:], []byte{'"'})
17 | if cont != q {
18 | if q {
19 | t.Errorf("quoting expected for: %#v", value)
20 | } else {
21 | t.Errorf("quoting not expected for: %#v", value)
22 | }
23 | }
24 | }
25 |
26 | checkQuoting(false, "abcd")
27 | checkQuoting(false, "v1.0")
28 | checkQuoting(false, "1234567890")
29 | checkQuoting(true, "/foobar")
30 | checkQuoting(true, "x y")
31 | checkQuoting(true, "x,y")
32 | checkQuoting(false, errors.New("invalid"))
33 | checkQuoting(true, errors.New("invalid argument"))
34 | }
35 |
36 | func TestTimestampFormat(t *testing.T) {
37 | checkTimeStr := func(format string) {
38 | customFormatter := &TextFormatter{DisableColors: true, TimestampFormat: format}
39 | customStr, _ := customFormatter.Format(WithField("test", "test"))
40 | timeStart := bytes.Index(customStr, ([]byte)("time="))
41 | timeEnd := bytes.Index(customStr, ([]byte)("level="))
42 | timeStr := customStr[timeStart+5 : timeEnd-1]
43 | if timeStr[0] == '"' && timeStr[len(timeStr)-1] == '"' {
44 | timeStr = timeStr[1 : len(timeStr)-1]
45 | }
46 | if format == "" {
47 | format = time.RFC3339
48 | }
49 | _, e := time.Parse(format, (string)(timeStr))
50 | if e != nil {
51 | t.Errorf("time string \"%s\" did not match provided time format \"%s\": %s", timeStr, format, e)
52 | }
53 | }
54 |
55 | checkTimeStr("2006-01-02T15:04:05.000000000Z07:00")
56 | checkTimeStr("Mon Jan _2 15:04:05 2006")
57 | checkTimeStr("")
58 | }
59 |
60 | // TODO add tests for sorting etc., this requires a parser for the text
61 | // formatter output.
62 |
--------------------------------------------------------------------------------
/pkg/config/config_test.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import (
4 | "strings"
5 | "testing"
6 |
7 | "github.com/moul/advanced-ssh-config/vendor/github.com/stretchr/testify/assert"
8 | )
9 |
10 | func dummyConfig() *Config {
11 | config := New()
12 | config.Hosts["toto"] = Host{
13 | Host: "1.2.3.4",
14 | }
15 | config.Hosts["titi"] = Host{
16 | Host: "tata",
17 | Port: 23,
18 | User: "moul",
19 | }
20 | config.Defaults = Host{
21 | Port: 22,
22 | User: "root",
23 | }
24 | return config
25 | }
26 |
27 | func TestNew(t *testing.T) {
28 | config := New()
29 |
30 | assert.Equal(t, len(config.Hosts), 0)
31 | assert.Equal(t, config.Defaults.Port, uint(0))
32 | assert.Equal(t, config.Defaults.Host, "")
33 | assert.Equal(t, config.Defaults.User, "")
34 | }
35 |
36 | func TestConfig(t *testing.T) {
37 | config := dummyConfig()
38 |
39 | assert.Equal(t, len(config.Hosts), 2)
40 | assert.Equal(t, config.Hosts["toto"].Host, "1.2.3.4")
41 | assert.Equal(t, config.Defaults.Port, uint(22))
42 | }
43 |
44 | func TestConfigLoadFile(t *testing.T) {
45 | config := New()
46 | err := config.LoadConfig(strings.NewReader(`
47 | hosts:
48 | aaa:
49 | host: 1.2.3.4
50 | bbb:
51 | port: 21
52 | ccc:
53 | host: 5.6.7.8
54 | port: 24
55 | user: toor
56 | defaults:
57 | port: 22
58 | user: root
59 | `))
60 | assert.Nil(t, err)
61 | assert.Equal(t, len(config.Hosts), 3)
62 | assert.Equal(t, config.Hosts["aaa"].Host, "1.2.3.4")
63 | assert.Equal(t, config.Hosts["aaa"].Port, uint(0))
64 | assert.Equal(t, config.Hosts["aaa"].User, "")
65 | assert.Equal(t, config.Hosts["bbb"].Host, "")
66 | assert.Equal(t, config.Hosts["bbb"].Port, uint(21))
67 | assert.Equal(t, config.Hosts["bbb"].User, "")
68 | assert.Equal(t, config.Hosts["ccc"].Host, "5.6.7.8")
69 | assert.Equal(t, config.Hosts["ccc"].Port, uint(24))
70 | assert.Equal(t, config.Hosts["ccc"].User, "toor")
71 | assert.Equal(t, config.Defaults.Port, uint(22))
72 | assert.Equal(t, config.Defaults.User, "root")
73 | }
74 |
--------------------------------------------------------------------------------
/vendor/github.com/Sirupsen/logrus/formatter_bench_test.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | import (
4 | "fmt"
5 | "testing"
6 | "time"
7 | )
8 |
9 | // smallFields is a small size data set for benchmarking
10 | var smallFields = Fields{
11 | "foo": "bar",
12 | "baz": "qux",
13 | "one": "two",
14 | "three": "four",
15 | }
16 |
17 | // largeFields is a large size data set for benchmarking
18 | var largeFields = Fields{
19 | "foo": "bar",
20 | "baz": "qux",
21 | "one": "two",
22 | "three": "four",
23 | "five": "six",
24 | "seven": "eight",
25 | "nine": "ten",
26 | "eleven": "twelve",
27 | "thirteen": "fourteen",
28 | "fifteen": "sixteen",
29 | "seventeen": "eighteen",
30 | "nineteen": "twenty",
31 | "a": "b",
32 | "c": "d",
33 | "e": "f",
34 | "g": "h",
35 | "i": "j",
36 | "k": "l",
37 | "m": "n",
38 | "o": "p",
39 | "q": "r",
40 | "s": "t",
41 | "u": "v",
42 | "w": "x",
43 | "y": "z",
44 | "this": "will",
45 | "make": "thirty",
46 | "entries": "yeah",
47 | }
48 |
49 | var errorFields = Fields{
50 | "foo": fmt.Errorf("bar"),
51 | "baz": fmt.Errorf("qux"),
52 | }
53 |
54 | func BenchmarkErrorTextFormatter(b *testing.B) {
55 | doBenchmark(b, &TextFormatter{DisableColors: true}, errorFields)
56 | }
57 |
58 | func BenchmarkSmallTextFormatter(b *testing.B) {
59 | doBenchmark(b, &TextFormatter{DisableColors: true}, smallFields)
60 | }
61 |
62 | func BenchmarkLargeTextFormatter(b *testing.B) {
63 | doBenchmark(b, &TextFormatter{DisableColors: true}, largeFields)
64 | }
65 |
66 | func BenchmarkSmallColoredTextFormatter(b *testing.B) {
67 | doBenchmark(b, &TextFormatter{ForceColors: true}, smallFields)
68 | }
69 |
70 | func BenchmarkLargeColoredTextFormatter(b *testing.B) {
71 | doBenchmark(b, &TextFormatter{ForceColors: true}, largeFields)
72 | }
73 |
74 | func BenchmarkSmallJSONFormatter(b *testing.B) {
75 | doBenchmark(b, &JSONFormatter{}, smallFields)
76 | }
77 |
78 | func BenchmarkLargeJSONFormatter(b *testing.B) {
79 | doBenchmark(b, &JSONFormatter{}, largeFields)
80 | }
81 |
82 | func doBenchmark(b *testing.B, formatter Formatter, fields Fields) {
83 | entry := &Entry{
84 | Time: time.Time{},
85 | Level: InfoLevel,
86 | Message: "message",
87 | Data: fields,
88 | }
89 | var d []byte
90 | var err error
91 | for i := 0; i < b.N; i++ {
92 | d, err = formatter.Format(entry)
93 | if err != nil {
94 | b.Fatal(err)
95 | }
96 | b.SetBytes(int64(len(d)))
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/vendor/github.com/codegangsta/cli/cli_test.go:
--------------------------------------------------------------------------------
1 | package cli_test
2 |
3 | import (
4 | "os"
5 |
6 | "github.com/moul/advanced-ssh-config/vendor/github.com/codegangsta/cli"
7 | )
8 |
9 | func Example() {
10 | app := cli.NewApp()
11 | app.Name = "todo"
12 | app.Usage = "task list on the command line"
13 | app.Commands = []cli.Command{
14 | {
15 | Name: "add",
16 | Aliases: []string{"a"},
17 | Usage: "add a task to the list",
18 | Action: func(c *cli.Context) {
19 | println("added task: ", c.Args().First())
20 | },
21 | },
22 | {
23 | Name: "complete",
24 | Aliases: []string{"c"},
25 | Usage: "complete a task on the list",
26 | Action: func(c *cli.Context) {
27 | println("completed task: ", c.Args().First())
28 | },
29 | },
30 | }
31 |
32 | app.Run(os.Args)
33 | }
34 |
35 | func ExampleSubcommand() {
36 | app := cli.NewApp()
37 | app.Name = "say"
38 | app.Commands = []cli.Command{
39 | {
40 | Name: "hello",
41 | Aliases: []string{"hi"},
42 | Usage: "use it to see a description",
43 | Description: "This is how we describe hello the function",
44 | Subcommands: []cli.Command{
45 | {
46 | Name: "english",
47 | Aliases: []string{"en"},
48 | Usage: "sends a greeting in english",
49 | Description: "greets someone in english",
50 | Flags: []cli.Flag{
51 | cli.StringFlag{
52 | Name: "name",
53 | Value: "Bob",
54 | Usage: "Name of the person to greet",
55 | },
56 | },
57 | Action: func(c *cli.Context) {
58 | println("Hello, ", c.String("name"))
59 | },
60 | }, {
61 | Name: "spanish",
62 | Aliases: []string{"sp"},
63 | Usage: "sends a greeting in spanish",
64 | Flags: []cli.Flag{
65 | cli.StringFlag{
66 | Name: "surname",
67 | Value: "Jones",
68 | Usage: "Surname of the person to greet",
69 | },
70 | },
71 | Action: func(c *cli.Context) {
72 | println("Hola, ", c.String("surname"))
73 | },
74 | }, {
75 | Name: "french",
76 | Aliases: []string{"fr"},
77 | Usage: "sends a greeting in french",
78 | Flags: []cli.Flag{
79 | cli.StringFlag{
80 | Name: "nickname",
81 | Value: "Stevie",
82 | Usage: "Nickname of the person to greet",
83 | },
84 | },
85 | Action: func(c *cli.Context) {
86 | println("Bonjour, ", c.String("nickname"))
87 | },
88 | },
89 | },
90 | }, {
91 | Name: "bye",
92 | Usage: "says goodbye",
93 | Action: func(c *cli.Context) {
94 | println("bye")
95 | },
96 | },
97 | }
98 |
99 | app.Run(os.Args)
100 | }
101 |
--------------------------------------------------------------------------------
/vendor/gopkg.in/yaml.v2/writerc.go:
--------------------------------------------------------------------------------
1 | package yaml
2 |
3 | // Set the writer error and return false.
4 | func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool {
5 | emitter.error = yaml_WRITER_ERROR
6 | emitter.problem = problem
7 | return false
8 | }
9 |
10 | // Flush the output buffer.
11 | func yaml_emitter_flush(emitter *yaml_emitter_t) bool {
12 | if emitter.write_handler == nil {
13 | panic("write handler not set")
14 | }
15 |
16 | // Check if the buffer is empty.
17 | if emitter.buffer_pos == 0 {
18 | return true
19 | }
20 |
21 | // If the output encoding is UTF-8, we don't need to recode the buffer.
22 | if emitter.encoding == yaml_UTF8_ENCODING {
23 | if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil {
24 | return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
25 | }
26 | emitter.buffer_pos = 0
27 | return true
28 | }
29 |
30 | // Recode the buffer into the raw buffer.
31 | var low, high int
32 | if emitter.encoding == yaml_UTF16LE_ENCODING {
33 | low, high = 0, 1
34 | } else {
35 | high, low = 1, 0
36 | }
37 |
38 | pos := 0
39 | for pos < emitter.buffer_pos {
40 | // See the "reader.c" code for more details on UTF-8 encoding. Note
41 | // that we assume that the buffer contains a valid UTF-8 sequence.
42 |
43 | // Read the next UTF-8 character.
44 | octet := emitter.buffer[pos]
45 |
46 | var w int
47 | var value rune
48 | switch {
49 | case octet&0x80 == 0x00:
50 | w, value = 1, rune(octet&0x7F)
51 | case octet&0xE0 == 0xC0:
52 | w, value = 2, rune(octet&0x1F)
53 | case octet&0xF0 == 0xE0:
54 | w, value = 3, rune(octet&0x0F)
55 | case octet&0xF8 == 0xF0:
56 | w, value = 4, rune(octet&0x07)
57 | }
58 | for k := 1; k < w; k++ {
59 | octet = emitter.buffer[pos+k]
60 | value = (value << 6) + (rune(octet) & 0x3F)
61 | }
62 | pos += w
63 |
64 | // Write the character.
65 | if value < 0x10000 {
66 | var b [2]byte
67 | b[high] = byte(value >> 8)
68 | b[low] = byte(value & 0xFF)
69 | emitter.raw_buffer = append(emitter.raw_buffer, b[0], b[1])
70 | } else {
71 | // Write the character using a surrogate pair (check "reader.c").
72 | var b [4]byte
73 | value -= 0x10000
74 | b[high] = byte(0xD8 + (value >> 18))
75 | b[low] = byte((value >> 10) & 0xFF)
76 | b[high+2] = byte(0xDC + ((value >> 8) & 0xFF))
77 | b[low+2] = byte(value & 0xFF)
78 | emitter.raw_buffer = append(emitter.raw_buffer, b[0], b[1], b[2], b[3])
79 | }
80 | }
81 |
82 | // Write the raw buffer.
83 | if err := emitter.write_handler(emitter, emitter.raw_buffer); err != nil {
84 | return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
85 | }
86 | emitter.buffer_pos = 0
87 | emitter.raw_buffer = emitter.raw_buffer[:0]
88 | return true
89 | }
90 |
--------------------------------------------------------------------------------
/vendor/github.com/Sirupsen/logrus/logrus.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | import (
4 | "fmt"
5 | "log"
6 | )
7 |
8 | // Fields type, used to pass to `WithFields`.
9 | type Fields map[string]interface{}
10 |
11 | // Level type
12 | type Level uint8
13 |
14 | // Convert the Level to a string. E.g. PanicLevel becomes "panic".
15 | func (level Level) String() string {
16 | switch level {
17 | case DebugLevel:
18 | return "debug"
19 | case InfoLevel:
20 | return "info"
21 | case WarnLevel:
22 | return "warning"
23 | case ErrorLevel:
24 | return "error"
25 | case FatalLevel:
26 | return "fatal"
27 | case PanicLevel:
28 | return "panic"
29 | }
30 |
31 | return "unknown"
32 | }
33 |
34 | // ParseLevel takes a string level and returns the Logrus log level constant.
35 | func ParseLevel(lvl string) (Level, error) {
36 | switch lvl {
37 | case "panic":
38 | return PanicLevel, nil
39 | case "fatal":
40 | return FatalLevel, nil
41 | case "error":
42 | return ErrorLevel, nil
43 | case "warn", "warning":
44 | return WarnLevel, nil
45 | case "info":
46 | return InfoLevel, nil
47 | case "debug":
48 | return DebugLevel, nil
49 | }
50 |
51 | var l Level
52 | return l, fmt.Errorf("not a valid logrus Level: %q", lvl)
53 | }
54 |
55 | // These are the different logging levels. You can set the logging level to log
56 | // on your instance of logger, obtained with `logrus.New()`.
57 | const (
58 | // PanicLevel level, highest level of severity. Logs and then calls panic with the
59 | // message passed to Debug, Info, ...
60 | PanicLevel Level = iota
61 | // FatalLevel level. Logs and then calls `os.Exit(1)`. It will exit even if the
62 | // logging level is set to Panic.
63 | FatalLevel
64 | // ErrorLevel level. Logs. Used for errors that should definitely be noted.
65 | // Commonly used for hooks to send errors to an error tracking service.
66 | ErrorLevel
67 | // WarnLevel level. Non-critical entries that deserve eyes.
68 | WarnLevel
69 | // InfoLevel level. General operational entries about what's going on inside the
70 | // application.
71 | InfoLevel
72 | // DebugLevel level. Usually only enabled when debugging. Very verbose logging.
73 | DebugLevel
74 | )
75 |
76 | // Won't compile if StdLogger can't be realized by a log.Logger
77 | var _ StdLogger = &log.Logger{}
78 |
79 | // StdLogger is what your logrus-enabled library should take, that way
80 | // it'll accept a stdlib logger and a logrus logger. There's no standard
81 | // interface, this is the closest we get, unfortunately.
82 | type StdLogger interface {
83 | Print(...interface{})
84 | Printf(string, ...interface{})
85 | Println(...interface{})
86 |
87 | Fatal(...interface{})
88 | Fatalf(string, ...interface{})
89 | Fatalln(...interface{})
90 |
91 | Panic(...interface{})
92 | Panicf(string, ...interface{})
93 | Panicln(...interface{})
94 | }
95 |
--------------------------------------------------------------------------------
/vendor/github.com/Sirupsen/logrus/hook_test.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/moul/advanced-ssh-config/vendor/github.com/stretchr/testify/assert"
7 | )
8 |
9 | type TestHook struct {
10 | Fired bool
11 | }
12 |
13 | func (hook *TestHook) Fire(entry *Entry) error {
14 | hook.Fired = true
15 | return nil
16 | }
17 |
18 | func (hook *TestHook) Levels() []Level {
19 | return []Level{
20 | DebugLevel,
21 | InfoLevel,
22 | WarnLevel,
23 | ErrorLevel,
24 | FatalLevel,
25 | PanicLevel,
26 | }
27 | }
28 |
29 | func TestHookFires(t *testing.T) {
30 | hook := new(TestHook)
31 |
32 | LogAndAssertJSON(t, func(log *Logger) {
33 | log.Hooks.Add(hook)
34 | assert.Equal(t, hook.Fired, false)
35 |
36 | log.Print("test")
37 | }, func(fields Fields) {
38 | assert.Equal(t, hook.Fired, true)
39 | })
40 | }
41 |
42 | type ModifyHook struct {
43 | }
44 |
45 | func (hook *ModifyHook) Fire(entry *Entry) error {
46 | entry.Data["wow"] = "whale"
47 | return nil
48 | }
49 |
50 | func (hook *ModifyHook) Levels() []Level {
51 | return []Level{
52 | DebugLevel,
53 | InfoLevel,
54 | WarnLevel,
55 | ErrorLevel,
56 | FatalLevel,
57 | PanicLevel,
58 | }
59 | }
60 |
61 | func TestHookCanModifyEntry(t *testing.T) {
62 | hook := new(ModifyHook)
63 |
64 | LogAndAssertJSON(t, func(log *Logger) {
65 | log.Hooks.Add(hook)
66 | log.WithField("wow", "elephant").Print("test")
67 | }, func(fields Fields) {
68 | assert.Equal(t, fields["wow"], "whale")
69 | })
70 | }
71 |
72 | func TestCanFireMultipleHooks(t *testing.T) {
73 | hook1 := new(ModifyHook)
74 | hook2 := new(TestHook)
75 |
76 | LogAndAssertJSON(t, func(log *Logger) {
77 | log.Hooks.Add(hook1)
78 | log.Hooks.Add(hook2)
79 |
80 | log.WithField("wow", "elephant").Print("test")
81 | }, func(fields Fields) {
82 | assert.Equal(t, fields["wow"], "whale")
83 | assert.Equal(t, hook2.Fired, true)
84 | })
85 | }
86 |
87 | type ErrorHook struct {
88 | Fired bool
89 | }
90 |
91 | func (hook *ErrorHook) Fire(entry *Entry) error {
92 | hook.Fired = true
93 | return nil
94 | }
95 |
96 | func (hook *ErrorHook) Levels() []Level {
97 | return []Level{
98 | ErrorLevel,
99 | }
100 | }
101 |
102 | func TestErrorHookShouldntFireOnInfo(t *testing.T) {
103 | hook := new(ErrorHook)
104 |
105 | LogAndAssertJSON(t, func(log *Logger) {
106 | log.Hooks.Add(hook)
107 | log.Info("test")
108 | }, func(fields Fields) {
109 | assert.Equal(t, hook.Fired, false)
110 | })
111 | }
112 |
113 | func TestErrorHookShouldFireOnError(t *testing.T) {
114 | hook := new(ErrorHook)
115 |
116 | LogAndAssertJSON(t, func(log *Logger) {
117 | log.Hooks.Add(hook)
118 | log.Error("test")
119 | }, func(fields Fields) {
120 | assert.Equal(t, hook.Fired, true)
121 | })
122 | }
123 |
--------------------------------------------------------------------------------
/vendor/gopkg.in/yaml.v2/sorter.go:
--------------------------------------------------------------------------------
1 | package yaml
2 |
3 | import (
4 | "reflect"
5 | "unicode"
6 | )
7 |
8 | type keyList []reflect.Value
9 |
10 | func (l keyList) Len() int { return len(l) }
11 | func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
12 | func (l keyList) Less(i, j int) bool {
13 | a := l[i]
14 | b := l[j]
15 | ak := a.Kind()
16 | bk := b.Kind()
17 | for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() {
18 | a = a.Elem()
19 | ak = a.Kind()
20 | }
21 | for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() {
22 | b = b.Elem()
23 | bk = b.Kind()
24 | }
25 | af, aok := keyFloat(a)
26 | bf, bok := keyFloat(b)
27 | if aok && bok {
28 | if af != bf {
29 | return af < bf
30 | }
31 | if ak != bk {
32 | return ak < bk
33 | }
34 | return numLess(a, b)
35 | }
36 | if ak != reflect.String || bk != reflect.String {
37 | return ak < bk
38 | }
39 | ar, br := []rune(a.String()), []rune(b.String())
40 | for i := 0; i < len(ar) && i < len(br); i++ {
41 | if ar[i] == br[i] {
42 | continue
43 | }
44 | al := unicode.IsLetter(ar[i])
45 | bl := unicode.IsLetter(br[i])
46 | if al && bl {
47 | return ar[i] < br[i]
48 | }
49 | if al || bl {
50 | return bl
51 | }
52 | var ai, bi int
53 | var an, bn int64
54 | for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ {
55 | an = an*10 + int64(ar[ai]-'0')
56 | }
57 | for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ {
58 | bn = bn*10 + int64(br[bi]-'0')
59 | }
60 | if an != bn {
61 | return an < bn
62 | }
63 | if ai != bi {
64 | return ai < bi
65 | }
66 | return ar[i] < br[i]
67 | }
68 | return len(ar) < len(br)
69 | }
70 |
71 | // keyFloat returns a float value for v if it is a number/bool
72 | // and whether it is a number/bool or not.
73 | func keyFloat(v reflect.Value) (f float64, ok bool) {
74 | switch v.Kind() {
75 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
76 | return float64(v.Int()), true
77 | case reflect.Float32, reflect.Float64:
78 | return v.Float(), true
79 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
80 | return float64(v.Uint()), true
81 | case reflect.Bool:
82 | if v.Bool() {
83 | return 1, true
84 | }
85 | return 0, true
86 | }
87 | return 0, false
88 | }
89 |
90 | // numLess returns whether a < b.
91 | // a and b must necessarily have the same kind.
92 | func numLess(a, b reflect.Value) bool {
93 | switch a.Kind() {
94 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
95 | return a.Int() < b.Int()
96 | case reflect.Float32, reflect.Float64:
97 | return a.Float() < b.Float()
98 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
99 | return a.Uint() < b.Uint()
100 | case reflect.Bool:
101 | return !a.Bool() && b.Bool()
102 | }
103 | panic("not a number")
104 | }
105 |
--------------------------------------------------------------------------------
/vendor/gopkg.in/yaml.v2/README.md:
--------------------------------------------------------------------------------
1 | # YAML support for the Go language
2 |
3 | Introduction
4 | ------------
5 |
6 | The yaml package enables Go programs to comfortably encode and decode YAML
7 | values. It was developed within [Canonical](https://www.canonical.com) as
8 | part of the [juju](https://juju.ubuntu.com) project, and is based on a
9 | pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML)
10 | C library to parse and generate YAML data quickly and reliably.
11 |
12 | Compatibility
13 | -------------
14 |
15 | The yaml package supports most of YAML 1.1 and 1.2, including support for
16 | anchors, tags, map merging, etc. Multi-document unmarshalling is not yet
17 | implemented, and base-60 floats from YAML 1.1 are purposefully not
18 | supported since they're a poor design and are gone in YAML 1.2.
19 |
20 | Installation and usage
21 | ----------------------
22 |
23 | The import path for the package is *gopkg.in/yaml.v2*.
24 |
25 | To install it, run:
26 |
27 | go get gopkg.in/yaml.v2
28 |
29 | API documentation
30 | -----------------
31 |
32 | If opened in a browser, the import path itself leads to the API documentation:
33 |
34 | * [https://gopkg.in/yaml.v2](https://gopkg.in/yaml.v2)
35 |
36 | API stability
37 | -------------
38 |
39 | The package API for yaml v2 will remain stable as described in [gopkg.in](https://gopkg.in).
40 |
41 |
42 | License
43 | -------
44 |
45 | The yaml package is licensed under the LGPL with an exception that allows it to be linked statically. Please see the LICENSE file for details.
46 |
47 |
48 | Example
49 | -------
50 |
51 | ```Go
52 | package main
53 |
54 | import (
55 | "fmt"
56 | "log"
57 |
58 | "gopkg.in/yaml.v2"
59 | )
60 |
61 | var data = `
62 | a: Easy!
63 | b:
64 | c: 2
65 | d: [3, 4]
66 | `
67 |
68 | type T struct {
69 | A string
70 | B struct{C int; D []int ",flow"}
71 | }
72 |
73 | func main() {
74 | t := T{}
75 |
76 | err := yaml.Unmarshal([]byte(data), &t)
77 | if err != nil {
78 | log.Fatalf("error: %v", err)
79 | }
80 | fmt.Printf("--- t:\n%v\n\n", t)
81 |
82 | d, err := yaml.Marshal(&t)
83 | if err != nil {
84 | log.Fatalf("error: %v", err)
85 | }
86 | fmt.Printf("--- t dump:\n%s\n\n", string(d))
87 |
88 | m := make(map[interface{}]interface{})
89 |
90 | err = yaml.Unmarshal([]byte(data), &m)
91 | if err != nil {
92 | log.Fatalf("error: %v", err)
93 | }
94 | fmt.Printf("--- m:\n%v\n\n", m)
95 |
96 | d, err = yaml.Marshal(&m)
97 | if err != nil {
98 | log.Fatalf("error: %v", err)
99 | }
100 | fmt.Printf("--- m dump:\n%s\n\n", string(d))
101 | }
102 | ```
103 |
104 | This example will generate the following output:
105 |
106 | ```
107 | --- t:
108 | {Easy! {2 [3 4]}}
109 |
110 | --- t dump:
111 | a: Easy!
112 | b:
113 | c: 2
114 | d: [3, 4]
115 |
116 |
117 | --- m:
118 | map[a:Easy! b:map[c:2 d:[3 4]]]
119 |
120 | --- m dump:
121 | a: Easy!
122 | b:
123 | c: 2
124 | d:
125 | - 3
126 | - 4
127 | ```
128 |
129 |
--------------------------------------------------------------------------------
/vendor/github.com/Sirupsen/logrus/json_formatter_test.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | import (
4 | "encoding/json"
5 | "errors"
6 |
7 | "testing"
8 | )
9 |
10 | func TestErrorNotLost(t *testing.T) {
11 | formatter := &JSONFormatter{}
12 |
13 | b, err := formatter.Format(WithField("error", errors.New("wild walrus")))
14 | if err != nil {
15 | t.Fatal("Unable to format entry: ", err)
16 | }
17 |
18 | entry := make(map[string]interface{})
19 | err = json.Unmarshal(b, &entry)
20 | if err != nil {
21 | t.Fatal("Unable to unmarshal formatted entry: ", err)
22 | }
23 |
24 | if entry["error"] != "wild walrus" {
25 | t.Fatal("Error field not set")
26 | }
27 | }
28 |
29 | func TestErrorNotLostOnFieldNotNamedError(t *testing.T) {
30 | formatter := &JSONFormatter{}
31 |
32 | b, err := formatter.Format(WithField("omg", errors.New("wild walrus")))
33 | if err != nil {
34 | t.Fatal("Unable to format entry: ", err)
35 | }
36 |
37 | entry := make(map[string]interface{})
38 | err = json.Unmarshal(b, &entry)
39 | if err != nil {
40 | t.Fatal("Unable to unmarshal formatted entry: ", err)
41 | }
42 |
43 | if entry["omg"] != "wild walrus" {
44 | t.Fatal("Error field not set")
45 | }
46 | }
47 |
48 | func TestFieldClashWithTime(t *testing.T) {
49 | formatter := &JSONFormatter{}
50 |
51 | b, err := formatter.Format(WithField("time", "right now!"))
52 | if err != nil {
53 | t.Fatal("Unable to format entry: ", err)
54 | }
55 |
56 | entry := make(map[string]interface{})
57 | err = json.Unmarshal(b, &entry)
58 | if err != nil {
59 | t.Fatal("Unable to unmarshal formatted entry: ", err)
60 | }
61 |
62 | if entry["fields.time"] != "right now!" {
63 | t.Fatal("fields.time not set to original time field")
64 | }
65 |
66 | if entry["time"] != "0001-01-01T00:00:00Z" {
67 | t.Fatal("time field not set to current time, was: ", entry["time"])
68 | }
69 | }
70 |
71 | func TestFieldClashWithMsg(t *testing.T) {
72 | formatter := &JSONFormatter{}
73 |
74 | b, err := formatter.Format(WithField("msg", "something"))
75 | if err != nil {
76 | t.Fatal("Unable to format entry: ", err)
77 | }
78 |
79 | entry := make(map[string]interface{})
80 | err = json.Unmarshal(b, &entry)
81 | if err != nil {
82 | t.Fatal("Unable to unmarshal formatted entry: ", err)
83 | }
84 |
85 | if entry["fields.msg"] != "something" {
86 | t.Fatal("fields.msg not set to original msg field")
87 | }
88 | }
89 |
90 | func TestFieldClashWithLevel(t *testing.T) {
91 | formatter := &JSONFormatter{}
92 |
93 | b, err := formatter.Format(WithField("level", "something"))
94 | if err != nil {
95 | t.Fatal("Unable to format entry: ", err)
96 | }
97 |
98 | entry := make(map[string]interface{})
99 | err = json.Unmarshal(b, &entry)
100 | if err != nil {
101 | t.Fatal("Unable to unmarshal formatted entry: ", err)
102 | }
103 |
104 | if entry["fields.level"] != "something" {
105 | t.Fatal("fields.level not set to original level field")
106 | }
107 | }
108 |
109 | func TestJSONEntryEndsWithNewline(t *testing.T) {
110 | formatter := &JSONFormatter{}
111 |
112 | b, err := formatter.Format(WithField("level", "something"))
113 | if err != nil {
114 | t.Fatal("Unable to format entry: ", err)
115 | }
116 |
117 | if b[len(b)-1] != '\n' {
118 | t.Fatal("Expected JSON log entry to end with a newline")
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/vendor/github.com/stretchr/testify/assert/http_assertions_test.go:
--------------------------------------------------------------------------------
1 | package assert
2 |
3 | import (
4 | "fmt"
5 | "net/http"
6 | "net/url"
7 | "testing"
8 | )
9 |
10 | func httpOK(w http.ResponseWriter, r *http.Request) {
11 | w.WriteHeader(http.StatusOK)
12 | }
13 |
14 | func httpRedirect(w http.ResponseWriter, r *http.Request) {
15 | w.WriteHeader(http.StatusTemporaryRedirect)
16 | }
17 |
18 | func httpError(w http.ResponseWriter, r *http.Request) {
19 | w.WriteHeader(http.StatusInternalServerError)
20 | }
21 |
22 | func TestHTTPStatuses(t *testing.T) {
23 | assert := New(t)
24 | mockT := new(testing.T)
25 |
26 | assert.Equal(HTTPSuccess(mockT, httpOK, "GET", "/", nil), true)
27 | assert.Equal(HTTPSuccess(mockT, httpRedirect, "GET", "/", nil), false)
28 | assert.Equal(HTTPSuccess(mockT, httpError, "GET", "/", nil), false)
29 |
30 | assert.Equal(HTTPRedirect(mockT, httpOK, "GET", "/", nil), false)
31 | assert.Equal(HTTPRedirect(mockT, httpRedirect, "GET", "/", nil), true)
32 | assert.Equal(HTTPRedirect(mockT, httpError, "GET", "/", nil), false)
33 |
34 | assert.Equal(HTTPError(mockT, httpOK, "GET", "/", nil), false)
35 | assert.Equal(HTTPError(mockT, httpRedirect, "GET", "/", nil), false)
36 | assert.Equal(HTTPError(mockT, httpError, "GET", "/", nil), true)
37 | }
38 |
39 | func TestHTTPStatusesWrapper(t *testing.T) {
40 | assert := New(t)
41 | mockAssert := New(new(testing.T))
42 |
43 | assert.Equal(mockAssert.HTTPSuccess(httpOK, "GET", "/", nil), true)
44 | assert.Equal(mockAssert.HTTPSuccess(httpRedirect, "GET", "/", nil), false)
45 | assert.Equal(mockAssert.HTTPSuccess(httpError, "GET", "/", nil), false)
46 |
47 | assert.Equal(mockAssert.HTTPRedirect(httpOK, "GET", "/", nil), false)
48 | assert.Equal(mockAssert.HTTPRedirect(httpRedirect, "GET", "/", nil), true)
49 | assert.Equal(mockAssert.HTTPRedirect(httpError, "GET", "/", nil), false)
50 |
51 | assert.Equal(mockAssert.HTTPError(httpOK, "GET", "/", nil), false)
52 | assert.Equal(mockAssert.HTTPError(httpRedirect, "GET", "/", nil), false)
53 | assert.Equal(mockAssert.HTTPError(httpError, "GET", "/", nil), true)
54 | }
55 |
56 | func httpHelloName(w http.ResponseWriter, r *http.Request) {
57 | name := r.FormValue("name")
58 | w.Write([]byte(fmt.Sprintf("Hello, %s!", name)))
59 | }
60 |
61 | func TestHttpBody(t *testing.T) {
62 | assert := New(t)
63 | mockT := new(testing.T)
64 |
65 | assert.True(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!"))
66 | assert.True(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World"))
67 | assert.False(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world"))
68 |
69 | assert.False(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!"))
70 | assert.False(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World"))
71 | assert.True(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world"))
72 | }
73 |
74 | func TestHttpBodyWrappers(t *testing.T) {
75 | assert := New(t)
76 | mockAssert := New(new(testing.T))
77 |
78 | assert.True(mockAssert.HTTPBodyContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!"))
79 | assert.True(mockAssert.HTTPBodyContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World"))
80 | assert.False(mockAssert.HTTPBodyContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world"))
81 |
82 | assert.False(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!"))
83 | assert.False(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World"))
84 | assert.True(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world"))
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/vendor/github.com/codegangsta/cli/context_test.go:
--------------------------------------------------------------------------------
1 | package cli_test
2 |
3 | import (
4 | "flag"
5 | "testing"
6 | "time"
7 |
8 | "github.com/moul/advanced-ssh-config/vendor/github.com/codegangsta/cli"
9 | )
10 |
11 | func TestNewContext(t *testing.T) {
12 | set := flag.NewFlagSet("test", 0)
13 | set.Int("myflag", 12, "doc")
14 | globalSet := flag.NewFlagSet("test", 0)
15 | globalSet.Int("myflag", 42, "doc")
16 | globalCtx := cli.NewContext(nil, globalSet, nil)
17 | command := cli.Command{Name: "mycommand"}
18 | c := cli.NewContext(nil, set, globalCtx)
19 | c.Command = command
20 | expect(t, c.Int("myflag"), 12)
21 | expect(t, c.GlobalInt("myflag"), 42)
22 | expect(t, c.Command.Name, "mycommand")
23 | }
24 |
25 | func TestContext_Int(t *testing.T) {
26 | set := flag.NewFlagSet("test", 0)
27 | set.Int("myflag", 12, "doc")
28 | c := cli.NewContext(nil, set, nil)
29 | expect(t, c.Int("myflag"), 12)
30 | }
31 |
32 | func TestContext_Duration(t *testing.T) {
33 | set := flag.NewFlagSet("test", 0)
34 | set.Duration("myflag", time.Duration(12*time.Second), "doc")
35 | c := cli.NewContext(nil, set, nil)
36 | expect(t, c.Duration("myflag"), time.Duration(12*time.Second))
37 | }
38 |
39 | func TestContext_String(t *testing.T) {
40 | set := flag.NewFlagSet("test", 0)
41 | set.String("myflag", "hello world", "doc")
42 | c := cli.NewContext(nil, set, nil)
43 | expect(t, c.String("myflag"), "hello world")
44 | }
45 |
46 | func TestContext_Bool(t *testing.T) {
47 | set := flag.NewFlagSet("test", 0)
48 | set.Bool("myflag", false, "doc")
49 | c := cli.NewContext(nil, set, nil)
50 | expect(t, c.Bool("myflag"), false)
51 | }
52 |
53 | func TestContext_BoolT(t *testing.T) {
54 | set := flag.NewFlagSet("test", 0)
55 | set.Bool("myflag", true, "doc")
56 | c := cli.NewContext(nil, set, nil)
57 | expect(t, c.BoolT("myflag"), true)
58 | }
59 |
60 | func TestContext_Args(t *testing.T) {
61 | set := flag.NewFlagSet("test", 0)
62 | set.Bool("myflag", false, "doc")
63 | c := cli.NewContext(nil, set, nil)
64 | set.Parse([]string{"--myflag", "bat", "baz"})
65 | expect(t, len(c.Args()), 2)
66 | expect(t, c.Bool("myflag"), true)
67 | }
68 |
69 | func TestContext_IsSet(t *testing.T) {
70 | set := flag.NewFlagSet("test", 0)
71 | set.Bool("myflag", false, "doc")
72 | set.String("otherflag", "hello world", "doc")
73 | globalSet := flag.NewFlagSet("test", 0)
74 | globalSet.Bool("myflagGlobal", true, "doc")
75 | globalCtx := cli.NewContext(nil, globalSet, nil)
76 | c := cli.NewContext(nil, set, globalCtx)
77 | set.Parse([]string{"--myflag", "bat", "baz"})
78 | globalSet.Parse([]string{"--myflagGlobal", "bat", "baz"})
79 | expect(t, c.IsSet("myflag"), true)
80 | expect(t, c.IsSet("otherflag"), false)
81 | expect(t, c.IsSet("bogusflag"), false)
82 | expect(t, c.IsSet("myflagGlobal"), false)
83 | }
84 |
85 | func TestContext_GlobalIsSet(t *testing.T) {
86 | set := flag.NewFlagSet("test", 0)
87 | set.Bool("myflag", false, "doc")
88 | set.String("otherflag", "hello world", "doc")
89 | globalSet := flag.NewFlagSet("test", 0)
90 | globalSet.Bool("myflagGlobal", true, "doc")
91 | globalSet.Bool("myflagGlobalUnset", true, "doc")
92 | globalCtx := cli.NewContext(nil, globalSet, nil)
93 | c := cli.NewContext(nil, set, globalCtx)
94 | set.Parse([]string{"--myflag", "bat", "baz"})
95 | globalSet.Parse([]string{"--myflagGlobal", "bat", "baz"})
96 | expect(t, c.GlobalIsSet("myflag"), false)
97 | expect(t, c.GlobalIsSet("otherflag"), false)
98 | expect(t, c.GlobalIsSet("bogusflag"), false)
99 | expect(t, c.GlobalIsSet("myflagGlobal"), true)
100 | expect(t, c.GlobalIsSet("myflagGlobalUnset"), false)
101 | expect(t, c.GlobalIsSet("bogusGlobal"), false)
102 | }
103 |
104 | func TestContext_NumFlags(t *testing.T) {
105 | set := flag.NewFlagSet("test", 0)
106 | set.Bool("myflag", false, "doc")
107 | set.String("otherflag", "hello world", "doc")
108 | globalSet := flag.NewFlagSet("test", 0)
109 | globalSet.Bool("myflagGlobal", true, "doc")
110 | globalCtx := cli.NewContext(nil, globalSet, nil)
111 | c := cli.NewContext(nil, set, globalCtx)
112 | set.Parse([]string{"--myflag", "--otherflag=foo"})
113 | globalSet.Parse([]string{"--myflagGlobal"})
114 | expect(t, c.NumFlags(), 2)
115 | }
116 |
--------------------------------------------------------------------------------
/vendor/github.com/Sirupsen/logrus/text_formatter.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | import (
4 | "bytes"
5 | "fmt"
6 | "runtime"
7 | "sort"
8 | "strings"
9 | "time"
10 | )
11 |
12 | const (
13 | nocolor = 0
14 | red = 31
15 | green = 32
16 | yellow = 33
17 | blue = 34
18 | gray = 37
19 | )
20 |
21 | var (
22 | baseTimestamp time.Time
23 | isTerminal bool
24 | )
25 |
26 | func init() {
27 | baseTimestamp = time.Now()
28 | isTerminal = IsTerminal()
29 | }
30 |
31 | func miniTS() int {
32 | return int(time.Since(baseTimestamp) / time.Second)
33 | }
34 |
35 | type TextFormatter struct {
36 | // Set to true to bypass checking for a TTY before outputting colors.
37 | ForceColors bool
38 |
39 | // Force disabling colors.
40 | DisableColors bool
41 |
42 | // Disable timestamp logging. useful when output is redirected to logging
43 | // system that already adds timestamps.
44 | DisableTimestamp bool
45 |
46 | // Enable logging the full timestamp when a TTY is attached instead of just
47 | // the time passed since beginning of execution.
48 | FullTimestamp bool
49 |
50 | // TimestampFormat to use for display when a full timestamp is printed
51 | TimestampFormat string
52 |
53 | // The fields are sorted by default for a consistent output. For applications
54 | // that log extremely frequently and don't use the JSON formatter this may not
55 | // be desired.
56 | DisableSorting bool
57 | }
58 |
59 | func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
60 | var keys []string = make([]string, 0, len(entry.Data))
61 | for k := range entry.Data {
62 | keys = append(keys, k)
63 | }
64 |
65 | if !f.DisableSorting {
66 | sort.Strings(keys)
67 | }
68 |
69 | b := &bytes.Buffer{}
70 |
71 | prefixFieldClashes(entry.Data)
72 |
73 | isColorTerminal := isTerminal && (runtime.GOOS != "windows")
74 | isColored := (f.ForceColors || isColorTerminal) && !f.DisableColors
75 |
76 | timestampFormat := f.TimestampFormat
77 | if timestampFormat == "" {
78 | timestampFormat = DefaultTimestampFormat
79 | }
80 | if isColored {
81 | f.printColored(b, entry, keys, timestampFormat)
82 | } else {
83 | if !f.DisableTimestamp {
84 | f.appendKeyValue(b, "time", entry.Time.Format(timestampFormat))
85 | }
86 | f.appendKeyValue(b, "level", entry.Level.String())
87 | f.appendKeyValue(b, "msg", entry.Message)
88 | for _, key := range keys {
89 | f.appendKeyValue(b, key, entry.Data[key])
90 | }
91 | }
92 |
93 | b.WriteByte('\n')
94 | return b.Bytes(), nil
95 | }
96 |
97 | func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, timestampFormat string) {
98 | var levelColor int
99 | switch entry.Level {
100 | case DebugLevel:
101 | levelColor = gray
102 | case WarnLevel:
103 | levelColor = yellow
104 | case ErrorLevel, FatalLevel, PanicLevel:
105 | levelColor = red
106 | default:
107 | levelColor = blue
108 | }
109 |
110 | levelText := strings.ToUpper(entry.Level.String())[0:4]
111 |
112 | if !f.FullTimestamp {
113 | fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, miniTS(), entry.Message)
114 | } else {
115 | fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), entry.Message)
116 | }
117 | for _, k := range keys {
118 | v := entry.Data[k]
119 | fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=%+v", levelColor, k, v)
120 | }
121 | }
122 |
123 | func needsQuoting(text string) bool {
124 | for _, ch := range text {
125 | if !((ch >= 'a' && ch <= 'z') ||
126 | (ch >= 'A' && ch <= 'Z') ||
127 | (ch >= '0' && ch <= '9') ||
128 | ch == '-' || ch == '.') {
129 | return false
130 | }
131 | }
132 | return true
133 | }
134 |
135 | func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) {
136 |
137 | b.WriteString(key)
138 | b.WriteByte('=')
139 |
140 | switch value := value.(type) {
141 | case string:
142 | if needsQuoting(value) {
143 | b.WriteString(value)
144 | } else {
145 | fmt.Fprintf(b, "%q", value)
146 | }
147 | case error:
148 | errmsg := value.Error()
149 | if needsQuoting(errmsg) {
150 | b.WriteString(errmsg)
151 | } else {
152 | fmt.Fprintf(b, "%q", value)
153 | }
154 | default:
155 | fmt.Fprint(b, value)
156 | }
157 |
158 | b.WriteByte(' ')
159 | }
160 |
--------------------------------------------------------------------------------
/pkg/config/config.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | "io"
7 | "io/ioutil"
8 | "os"
9 | "path"
10 | "path/filepath"
11 | "strings"
12 |
13 | "github.com/moul/advanced-ssh-config/vendor/github.com/Sirupsen/logrus"
14 | "github.com/moul/advanced-ssh-config/vendor/gopkg.in/yaml.v2"
15 | )
16 |
17 | // Config contains a list of Hosts sections and a Defaults section representing a configuration file
18 | type Config struct {
19 | Hosts map[string]Host `json:"hosts"`
20 | Defaults Host `json:"defaults",omitempty`
21 | Includes []string `json:"includes",omitempty`
22 |
23 | includedFiles map[string]bool
24 | }
25 |
26 | // JsonString returns a string representing the JSON of a Config object
27 | func (c *Config) JsonString() error {
28 | output, err := json.MarshalIndent(c, "", " ")
29 | if err != nil {
30 | return err
31 | }
32 | fmt.Fprintf(os.Stderr, "%s\n", output)
33 | return nil
34 | }
35 |
36 | func (c *Config) getHostByName(name string, safe bool) (*Host, error) {
37 | if host, ok := c.Hosts[name]; ok {
38 | var computedHost Host = host
39 | computedHost.ApplyDefaults(&c.Defaults)
40 | computedHost.Name = name
41 | return &computedHost, nil
42 | }
43 |
44 | for pattern, host := range c.Hosts {
45 | matched, err := path.Match(pattern, name)
46 | if err != nil {
47 | return nil, err
48 | }
49 | if matched {
50 | var computedHost Host = host
51 | computedHost.ApplyDefaults(&c.Defaults)
52 | computedHost.Name = name
53 | return &computedHost, nil
54 | }
55 | }
56 |
57 | if safe {
58 | host := &Host{
59 | Host: name,
60 | Name: name,
61 | }
62 | host.ApplyDefaults(&c.Defaults)
63 | return host, nil
64 | }
65 |
66 | return nil, fmt.Errorf("no such host: %s", name)
67 | }
68 |
69 | func (c *Config) getHostByPath(path string, safe bool) (*Host, error) {
70 | parts := strings.SplitN(path, "/", 2)
71 |
72 | host, err := c.getHostByName(parts[0], safe)
73 | if err != nil {
74 | return nil, err
75 | }
76 |
77 | if len(parts) > 1 {
78 | host.Gateways = []string{parts[1]}
79 | }
80 |
81 | return host, nil
82 | }
83 |
84 | // GetGatewaySafe returns gateway Host configuration, a gateway is like a Host, except, the host path is not resolved
85 | func (c *Config) GetGatewaySafe(name string) *Host {
86 | host, err := c.getHostByName(name, true)
87 | if err != nil {
88 | panic(err)
89 | }
90 | return host
91 | }
92 |
93 | // GetHost returns a matching host form Config hosts list
94 | func (c *Config) GetHost(name string) (*Host, error) {
95 | return c.getHostByPath(name, false)
96 | }
97 |
98 | // GetHostSafe won't fail, in case the host is not found, it will returns a virtual host matching the pattern
99 | func (c *Config) GetHostSafe(name string) *Host {
100 | host, err := c.getHostByPath(name, true)
101 | if err != nil {
102 | panic(err)
103 | }
104 | return host
105 | }
106 |
107 | // LoadConfig loads the content of an io.Reader source
108 | func (c *Config) LoadConfig(source io.Reader) error {
109 | buf, err := ioutil.ReadAll(source)
110 | if err != nil {
111 | return err
112 | }
113 | return yaml.Unmarshal(buf, &c)
114 | }
115 |
116 | // LoadFile loads the content of a configuration file in the Config object
117 | func (c *Config) LoadFile(filename string) error {
118 | // Resolve '~' and '$HOME'
119 | filepath, err := expandUser(filename)
120 | if err != nil {
121 | return err
122 | }
123 | logrus.Debugf("Loading config file '%s'", filepath)
124 |
125 | // Anti-loop protection
126 | if _, ok := c.includedFiles[filepath]; ok {
127 | logrus.Debugf("File %s already loaded", filepath)
128 | return nil
129 | }
130 | c.includedFiles[filepath] = false
131 |
132 | // Read file
133 | source, err := os.Open(filepath)
134 | if err != nil {
135 | return err
136 | }
137 |
138 | // Load config stream
139 | err = c.LoadConfig(source)
140 | if err != nil {
141 | return err
142 | }
143 |
144 | // Successful loading
145 | c.includedFiles[filepath] = true
146 |
147 | // Handling includes
148 | for _, include := range c.Includes {
149 | c.LoadFiles(include)
150 | }
151 |
152 | return nil
153 | }
154 |
155 | // Loadfiles will try to glob the pattern and load each maching entries
156 | func (c *Config) LoadFiles(pattern string) error {
157 | // Resolve '~' and '$HOME'
158 | expandedPattern, err := expandUser(pattern)
159 | if err != nil {
160 | return err
161 | }
162 |
163 | // Globbing
164 | filepaths, err := filepath.Glob(expandedPattern)
165 | if err != nil {
166 | return err
167 | }
168 |
169 | // Load files iteratively
170 | for _, filepath := range filepaths {
171 | err := c.LoadFile(filepath)
172 | if err != nil {
173 | return err
174 | }
175 | }
176 |
177 | return nil
178 | }
179 |
180 | // New returns an instantiated Config object
181 | func New() *Config {
182 | var config Config
183 | config.Hosts = make(map[string]Host)
184 | config.includedFiles = make(map[string]bool)
185 | return &config
186 | }
187 |
188 | // Open returns a Config object loaded with standard configuration file paths
189 | func Open() (*Config, error) {
190 | config := New()
191 | err := config.LoadFile("~/.ssh/assh.yml")
192 | if err != nil {
193 | return nil, err
194 | }
195 | return config, nil
196 | }
197 |
--------------------------------------------------------------------------------
/vendor/github.com/flynn/go-shlex/shlex_test.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2012 Google Inc. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package shlex
18 |
19 | import (
20 | "strings"
21 | "testing"
22 | )
23 |
24 | func checkError(err error, t *testing.T) {
25 | if err != nil {
26 | t.Error(err)
27 | }
28 | }
29 |
30 | func TestClassifier(t *testing.T) {
31 | classifier := NewDefaultClassifier()
32 | runeTests := map[int32]RuneTokenType{
33 | 'a': RUNETOKEN_CHAR,
34 | ' ': RUNETOKEN_SPACE,
35 | '"': RUNETOKEN_ESCAPING_QUOTE,
36 | '\'': RUNETOKEN_NONESCAPING_QUOTE,
37 | '#': RUNETOKEN_COMMENT}
38 | for rune, expectedType := range runeTests {
39 | foundType := classifier.ClassifyRune(rune)
40 | if foundType != expectedType {
41 | t.Logf("Expected type: %v for rune '%c'(%v). Found type: %v.", expectedType, rune, rune, foundType)
42 | t.Fail()
43 | }
44 | }
45 | }
46 |
47 | func TestTokenizer(t *testing.T) {
48 | testInput := strings.NewReader("one two \"three four\" \"five \\\"six\\\"\" seven#eight # nine # ten\n eleven")
49 | expectedTokens := []*Token{
50 | &Token{
51 | tokenType: TOKEN_WORD,
52 | value: "one"},
53 | &Token{
54 | tokenType: TOKEN_WORD,
55 | value: "two"},
56 | &Token{
57 | tokenType: TOKEN_WORD,
58 | value: "three four"},
59 | &Token{
60 | tokenType: TOKEN_WORD,
61 | value: "five \"six\""},
62 | &Token{
63 | tokenType: TOKEN_WORD,
64 | value: "seven#eight"},
65 | &Token{
66 | tokenType: TOKEN_COMMENT,
67 | value: " nine # ten"},
68 | &Token{
69 | tokenType: TOKEN_WORD,
70 | value: "eleven"}}
71 |
72 | tokenizer, err := NewTokenizer(testInput)
73 | checkError(err, t)
74 | for _, expectedToken := range expectedTokens {
75 | foundToken, err := tokenizer.NextToken()
76 | checkError(err, t)
77 | if !foundToken.Equal(expectedToken) {
78 | t.Error("Expected token:", expectedToken, ". Found:", foundToken)
79 | }
80 | }
81 | }
82 |
83 | func TestLexer(t *testing.T) {
84 | testInput := strings.NewReader("one")
85 | expectedWord := "one"
86 | lexer, err := NewLexer(testInput)
87 | checkError(err, t)
88 | foundWord, err := lexer.NextWord()
89 | checkError(err, t)
90 | if expectedWord != foundWord {
91 | t.Error("Expected word:", expectedWord, ". Found:", foundWord)
92 | }
93 | }
94 |
95 | func TestSplitSimple(t *testing.T) {
96 | testInput := "one two three"
97 | expectedOutput := []string{"one", "two", "three"}
98 | foundOutput, err := Split(testInput)
99 | if err != nil {
100 | t.Error("Split returned error:", err)
101 | }
102 | if len(expectedOutput) != len(foundOutput) {
103 | t.Error("Split expected:", len(expectedOutput), "results. Found:", len(foundOutput), "results")
104 | }
105 | for i := range foundOutput {
106 | if foundOutput[i] != expectedOutput[i] {
107 | t.Error("Item:", i, "(", foundOutput[i], ") differs from the expected value:", expectedOutput[i])
108 | }
109 | }
110 | }
111 |
112 | func TestSplitEscapingQuotes(t *testing.T) {
113 | testInput := "one \"два ${three}\" four"
114 | expectedOutput := []string{"one", "два ${three}", "four"}
115 | foundOutput, err := Split(testInput)
116 | if err != nil {
117 | t.Error("Split returned error:", err)
118 | }
119 | if len(expectedOutput) != len(foundOutput) {
120 | t.Error("Split expected:", len(expectedOutput), "results. Found:", len(foundOutput), "results")
121 | }
122 | for i := range foundOutput {
123 | if foundOutput[i] != expectedOutput[i] {
124 | t.Error("Item:", i, "(", foundOutput[i], ") differs from the expected value:", expectedOutput[i])
125 | }
126 | }
127 | }
128 |
129 | func TestGlobbingExpressions(t *testing.T) {
130 | testInput := "onefile *file one?ile onefil[de]"
131 | expectedOutput := []string{"onefile", "*file", "one?ile", "onefil[de]"}
132 | foundOutput, err := Split(testInput)
133 | if err != nil {
134 | t.Error("Split returned error", err)
135 | }
136 | if len(expectedOutput) != len(foundOutput) {
137 | t.Error("Split expected:", len(expectedOutput), "results. Found:", len(foundOutput), "results")
138 | }
139 | for i := range foundOutput {
140 | if foundOutput[i] != expectedOutput[i] {
141 | t.Error("Item:", i, "(", foundOutput[i], ") differs from the expected value:", expectedOutput[i])
142 | }
143 | }
144 |
145 | }
146 |
147 | func TestSplitNonEscapingQuotes(t *testing.T) {
148 | testInput := "one 'два ${three}' four"
149 | expectedOutput := []string{"one", "два ${three}", "four"}
150 | foundOutput, err := Split(testInput)
151 | if err != nil {
152 | t.Error("Split returned error:", err)
153 | }
154 | if len(expectedOutput) != len(foundOutput) {
155 | t.Error("Split expected:", len(expectedOutput), "results. Found:", len(foundOutput), "results")
156 | }
157 | for i := range foundOutput {
158 | if foundOutput[i] != expectedOutput[i] {
159 | t.Error("Item:", i, "(", foundOutput[i], ") differs from the expected value:", expectedOutput[i])
160 | }
161 | }
162 | }
163 |
--------------------------------------------------------------------------------
/vendor/github.com/Sirupsen/logrus/exported.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | import (
4 | "io"
5 | )
6 |
7 | var (
8 | // std is the name of the standard logger in stdlib `log`
9 | std = New()
10 | )
11 |
12 | func StandardLogger() *Logger {
13 | return std
14 | }
15 |
16 | // SetOutput sets the standard logger output.
17 | func SetOutput(out io.Writer) {
18 | std.mu.Lock()
19 | defer std.mu.Unlock()
20 | std.Out = out
21 | }
22 |
23 | // SetFormatter sets the standard logger formatter.
24 | func SetFormatter(formatter Formatter) {
25 | std.mu.Lock()
26 | defer std.mu.Unlock()
27 | std.Formatter = formatter
28 | }
29 |
30 | // SetLevel sets the standard logger level.
31 | func SetLevel(level Level) {
32 | std.mu.Lock()
33 | defer std.mu.Unlock()
34 | std.Level = level
35 | }
36 |
37 | // GetLevel returns the standard logger level.
38 | func GetLevel() Level {
39 | std.mu.Lock()
40 | defer std.mu.Unlock()
41 | return std.Level
42 | }
43 |
44 | // AddHook adds a hook to the standard logger hooks.
45 | func AddHook(hook Hook) {
46 | std.mu.Lock()
47 | defer std.mu.Unlock()
48 | std.Hooks.Add(hook)
49 | }
50 |
51 | // WithField creates an entry from the standard logger and adds a field to
52 | // it. If you want multiple fields, use `WithFields`.
53 | //
54 | // Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
55 | // or Panic on the Entry it returns.
56 | func WithField(key string, value interface{}) *Entry {
57 | return std.WithField(key, value)
58 | }
59 |
60 | // WithFields creates an entry from the standard logger and adds multiple
61 | // fields to it. This is simply a helper for `WithField`, invoking it
62 | // once for each field.
63 | //
64 | // Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
65 | // or Panic on the Entry it returns.
66 | func WithFields(fields Fields) *Entry {
67 | return std.WithFields(fields)
68 | }
69 |
70 | // Debug logs a message at level Debug on the standard logger.
71 | func Debug(args ...interface{}) {
72 | std.Debug(args...)
73 | }
74 |
75 | // Print logs a message at level Info on the standard logger.
76 | func Print(args ...interface{}) {
77 | std.Print(args...)
78 | }
79 |
80 | // Info logs a message at level Info on the standard logger.
81 | func Info(args ...interface{}) {
82 | std.Info(args...)
83 | }
84 |
85 | // Warn logs a message at level Warn on the standard logger.
86 | func Warn(args ...interface{}) {
87 | std.Warn(args...)
88 | }
89 |
90 | // Warning logs a message at level Warn on the standard logger.
91 | func Warning(args ...interface{}) {
92 | std.Warning(args...)
93 | }
94 |
95 | // Error logs a message at level Error on the standard logger.
96 | func Error(args ...interface{}) {
97 | std.Error(args...)
98 | }
99 |
100 | // Panic logs a message at level Panic on the standard logger.
101 | func Panic(args ...interface{}) {
102 | std.Panic(args...)
103 | }
104 |
105 | // Fatal logs a message at level Fatal on the standard logger.
106 | func Fatal(args ...interface{}) {
107 | std.Fatal(args...)
108 | }
109 |
110 | // Debugf logs a message at level Debug on the standard logger.
111 | func Debugf(format string, args ...interface{}) {
112 | std.Debugf(format, args...)
113 | }
114 |
115 | // Printf logs a message at level Info on the standard logger.
116 | func Printf(format string, args ...interface{}) {
117 | std.Printf(format, args...)
118 | }
119 |
120 | // Infof logs a message at level Info on the standard logger.
121 | func Infof(format string, args ...interface{}) {
122 | std.Infof(format, args...)
123 | }
124 |
125 | // Warnf logs a message at level Warn on the standard logger.
126 | func Warnf(format string, args ...interface{}) {
127 | std.Warnf(format, args...)
128 | }
129 |
130 | // Warningf logs a message at level Warn on the standard logger.
131 | func Warningf(format string, args ...interface{}) {
132 | std.Warningf(format, args...)
133 | }
134 |
135 | // Errorf logs a message at level Error on the standard logger.
136 | func Errorf(format string, args ...interface{}) {
137 | std.Errorf(format, args...)
138 | }
139 |
140 | // Panicf logs a message at level Panic on the standard logger.
141 | func Panicf(format string, args ...interface{}) {
142 | std.Panicf(format, args...)
143 | }
144 |
145 | // Fatalf logs a message at level Fatal on the standard logger.
146 | func Fatalf(format string, args ...interface{}) {
147 | std.Fatalf(format, args...)
148 | }
149 |
150 | // Debugln logs a message at level Debug on the standard logger.
151 | func Debugln(args ...interface{}) {
152 | std.Debugln(args...)
153 | }
154 |
155 | // Println logs a message at level Info on the standard logger.
156 | func Println(args ...interface{}) {
157 | std.Println(args...)
158 | }
159 |
160 | // Infoln logs a message at level Info on the standard logger.
161 | func Infoln(args ...interface{}) {
162 | std.Infoln(args...)
163 | }
164 |
165 | // Warnln logs a message at level Warn on the standard logger.
166 | func Warnln(args ...interface{}) {
167 | std.Warnln(args...)
168 | }
169 |
170 | // Warningln logs a message at level Warn on the standard logger.
171 | func Warningln(args ...interface{}) {
172 | std.Warningln(args...)
173 | }
174 |
175 | // Errorln logs a message at level Error on the standard logger.
176 | func Errorln(args ...interface{}) {
177 | std.Errorln(args...)
178 | }
179 |
180 | // Panicln logs a message at level Panic on the standard logger.
181 | func Panicln(args ...interface{}) {
182 | std.Panicln(args...)
183 | }
184 |
185 | // Fatalln logs a message at level Fatal on the standard logger.
186 | func Fatalln(args ...interface{}) {
187 | std.Fatalln(args...)
188 | }
189 |
--------------------------------------------------------------------------------
/vendor/github.com/stretchr/testify/assert/doc.go:
--------------------------------------------------------------------------------
1 | // Package assert provides a set of comprehensive testing tools for use with the normal Go testing system.
2 | //
3 | // Example Usage
4 | //
5 | // The following is a complete example using assert in a standard test function:
6 | // import (
7 | // "testing"
8 | // "github.com/stretchr/testify/assert"
9 | // )
10 | //
11 | // func TestSomething(t *testing.T) {
12 | //
13 | // var a string = "Hello"
14 | // var b string = "Hello"
15 | //
16 | // assert.Equal(t, a, b, "The two words should be the same.")
17 | //
18 | // }
19 | //
20 | // if you assert many times, use the below:
21 | //
22 | // import (
23 | // "testing"
24 | // "github.com/stretchr/testify/assert"
25 | // )
26 | //
27 | // func TestSomething(t *testing.T) {
28 | // assert := assert.New(t)
29 | //
30 | // var a string = "Hello"
31 | // var b string = "Hello"
32 | //
33 | // assert.Equal(a, b, "The two words should be the same.")
34 | // }
35 | //
36 | // Assertions
37 | //
38 | // Assertions allow you to easily write test code, and are global funcs in the `assert` package.
39 | // All assertion functions take, as the first argument, the `*testing.T` object provided by the
40 | // testing framework. This allows the assertion funcs to write the failings and other details to
41 | // the correct place.
42 | //
43 | // Every assertion function also takes an optional string message as the final argument,
44 | // allowing custom error messages to be appended to the message the assertion method outputs.
45 | //
46 | // Here is an overview of the assert functions:
47 | //
48 | // assert.Equal(t, expected, actual [, message [, format-args]])
49 | //
50 | // assert.EqualValues(t, expected, actual [, message [, format-args]])
51 | //
52 | // assert.NotEqual(t, notExpected, actual [, message [, format-args]])
53 | //
54 | // assert.True(t, actualBool [, message [, format-args]])
55 | //
56 | // assert.False(t, actualBool [, message [, format-args]])
57 | //
58 | // assert.Nil(t, actualObject [, message [, format-args]])
59 | //
60 | // assert.NotNil(t, actualObject [, message [, format-args]])
61 | //
62 | // assert.Empty(t, actualObject [, message [, format-args]])
63 | //
64 | // assert.NotEmpty(t, actualObject [, message [, format-args]])
65 | //
66 | // assert.Len(t, actualObject, expectedLength, [, message [, format-args]])
67 | //
68 | // assert.Error(t, errorObject [, message [, format-args]])
69 | //
70 | // assert.NoError(t, errorObject [, message [, format-args]])
71 | //
72 | // assert.EqualError(t, theError, errString [, message [, format-args]])
73 | //
74 | // assert.Implements(t, (*MyInterface)(nil), new(MyObject) [,message [, format-args]])
75 | //
76 | // assert.IsType(t, expectedObject, actualObject [, message [, format-args]])
77 | //
78 | // assert.Contains(t, stringOrSlice, substringOrElement [, message [, format-args]])
79 | //
80 | // assert.NotContains(t, stringOrSlice, substringOrElement [, message [, format-args]])
81 | //
82 | // assert.Panics(t, func(){
83 | //
84 | // // call code that should panic
85 | //
86 | // } [, message [, format-args]])
87 | //
88 | // assert.NotPanics(t, func(){
89 | //
90 | // // call code that should not panic
91 | //
92 | // } [, message [, format-args]])
93 | //
94 | // assert.WithinDuration(t, timeA, timeB, deltaTime, [, message [, format-args]])
95 | //
96 | // assert.InDelta(t, numA, numB, delta, [, message [, format-args]])
97 | //
98 | // assert.InEpsilon(t, numA, numB, epsilon, [, message [, format-args]])
99 | //
100 | // assert package contains Assertions object. it has assertion methods.
101 | //
102 | // Here is an overview of the assert functions:
103 | // assert.Equal(expected, actual [, message [, format-args]])
104 | //
105 | // assert.EqualValues(expected, actual [, message [, format-args]])
106 | //
107 | // assert.NotEqual(notExpected, actual [, message [, format-args]])
108 | //
109 | // assert.True(actualBool [, message [, format-args]])
110 | //
111 | // assert.False(actualBool [, message [, format-args]])
112 | //
113 | // assert.Nil(actualObject [, message [, format-args]])
114 | //
115 | // assert.NotNil(actualObject [, message [, format-args]])
116 | //
117 | // assert.Empty(actualObject [, message [, format-args]])
118 | //
119 | // assert.NotEmpty(actualObject [, message [, format-args]])
120 | //
121 | // assert.Len(actualObject, expectedLength, [, message [, format-args]])
122 | //
123 | // assert.Error(errorObject [, message [, format-args]])
124 | //
125 | // assert.NoError(errorObject [, message [, format-args]])
126 | //
127 | // assert.EqualError(theError, errString [, message [, format-args]])
128 | //
129 | // assert.Implements((*MyInterface)(nil), new(MyObject) [,message [, format-args]])
130 | //
131 | // assert.IsType(expectedObject, actualObject [, message [, format-args]])
132 | //
133 | // assert.Contains(stringOrSlice, substringOrElement [, message [, format-args]])
134 | //
135 | // assert.NotContains(stringOrSlice, substringOrElement [, message [, format-args]])
136 | //
137 | // assert.Panics(func(){
138 | //
139 | // // call code that should panic
140 | //
141 | // } [, message [, format-args]])
142 | //
143 | // assert.NotPanics(func(){
144 | //
145 | // // call code that should not panic
146 | //
147 | // } [, message [, format-args]])
148 | //
149 | // assert.WithinDuration(timeA, timeB, deltaTime, [, message [, format-args]])
150 | //
151 | // assert.InDelta(numA, numB, delta, [, message [, format-args]])
152 | //
153 | // assert.InEpsilon(numA, numB, epsilon, [, message [, format-args]])
154 | package assert
155 |
--------------------------------------------------------------------------------
/vendor/github.com/codegangsta/cli/command.go:
--------------------------------------------------------------------------------
1 | package cli
2 |
3 | import (
4 | "fmt"
5 | "io/ioutil"
6 | "strings"
7 | )
8 |
9 | // Command is a subcommand for a cli.App.
10 | type Command struct {
11 | // The name of the command
12 | Name string
13 | // short name of the command. Typically one character (deprecated, use `Aliases`)
14 | ShortName string
15 | // A list of aliases for the command
16 | Aliases []string
17 | // A short description of the usage of this command
18 | Usage string
19 | // A longer explanation of how the command works
20 | Description string
21 | // The function to call when checking for bash command completions
22 | BashComplete func(context *Context)
23 | // An action to execute before any sub-subcommands are run, but after the context is ready
24 | // If a non-nil error is returned, no sub-subcommands are run
25 | Before func(context *Context) error
26 | // An action to execute after any subcommands are run, but after the subcommand has finished
27 | // It is run even if Action() panics
28 | After func(context *Context) error
29 | // The function to call when this command is invoked
30 | Action func(context *Context)
31 | // List of child commands
32 | Subcommands []Command
33 | // List of flags to parse
34 | Flags []Flag
35 | // Treat all flags as normal arguments if true
36 | SkipFlagParsing bool
37 | // Boolean to hide built-in help command
38 | HideHelp bool
39 |
40 | commandNamePath []string
41 | }
42 |
43 | // Returns the full name of the command.
44 | // For subcommands this ensures that parent commands are part of the command path
45 | func (c Command) FullName() string {
46 | if c.commandNamePath == nil {
47 | return c.Name
48 | }
49 | return strings.Join(c.commandNamePath, " ")
50 | }
51 |
52 | // Invokes the command given the context, parses ctx.Args() to generate command-specific flags
53 | func (c Command) Run(ctx *Context) error {
54 | if len(c.Subcommands) > 0 || c.Before != nil || c.After != nil {
55 | return c.startApp(ctx)
56 | }
57 |
58 | if !c.HideHelp && (HelpFlag != BoolFlag{}) {
59 | // append help to flags
60 | c.Flags = append(
61 | c.Flags,
62 | HelpFlag,
63 | )
64 | }
65 |
66 | if ctx.App.EnableBashCompletion {
67 | c.Flags = append(c.Flags, BashCompletionFlag)
68 | }
69 |
70 | set := flagSet(c.Name, c.Flags)
71 | set.SetOutput(ioutil.Discard)
72 |
73 | firstFlagIndex := -1
74 | terminatorIndex := -1
75 | for index, arg := range ctx.Args() {
76 | if arg == "--" {
77 | terminatorIndex = index
78 | break
79 | } else if strings.HasPrefix(arg, "-") && firstFlagIndex == -1 {
80 | firstFlagIndex = index
81 | }
82 | }
83 |
84 | var err error
85 | if firstFlagIndex > -1 && !c.SkipFlagParsing {
86 | args := ctx.Args()
87 | regularArgs := make([]string, len(args[1:firstFlagIndex]))
88 | copy(regularArgs, args[1:firstFlagIndex])
89 |
90 | var flagArgs []string
91 | if terminatorIndex > -1 {
92 | flagArgs = args[firstFlagIndex:terminatorIndex]
93 | regularArgs = append(regularArgs, args[terminatorIndex:]...)
94 | } else {
95 | flagArgs = args[firstFlagIndex:]
96 | }
97 |
98 | err = set.Parse(append(flagArgs, regularArgs...))
99 | } else {
100 | err = set.Parse(ctx.Args().Tail())
101 | }
102 |
103 | if err != nil {
104 | fmt.Fprintln(ctx.App.Writer, "Incorrect Usage.")
105 | fmt.Fprintln(ctx.App.Writer)
106 | ShowCommandHelp(ctx, c.Name)
107 | return err
108 | }
109 |
110 | nerr := normalizeFlags(c.Flags, set)
111 | if nerr != nil {
112 | fmt.Fprintln(ctx.App.Writer, nerr)
113 | fmt.Fprintln(ctx.App.Writer)
114 | ShowCommandHelp(ctx, c.Name)
115 | return nerr
116 | }
117 | context := NewContext(ctx.App, set, ctx)
118 |
119 | if checkCommandCompletions(context, c.Name) {
120 | return nil
121 | }
122 |
123 | if checkCommandHelp(context, c.Name) {
124 | return nil
125 | }
126 | context.Command = c
127 | c.Action(context)
128 | return nil
129 | }
130 |
131 | func (c Command) Names() []string {
132 | names := []string{c.Name}
133 |
134 | if c.ShortName != "" {
135 | names = append(names, c.ShortName)
136 | }
137 |
138 | return append(names, c.Aliases...)
139 | }
140 |
141 | // Returns true if Command.Name or Command.ShortName matches given name
142 | func (c Command) HasName(name string) bool {
143 | for _, n := range c.Names() {
144 | if n == name {
145 | return true
146 | }
147 | }
148 | return false
149 | }
150 |
151 | func (c Command) startApp(ctx *Context) error {
152 | app := NewApp()
153 |
154 | // set the name and usage
155 | app.Name = fmt.Sprintf("%s %s", ctx.App.Name, c.Name)
156 | if c.Description != "" {
157 | app.Usage = c.Description
158 | } else {
159 | app.Usage = c.Usage
160 | }
161 |
162 | // set CommandNotFound
163 | app.CommandNotFound = ctx.App.CommandNotFound
164 |
165 | // set the flags and commands
166 | app.Commands = c.Subcommands
167 | app.Flags = c.Flags
168 | app.HideHelp = c.HideHelp
169 |
170 | app.Version = ctx.App.Version
171 | app.HideVersion = ctx.App.HideVersion
172 | app.Compiled = ctx.App.Compiled
173 | app.Author = ctx.App.Author
174 | app.Email = ctx.App.Email
175 | app.Writer = ctx.App.Writer
176 |
177 | // bash completion
178 | app.EnableBashCompletion = ctx.App.EnableBashCompletion
179 | if c.BashComplete != nil {
180 | app.BashComplete = c.BashComplete
181 | }
182 |
183 | // set the actions
184 | app.Before = c.Before
185 | app.After = c.After
186 | if c.Action != nil {
187 | app.Action = c.Action
188 | } else {
189 | app.Action = helpSubcommand.Action
190 | }
191 |
192 | var newCmds []Command
193 | for _, cc := range app.Commands {
194 | cc.commandNamePath = []string{c.Name, cc.Name}
195 | newCmds = append(newCmds, cc)
196 | }
197 | app.Commands = newCmds
198 |
199 | return app.RunAsSubcommand(ctx)
200 | }
201 |
--------------------------------------------------------------------------------
/vendor/gopkg.in/yaml.v2/yamlprivateh.go:
--------------------------------------------------------------------------------
1 | package yaml
2 |
3 | const (
4 | // The size of the input raw buffer.
5 | input_raw_buffer_size = 512
6 |
7 | // The size of the input buffer.
8 | // It should be possible to decode the whole raw buffer.
9 | input_buffer_size = input_raw_buffer_size * 3
10 |
11 | // The size of the output buffer.
12 | output_buffer_size = 128
13 |
14 | // The size of the output raw buffer.
15 | // It should be possible to encode the whole output buffer.
16 | output_raw_buffer_size = (output_buffer_size*2 + 2)
17 |
18 | // The size of other stacks and queues.
19 | initial_stack_size = 16
20 | initial_queue_size = 16
21 | initial_string_size = 16
22 | )
23 |
24 | // Check if the character at the specified position is an alphabetical
25 | // character, a digit, '_', or '-'.
26 | func is_alpha(b []byte, i int) bool {
27 | return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-'
28 | }
29 |
30 | // Check if the character at the specified position is a digit.
31 | func is_digit(b []byte, i int) bool {
32 | return b[i] >= '0' && b[i] <= '9'
33 | }
34 |
35 | // Get the value of a digit.
36 | func as_digit(b []byte, i int) int {
37 | return int(b[i]) - '0'
38 | }
39 |
40 | // Check if the character at the specified position is a hex-digit.
41 | func is_hex(b []byte, i int) bool {
42 | return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f'
43 | }
44 |
45 | // Get the value of a hex-digit.
46 | func as_hex(b []byte, i int) int {
47 | bi := b[i]
48 | if bi >= 'A' && bi <= 'F' {
49 | return int(bi) - 'A' + 10
50 | }
51 | if bi >= 'a' && bi <= 'f' {
52 | return int(bi) - 'a' + 10
53 | }
54 | return int(bi) - '0'
55 | }
56 |
57 | // Check if the character is ASCII.
58 | func is_ascii(b []byte, i int) bool {
59 | return b[i] <= 0x7F
60 | }
61 |
62 | // Check if the character at the start of the buffer can be printed unescaped.
63 | func is_printable(b []byte, i int) bool {
64 | return ((b[i] == 0x0A) || // . == #x0A
65 | (b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E
66 | (b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF
67 | (b[i] > 0xC2 && b[i] < 0xED) ||
68 | (b[i] == 0xED && b[i+1] < 0xA0) ||
69 | (b[i] == 0xEE) ||
70 | (b[i] == 0xEF && // #xE000 <= . <= #xFFFD
71 | !(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF
72 | !(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF))))
73 | }
74 |
75 | // Check if the character at the specified position is NUL.
76 | func is_z(b []byte, i int) bool {
77 | return b[i] == 0x00
78 | }
79 |
80 | // Check if the beginning of the buffer is a BOM.
81 | func is_bom(b []byte, i int) bool {
82 | return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF
83 | }
84 |
85 | // Check if the character at the specified position is space.
86 | func is_space(b []byte, i int) bool {
87 | return b[i] == ' '
88 | }
89 |
90 | // Check if the character at the specified position is tab.
91 | func is_tab(b []byte, i int) bool {
92 | return b[i] == '\t'
93 | }
94 |
95 | // Check if the character at the specified position is blank (space or tab).
96 | func is_blank(b []byte, i int) bool {
97 | //return is_space(b, i) || is_tab(b, i)
98 | return b[i] == ' ' || b[i] == '\t'
99 | }
100 |
101 | // Check if the character at the specified position is a line break.
102 | func is_break(b []byte, i int) bool {
103 | return (b[i] == '\r' || // CR (#xD)
104 | b[i] == '\n' || // LF (#xA)
105 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
106 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
107 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029)
108 | }
109 |
110 | func is_crlf(b []byte, i int) bool {
111 | return b[i] == '\r' && b[i+1] == '\n'
112 | }
113 |
114 | // Check if the character is a line break or NUL.
115 | func is_breakz(b []byte, i int) bool {
116 | //return is_break(b, i) || is_z(b, i)
117 | return ( // is_break:
118 | b[i] == '\r' || // CR (#xD)
119 | b[i] == '\n' || // LF (#xA)
120 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
121 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
122 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
123 | // is_z:
124 | b[i] == 0)
125 | }
126 |
127 | // Check if the character is a line break, space, or NUL.
128 | func is_spacez(b []byte, i int) bool {
129 | //return is_space(b, i) || is_breakz(b, i)
130 | return ( // is_space:
131 | b[i] == ' ' ||
132 | // is_breakz:
133 | b[i] == '\r' || // CR (#xD)
134 | b[i] == '\n' || // LF (#xA)
135 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
136 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
137 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
138 | b[i] == 0)
139 | }
140 |
141 | // Check if the character is a line break, space, tab, or NUL.
142 | func is_blankz(b []byte, i int) bool {
143 | //return is_blank(b, i) || is_breakz(b, i)
144 | return ( // is_blank:
145 | b[i] == ' ' || b[i] == '\t' ||
146 | // is_breakz:
147 | b[i] == '\r' || // CR (#xD)
148 | b[i] == '\n' || // LF (#xA)
149 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
150 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
151 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
152 | b[i] == 0)
153 | }
154 |
155 | // Determine the width of the character.
156 | func width(b byte) int {
157 | // Don't replace these by a switch without first
158 | // confirming that it is being inlined.
159 | if b&0x80 == 0x00 {
160 | return 1
161 | }
162 | if b&0xE0 == 0xC0 {
163 | return 2
164 | }
165 | if b&0xF0 == 0xE0 {
166 | return 3
167 | }
168 | if b&0xF8 == 0xF0 {
169 | return 4
170 | }
171 | return 0
172 |
173 | }
174 |
--------------------------------------------------------------------------------
/pkg/commands/proxy.go:
--------------------------------------------------------------------------------
1 | package commands
2 |
3 | import (
4 | "fmt"
5 | "io"
6 | "net"
7 | "os"
8 | "os/exec"
9 | "path"
10 | "strings"
11 |
12 | "github.com/moul/advanced-ssh-config/vendor/github.com/Sirupsen/logrus"
13 | "github.com/moul/advanced-ssh-config/vendor/github.com/codegangsta/cli"
14 | shlex "github.com/moul/advanced-ssh-config/vendor/github.com/flynn/go-shlex"
15 |
16 | "github.com/moul/advanced-ssh-config/pkg/config"
17 | )
18 |
19 | func cmdProxy(c *cli.Context) {
20 | if len(c.Args()) < 1 {
21 | logrus.Fatalf("assh: \"proxy\" requires 1 argument. See 'assh proxy --help'.")
22 | }
23 |
24 | conf, err := config.Open()
25 | if err != nil {
26 | logrus.Fatalf("Cannot open configuration file: %v", err)
27 | }
28 |
29 | // FIXME: handle complete host with json
30 |
31 | host, err := computeHost(c.Args()[0], c.Int("port"), conf)
32 | if err != nil {
33 | logrus.Fatalf("Cannot get host '%s': %v", c.Args()[0], err)
34 | }
35 |
36 | err = proxy(host, conf)
37 | if err != nil {
38 | logrus.Fatalf("Proxy error: %v", err)
39 | }
40 | }
41 |
42 | func computeHost(dest string, portOverride int, conf *config.Config) (*config.Host, error) {
43 | host := conf.GetHostSafe(dest)
44 |
45 | if portOverride > 0 {
46 | host.Port = uint(portOverride)
47 | }
48 |
49 | return host, nil
50 | }
51 |
52 | func prepareHostControlPath(host, gateway *config.Host) error {
53 | controlPathDir := path.Dir(os.ExpandEnv(strings.Replace(host.ControlPath, "~", "$HOME", -1)))
54 | gatewayControlPath := path.Join(controlPathDir, gateway.Name)
55 | return os.MkdirAll(gatewayControlPath, 0700)
56 | }
57 |
58 | func proxy(host *config.Host, conf *config.Config) error {
59 | if len(host.Gateways) > 0 {
60 | logrus.Debugf("Trying gateways: %s", host.Gateways)
61 | for _, gateway := range host.Gateways {
62 | if gateway == "direct" {
63 | err := proxyDirect(host)
64 | if err != nil {
65 | logrus.Errorf("Failed to use 'direct' connection")
66 | }
67 | } else {
68 | gatewayHost := conf.GetGatewaySafe(gateway)
69 |
70 | err := prepareHostControlPath(host, gatewayHost)
71 | if err != nil {
72 | return err
73 | }
74 |
75 | if host.ProxyCommand == "" {
76 | host.ProxyCommand = "nc %h %p"
77 | }
78 | command := "ssh %name -- " + commandApplyHost(host.ProxyCommand, host)
79 |
80 | logrus.Debugf("Using gateway '%s': %s", gateway, command)
81 | err = proxyCommand(gatewayHost, command)
82 | if err == nil {
83 | return nil
84 | }
85 | logrus.Errorf("Cannot use gateway '%s': %v", gateway, err)
86 | }
87 | }
88 | return fmt.Errorf("No such available gateway")
89 | }
90 |
91 | logrus.Debugf("Connecting without gateway")
92 | return proxyDirect(host)
93 | }
94 |
95 | func commandApplyHost(command string, host *config.Host) string {
96 | command = strings.Replace(command, "%name", host.Name, -1)
97 | command = strings.Replace(command, "%h", host.Host, -1)
98 | command = strings.Replace(command, "%p", fmt.Sprintf("%d", host.Port), -1)
99 | return command
100 | }
101 |
102 | func proxyDirect(host *config.Host) error {
103 | if host.ProxyCommand != "" {
104 | return proxyCommand(host, host.ProxyCommand)
105 | }
106 | return proxyGo(host)
107 | }
108 |
109 | func proxyCommand(host *config.Host, command string) error {
110 | command = commandApplyHost(command, host)
111 | args, err := shlex.Split(command)
112 | logrus.Debugf("ProxyCommand: %s", command)
113 | if err != nil {
114 | return err
115 | }
116 | spawn := exec.Command(args[0], args[1:]...)
117 | spawn.Stdout = os.Stdout
118 | spawn.Stdin = os.Stdin
119 | spawn.Stderr = os.Stderr
120 | return spawn.Run()
121 | }
122 |
123 | func proxyGo(host *config.Host) error {
124 | if host.Host == "" {
125 | host.Host = host.Name
126 | }
127 |
128 | if len(host.ResolveNameservers) > 0 {
129 | logrus.Debugf("Resolving host: '%s' using nameservers %s", host.Host, host.ResolveNameservers)
130 | // FIXME: resolve using custom dns server
131 | results, err := net.LookupAddr(host.Host)
132 | if err != nil {
133 | return err
134 | }
135 | if len(results) > 0 {
136 | host.Host = results[0]
137 | }
138 | logrus.Debugf("Resolved host is: %s", host.Host)
139 | }
140 | if host.ResolveCommand != "" {
141 | command := commandApplyHost(host.ResolveCommand, host)
142 | logrus.Debugf("Resolving host: '%s' using command: '%s'", host.Host, command)
143 |
144 | args, err := shlex.Split(command)
145 | if err != nil {
146 | return err
147 | }
148 |
149 | out, err := exec.Command(args[0], args[1:]...).Output()
150 | if err != nil {
151 | return err
152 | }
153 |
154 | host.Host = strings.TrimSpace(fmt.Sprintf("%s", out))
155 | logrus.Debugf("Resolved host is: %s", host.Host)
156 | }
157 |
158 | logrus.Debugf("Connecting to %s:%d", host.Host, host.Port)
159 | conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", host.Host, host.Port))
160 | if err != nil {
161 | return err
162 | }
163 | defer conn.Close()
164 |
165 | logrus.Debugf("Connected to %s:%d", host.Host, host.Port)
166 |
167 | // Create Stdio pipes
168 | c1 := readAndWrite(conn, os.Stdout)
169 | c2 := readAndWrite(os.Stdin, conn)
170 |
171 | select {
172 | case err = <-c1:
173 | case err = <-c2:
174 | }
175 | if err != nil {
176 | return err
177 | }
178 |
179 | return nil
180 | }
181 |
182 | func readAndWrite(r io.Reader, w io.Writer) <-chan error {
183 | // Fixme: add an error channel
184 | buf := make([]byte, 1024)
185 | c := make(chan error)
186 |
187 | go func() {
188 | for {
189 | // Read
190 | n, err := r.Read(buf)
191 | if err != nil {
192 | if err != io.EOF {
193 | c <- err
194 | }
195 | break
196 | }
197 |
198 | // Write
199 | _, err = w.Write(buf[0:n])
200 | if err != nil {
201 | c <- err
202 | }
203 | }
204 | c <- nil
205 | }()
206 | return c
207 | }
208 |
--------------------------------------------------------------------------------
/vendor/gopkg.in/yaml.v2/resolve.go:
--------------------------------------------------------------------------------
1 | package yaml
2 |
3 | import (
4 | "encoding/base64"
5 | "math"
6 | "strconv"
7 | "strings"
8 | "unicode/utf8"
9 | )
10 |
11 | type resolveMapItem struct {
12 | value interface{}
13 | tag string
14 | }
15 |
16 | var resolveTable = make([]byte, 256)
17 | var resolveMap = make(map[string]resolveMapItem)
18 |
19 | func init() {
20 | t := resolveTable
21 | t[int('+')] = 'S' // Sign
22 | t[int('-')] = 'S'
23 | for _, c := range "0123456789" {
24 | t[int(c)] = 'D' // Digit
25 | }
26 | for _, c := range "yYnNtTfFoO~" {
27 | t[int(c)] = 'M' // In map
28 | }
29 | t[int('.')] = '.' // Float (potentially in map)
30 |
31 | var resolveMapList = []struct {
32 | v interface{}
33 | tag string
34 | l []string
35 | }{
36 | {true, yaml_BOOL_TAG, []string{"y", "Y", "yes", "Yes", "YES"}},
37 | {true, yaml_BOOL_TAG, []string{"true", "True", "TRUE"}},
38 | {true, yaml_BOOL_TAG, []string{"on", "On", "ON"}},
39 | {false, yaml_BOOL_TAG, []string{"n", "N", "no", "No", "NO"}},
40 | {false, yaml_BOOL_TAG, []string{"false", "False", "FALSE"}},
41 | {false, yaml_BOOL_TAG, []string{"off", "Off", "OFF"}},
42 | {nil, yaml_NULL_TAG, []string{"", "~", "null", "Null", "NULL"}},
43 | {math.NaN(), yaml_FLOAT_TAG, []string{".nan", ".NaN", ".NAN"}},
44 | {math.Inf(+1), yaml_FLOAT_TAG, []string{".inf", ".Inf", ".INF"}},
45 | {math.Inf(+1), yaml_FLOAT_TAG, []string{"+.inf", "+.Inf", "+.INF"}},
46 | {math.Inf(-1), yaml_FLOAT_TAG, []string{"-.inf", "-.Inf", "-.INF"}},
47 | {"<<", yaml_MERGE_TAG, []string{"<<"}},
48 | }
49 |
50 | m := resolveMap
51 | for _, item := range resolveMapList {
52 | for _, s := range item.l {
53 | m[s] = resolveMapItem{item.v, item.tag}
54 | }
55 | }
56 | }
57 |
58 | const longTagPrefix = "tag:yaml.org,2002:"
59 |
60 | func shortTag(tag string) string {
61 | // TODO This can easily be made faster and produce less garbage.
62 | if strings.HasPrefix(tag, longTagPrefix) {
63 | return "!!" + tag[len(longTagPrefix):]
64 | }
65 | return tag
66 | }
67 |
68 | func longTag(tag string) string {
69 | if strings.HasPrefix(tag, "!!") {
70 | return longTagPrefix + tag[2:]
71 | }
72 | return tag
73 | }
74 |
75 | func resolvableTag(tag string) bool {
76 | switch tag {
77 | case "", yaml_STR_TAG, yaml_BOOL_TAG, yaml_INT_TAG, yaml_FLOAT_TAG, yaml_NULL_TAG:
78 | return true
79 | }
80 | return false
81 | }
82 |
83 | func resolve(tag string, in string) (rtag string, out interface{}) {
84 | if !resolvableTag(tag) {
85 | return tag, in
86 | }
87 |
88 | defer func() {
89 | switch tag {
90 | case "", rtag, yaml_STR_TAG, yaml_BINARY_TAG:
91 | return
92 | }
93 | failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag))
94 | }()
95 |
96 | // Any data is accepted as a !!str or !!binary.
97 | // Otherwise, the prefix is enough of a hint about what it might be.
98 | hint := byte('N')
99 | if in != "" {
100 | hint = resolveTable[in[0]]
101 | }
102 | if hint != 0 && tag != yaml_STR_TAG && tag != yaml_BINARY_TAG {
103 | // Handle things we can lookup in a map.
104 | if item, ok := resolveMap[in]; ok {
105 | return item.tag, item.value
106 | }
107 |
108 | // Base 60 floats are a bad idea, were dropped in YAML 1.2, and
109 | // are purposefully unsupported here. They're still quoted on
110 | // the way out for compatibility with other parser, though.
111 |
112 | switch hint {
113 | case 'M':
114 | // We've already checked the map above.
115 |
116 | case '.':
117 | // Not in the map, so maybe a normal float.
118 | floatv, err := strconv.ParseFloat(in, 64)
119 | if err == nil {
120 | return yaml_FLOAT_TAG, floatv
121 | }
122 |
123 | case 'D', 'S':
124 | // Int, float, or timestamp.
125 | plain := strings.Replace(in, "_", "", -1)
126 | intv, err := strconv.ParseInt(plain, 0, 64)
127 | if err == nil {
128 | if intv == int64(int(intv)) {
129 | return yaml_INT_TAG, int(intv)
130 | } else {
131 | return yaml_INT_TAG, intv
132 | }
133 | }
134 | uintv, err := strconv.ParseUint(plain, 0, 64)
135 | if err == nil {
136 | return yaml_INT_TAG, uintv
137 | }
138 | floatv, err := strconv.ParseFloat(plain, 64)
139 | if err == nil {
140 | return yaml_FLOAT_TAG, floatv
141 | }
142 | if strings.HasPrefix(plain, "0b") {
143 | intv, err := strconv.ParseInt(plain[2:], 2, 64)
144 | if err == nil {
145 | if intv == int64(int(intv)) {
146 | return yaml_INT_TAG, int(intv)
147 | } else {
148 | return yaml_INT_TAG, intv
149 | }
150 | }
151 | uintv, err := strconv.ParseUint(plain[2:], 2, 64)
152 | if err == nil {
153 | return yaml_INT_TAG, uintv
154 | }
155 | } else if strings.HasPrefix(plain, "-0b") {
156 | intv, err := strconv.ParseInt(plain[3:], 2, 64)
157 | if err == nil {
158 | if intv == int64(int(intv)) {
159 | return yaml_INT_TAG, -int(intv)
160 | } else {
161 | return yaml_INT_TAG, -intv
162 | }
163 | }
164 | }
165 | // XXX Handle timestamps here.
166 |
167 | default:
168 | panic("resolveTable item not yet handled: " + string(rune(hint)) + " (with " + in + ")")
169 | }
170 | }
171 | if tag == yaml_BINARY_TAG {
172 | return yaml_BINARY_TAG, in
173 | }
174 | if utf8.ValidString(in) {
175 | return yaml_STR_TAG, in
176 | }
177 | return yaml_BINARY_TAG, encodeBase64(in)
178 | }
179 |
180 | // encodeBase64 encodes s as base64 that is broken up into multiple lines
181 | // as appropriate for the resulting length.
182 | func encodeBase64(s string) string {
183 | const lineLen = 70
184 | encLen := base64.StdEncoding.EncodedLen(len(s))
185 | lines := encLen/lineLen + 1
186 | buf := make([]byte, encLen*2+lines)
187 | in := buf[0:encLen]
188 | out := buf[encLen:]
189 | base64.StdEncoding.Encode(in, []byte(s))
190 | k := 0
191 | for i := 0; i < len(in); i += lineLen {
192 | j := i + lineLen
193 | if j > len(in) {
194 | j = len(in)
195 | }
196 | k += copy(out[k:], in[i:j])
197 | if lines > 1 {
198 | out[k] = '\n'
199 | k++
200 | }
201 | }
202 | return string(out[:k])
203 | }
204 |
--------------------------------------------------------------------------------
/vendor/github.com/Sirupsen/logrus/logger.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | import (
4 | "io"
5 | "os"
6 | "sync"
7 | )
8 |
9 | type Logger struct {
10 | // The logs are `io.Copy`'d to this in a mutex. It's common to set this to a
11 | // file, or leave it default which is `os.Stdout`. You can also set this to
12 | // something more adventorous, such as logging to Kafka.
13 | Out io.Writer
14 | // Hooks for the logger instance. These allow firing events based on logging
15 | // levels and log entries. For example, to send errors to an error tracking
16 | // service, log to StatsD or dump the core on fatal errors.
17 | Hooks LevelHooks
18 | // All log entries pass through the formatter before logged to Out. The
19 | // included formatters are `TextFormatter` and `JSONFormatter` for which
20 | // TextFormatter is the default. In development (when a TTY is attached) it
21 | // logs with colors, but to a file it wouldn't. You can easily implement your
22 | // own that implements the `Formatter` interface, see the `README` or included
23 | // formatters for examples.
24 | Formatter Formatter
25 | // The logging level the logger should log at. This is typically (and defaults
26 | // to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be
27 | // logged. `logrus.Debug` is useful in
28 | Level Level
29 | // Used to sync writing to the log.
30 | mu sync.Mutex
31 | }
32 |
33 | // Creates a new logger. Configuration should be set by changing `Formatter`,
34 | // `Out` and `Hooks` directly on the default logger instance. You can also just
35 | // instantiate your own:
36 | //
37 | // var log = &Logger{
38 | // Out: os.Stderr,
39 | // Formatter: new(JSONFormatter),
40 | // Hooks: make(LevelHooks),
41 | // Level: logrus.DebugLevel,
42 | // }
43 | //
44 | // It's recommended to make this a global instance called `log`.
45 | func New() *Logger {
46 | return &Logger{
47 | Out: os.Stderr,
48 | Formatter: new(TextFormatter),
49 | Hooks: make(LevelHooks),
50 | Level: InfoLevel,
51 | }
52 | }
53 |
54 | // Adds a field to the log entry, note that you it doesn't log until you call
55 | // Debug, Print, Info, Warn, Fatal or Panic. It only creates a log entry.
56 | // Ff you want multiple fields, use `WithFields`.
57 | func (logger *Logger) WithField(key string, value interface{}) *Entry {
58 | return NewEntry(logger).WithField(key, value)
59 | }
60 |
61 | // Adds a struct of fields to the log entry. All it does is call `WithField` for
62 | // each `Field`.
63 | func (logger *Logger) WithFields(fields Fields) *Entry {
64 | return NewEntry(logger).WithFields(fields)
65 | }
66 |
67 | func (logger *Logger) Debugf(format string, args ...interface{}) {
68 | if logger.Level >= DebugLevel {
69 | NewEntry(logger).Debugf(format, args...)
70 | }
71 | }
72 |
73 | func (logger *Logger) Infof(format string, args ...interface{}) {
74 | if logger.Level >= InfoLevel {
75 | NewEntry(logger).Infof(format, args...)
76 | }
77 | }
78 |
79 | func (logger *Logger) Printf(format string, args ...interface{}) {
80 | NewEntry(logger).Printf(format, args...)
81 | }
82 |
83 | func (logger *Logger) Warnf(format string, args ...interface{}) {
84 | if logger.Level >= WarnLevel {
85 | NewEntry(logger).Warnf(format, args...)
86 | }
87 | }
88 |
89 | func (logger *Logger) Warningf(format string, args ...interface{}) {
90 | if logger.Level >= WarnLevel {
91 | NewEntry(logger).Warnf(format, args...)
92 | }
93 | }
94 |
95 | func (logger *Logger) Errorf(format string, args ...interface{}) {
96 | if logger.Level >= ErrorLevel {
97 | NewEntry(logger).Errorf(format, args...)
98 | }
99 | }
100 |
101 | func (logger *Logger) Fatalf(format string, args ...interface{}) {
102 | if logger.Level >= FatalLevel {
103 | NewEntry(logger).Fatalf(format, args...)
104 | }
105 | os.Exit(1)
106 | }
107 |
108 | func (logger *Logger) Panicf(format string, args ...interface{}) {
109 | if logger.Level >= PanicLevel {
110 | NewEntry(logger).Panicf(format, args...)
111 | }
112 | }
113 |
114 | func (logger *Logger) Debug(args ...interface{}) {
115 | if logger.Level >= DebugLevel {
116 | NewEntry(logger).Debug(args...)
117 | }
118 | }
119 |
120 | func (logger *Logger) Info(args ...interface{}) {
121 | if logger.Level >= InfoLevel {
122 | NewEntry(logger).Info(args...)
123 | }
124 | }
125 |
126 | func (logger *Logger) Print(args ...interface{}) {
127 | NewEntry(logger).Info(args...)
128 | }
129 |
130 | func (logger *Logger) Warn(args ...interface{}) {
131 | if logger.Level >= WarnLevel {
132 | NewEntry(logger).Warn(args...)
133 | }
134 | }
135 |
136 | func (logger *Logger) Warning(args ...interface{}) {
137 | if logger.Level >= WarnLevel {
138 | NewEntry(logger).Warn(args...)
139 | }
140 | }
141 |
142 | func (logger *Logger) Error(args ...interface{}) {
143 | if logger.Level >= ErrorLevel {
144 | NewEntry(logger).Error(args...)
145 | }
146 | }
147 |
148 | func (logger *Logger) Fatal(args ...interface{}) {
149 | if logger.Level >= FatalLevel {
150 | NewEntry(logger).Fatal(args...)
151 | }
152 | os.Exit(1)
153 | }
154 |
155 | func (logger *Logger) Panic(args ...interface{}) {
156 | if logger.Level >= PanicLevel {
157 | NewEntry(logger).Panic(args...)
158 | }
159 | }
160 |
161 | func (logger *Logger) Debugln(args ...interface{}) {
162 | if logger.Level >= DebugLevel {
163 | NewEntry(logger).Debugln(args...)
164 | }
165 | }
166 |
167 | func (logger *Logger) Infoln(args ...interface{}) {
168 | if logger.Level >= InfoLevel {
169 | NewEntry(logger).Infoln(args...)
170 | }
171 | }
172 |
173 | func (logger *Logger) Println(args ...interface{}) {
174 | NewEntry(logger).Println(args...)
175 | }
176 |
177 | func (logger *Logger) Warnln(args ...interface{}) {
178 | if logger.Level >= WarnLevel {
179 | NewEntry(logger).Warnln(args...)
180 | }
181 | }
182 |
183 | func (logger *Logger) Warningln(args ...interface{}) {
184 | if logger.Level >= WarnLevel {
185 | NewEntry(logger).Warnln(args...)
186 | }
187 | }
188 |
189 | func (logger *Logger) Errorln(args ...interface{}) {
190 | if logger.Level >= ErrorLevel {
191 | NewEntry(logger).Errorln(args...)
192 | }
193 | }
194 |
195 | func (logger *Logger) Fatalln(args ...interface{}) {
196 | if logger.Level >= FatalLevel {
197 | NewEntry(logger).Fatalln(args...)
198 | }
199 | os.Exit(1)
200 | }
201 |
202 | func (logger *Logger) Panicln(args ...interface{}) {
203 | if logger.Level >= PanicLevel {
204 | NewEntry(logger).Panicln(args...)
205 | }
206 | }
207 |
--------------------------------------------------------------------------------
/vendor/github.com/stretchr/testify/assert/http_assertions.go:
--------------------------------------------------------------------------------
1 | package assert
2 |
3 | import (
4 | "fmt"
5 | "net/http"
6 | "net/http/httptest"
7 | "net/url"
8 | "strings"
9 | )
10 |
11 | // httpCode is a helper that returns HTTP code of the response. It returns -1
12 | // if building a new request fails.
13 | func httpCode(handler http.HandlerFunc, mode, url string, values url.Values) int {
14 | w := httptest.NewRecorder()
15 | req, err := http.NewRequest(mode, url+"?"+values.Encode(), nil)
16 | if err != nil {
17 | return -1
18 | }
19 | handler(w, req)
20 | return w.Code
21 | }
22 |
23 | // HTTPSuccess asserts that a specified handler returns a success status code.
24 | //
25 | // assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil)
26 | //
27 | // Returns whether the assertion was successful (true) or not (false).
28 | func HTTPSuccess(t TestingT, handler http.HandlerFunc, mode, url string, values url.Values) bool {
29 | code := httpCode(handler, mode, url, values)
30 | if code == -1 {
31 | return false
32 | }
33 | return code >= http.StatusOK && code <= http.StatusPartialContent
34 | }
35 |
36 | // HTTPRedirect asserts that a specified handler returns a redirect status code.
37 | //
38 | // assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
39 | //
40 | // Returns whether the assertion was successful (true) or not (false).
41 | func HTTPRedirect(t TestingT, handler http.HandlerFunc, mode, url string, values url.Values) bool {
42 | code := httpCode(handler, mode, url, values)
43 | if code == -1 {
44 | return false
45 | }
46 | return code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect
47 | }
48 |
49 | // HTTPError asserts that a specified handler returns an error status code.
50 | //
51 | // assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
52 | //
53 | // Returns whether the assertion was successful (true) or not (false).
54 | func HTTPError(t TestingT, handler http.HandlerFunc, mode, url string, values url.Values) bool {
55 | code := httpCode(handler, mode, url, values)
56 | if code == -1 {
57 | return false
58 | }
59 | return code >= http.StatusBadRequest
60 | }
61 |
62 | // HTTPBody is a helper that returns HTTP body of the response. It returns
63 | // empty string if building a new request fails.
64 | func HTTPBody(handler http.HandlerFunc, mode, url string, values url.Values) string {
65 | w := httptest.NewRecorder()
66 | req, err := http.NewRequest(mode, url+"?"+values.Encode(), nil)
67 | if err != nil {
68 | return ""
69 | }
70 | handler(w, req)
71 | return w.Body.String()
72 | }
73 |
74 | // HTTPBodyContains asserts that a specified handler returns a
75 | // body that contains a string.
76 | //
77 | // assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
78 | //
79 | // Returns whether the assertion was successful (true) or not (false).
80 | func HTTPBodyContains(t TestingT, handler http.HandlerFunc, mode, url string, values url.Values, str interface{}) bool {
81 | body := HTTPBody(handler, mode, url, values)
82 |
83 | contains := strings.Contains(body, fmt.Sprint(str))
84 | if !contains {
85 | Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body))
86 | }
87 |
88 | return contains
89 | }
90 |
91 | // HTTPBodyNotContains asserts that a specified handler returns a
92 | // body that does not contain a string.
93 | //
94 | // assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
95 | //
96 | // Returns whether the assertion was successful (true) or not (false).
97 | func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, mode, url string, values url.Values, str interface{}) bool {
98 | body := HTTPBody(handler, mode, url, values)
99 |
100 | contains := strings.Contains(body, fmt.Sprint(str))
101 | if contains {
102 | Fail(t, "Expected response body for %s to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)
103 | }
104 |
105 | return !contains
106 | }
107 |
108 | //
109 | // Assertions Wrappers
110 | //
111 |
112 | // HTTPSuccess asserts that a specified handler returns a success status code.
113 | //
114 | // assert.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil)
115 | //
116 | // Returns whether the assertion was successful (true) or not (false).
117 | func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, mode, url string, values url.Values) bool {
118 | return HTTPSuccess(a.t, handler, mode, url, values)
119 | }
120 |
121 | // HTTPRedirect asserts that a specified handler returns a redirect status code.
122 | //
123 | // assert.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
124 | //
125 | // Returns whether the assertion was successful (true) or not (false).
126 | func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, mode, url string, values url.Values) bool {
127 | return HTTPRedirect(a.t, handler, mode, url, values)
128 | }
129 |
130 | // HTTPError asserts that a specified handler returns an error status code.
131 | //
132 | // assert.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
133 | //
134 | // Returns whether the assertion was successful (true) or not (false).
135 | func (a *Assertions) HTTPError(handler http.HandlerFunc, mode, url string, values url.Values) bool {
136 | return HTTPError(a.t, handler, mode, url, values)
137 | }
138 |
139 | // HTTPBodyContains asserts that a specified handler returns a
140 | // body that contains a string.
141 | //
142 | // assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
143 | //
144 | // Returns whether the assertion was successful (true) or not (false).
145 | func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, mode, url string, values url.Values, str interface{}) bool {
146 | return HTTPBodyContains(a.t, handler, mode, url, values, str)
147 | }
148 |
149 | // HTTPBodyNotContains asserts that a specified handler returns a
150 | // body that does not contain a string.
151 | //
152 | // assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
153 | //
154 | // Returns whether the assertion was successful (true) or not (false).
155 | func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, mode, url string, values url.Values, str interface{}) bool {
156 | return HTTPBodyNotContains(a.t, handler, mode, url, values, str)
157 | }
158 |
--------------------------------------------------------------------------------
/vendor/github.com/codegangsta/cli/help.go:
--------------------------------------------------------------------------------
1 | package cli
2 |
3 | import (
4 | "fmt"
5 | "io"
6 | "strings"
7 | "text/tabwriter"
8 | "text/template"
9 | )
10 |
11 | // The text template for the Default help topic.
12 | // cli.go uses text/template to render templates. You can
13 | // render custom help text by setting this variable.
14 | var AppHelpTemplate = `NAME:
15 | {{.Name}} - {{.Usage}}
16 |
17 | USAGE:
18 | {{.Name}} {{if .Flags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} [arguments...]
19 | {{if .Version}}
20 | VERSION:
21 | {{.Version}}
22 | {{end}}{{if len .Authors}}
23 | AUTHOR(S):
24 | {{range .Authors}}{{ . }}{{end}}
25 | {{end}}{{if .Commands}}
26 | COMMANDS:
27 | {{range .Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}}
28 | {{end}}{{end}}{{if .Flags}}
29 | GLOBAL OPTIONS:
30 | {{range .Flags}}{{.}}
31 | {{end}}{{end}}{{if .Copyright }}
32 | COPYRIGHT:
33 | {{.Copyright}}
34 | {{end}}
35 | `
36 |
37 | // The text template for the command help topic.
38 | // cli.go uses text/template to render templates. You can
39 | // render custom help text by setting this variable.
40 | var CommandHelpTemplate = `NAME:
41 | {{.FullName}} - {{.Usage}}
42 |
43 | USAGE:
44 | command {{.FullName}}{{if .Flags}} [command options]{{end}} [arguments...]{{if .Description}}
45 |
46 | DESCRIPTION:
47 | {{.Description}}{{end}}{{if .Flags}}
48 |
49 | OPTIONS:
50 | {{range .Flags}}{{.}}
51 | {{end}}{{ end }}
52 | `
53 |
54 | // The text template for the subcommand help topic.
55 | // cli.go uses text/template to render templates. You can
56 | // render custom help text by setting this variable.
57 | var SubcommandHelpTemplate = `NAME:
58 | {{.Name}} - {{.Usage}}
59 |
60 | USAGE:
61 | {{.Name}} command{{if .Flags}} [command options]{{end}} [arguments...]
62 |
63 | COMMANDS:
64 | {{range .Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}}
65 | {{end}}{{if .Flags}}
66 | OPTIONS:
67 | {{range .Flags}}{{.}}
68 | {{end}}{{end}}
69 | `
70 |
71 | var helpCommand = Command{
72 | Name: "help",
73 | Aliases: []string{"h"},
74 | Usage: "Shows a list of commands or help for one command",
75 | Action: func(c *Context) {
76 | args := c.Args()
77 | if args.Present() {
78 | ShowCommandHelp(c, args.First())
79 | } else {
80 | ShowAppHelp(c)
81 | }
82 | },
83 | }
84 |
85 | var helpSubcommand = Command{
86 | Name: "help",
87 | Aliases: []string{"h"},
88 | Usage: "Shows a list of commands or help for one command",
89 | Action: func(c *Context) {
90 | args := c.Args()
91 | if args.Present() {
92 | ShowCommandHelp(c, args.First())
93 | } else {
94 | ShowSubcommandHelp(c)
95 | }
96 | },
97 | }
98 |
99 | // Prints help for the App or Command
100 | type helpPrinter func(w io.Writer, templ string, data interface{})
101 |
102 | var HelpPrinter helpPrinter = printHelp
103 |
104 | // Prints version for the App
105 | var VersionPrinter = printVersion
106 |
107 | func ShowAppHelp(c *Context) {
108 | HelpPrinter(c.App.Writer, AppHelpTemplate, c.App)
109 | }
110 |
111 | // Prints the list of subcommands as the default app completion method
112 | func DefaultAppComplete(c *Context) {
113 | for _, command := range c.App.Commands {
114 | for _, name := range command.Names() {
115 | fmt.Fprintln(c.App.Writer, name)
116 | }
117 | }
118 | }
119 |
120 | // Prints help for the given command
121 | func ShowCommandHelp(ctx *Context, command string) {
122 | // show the subcommand help for a command with subcommands
123 | if command == "" {
124 | HelpPrinter(ctx.App.Writer, SubcommandHelpTemplate, ctx.App)
125 | return
126 | }
127 |
128 | for _, c := range ctx.App.Commands {
129 | if c.HasName(command) {
130 | HelpPrinter(ctx.App.Writer, CommandHelpTemplate, c)
131 | return
132 | }
133 | }
134 |
135 | if ctx.App.CommandNotFound != nil {
136 | ctx.App.CommandNotFound(ctx, command)
137 | } else {
138 | fmt.Fprintf(ctx.App.Writer, "No help topic for '%v'\n", command)
139 | }
140 | }
141 |
142 | // Prints help for the given subcommand
143 | func ShowSubcommandHelp(c *Context) {
144 | ShowCommandHelp(c, c.Command.Name)
145 | }
146 |
147 | // Prints the version number of the App
148 | func ShowVersion(c *Context) {
149 | VersionPrinter(c)
150 | }
151 |
152 | func printVersion(c *Context) {
153 | fmt.Fprintf(c.App.Writer, "%v version %v\n", c.App.Name, c.App.Version)
154 | }
155 |
156 | // Prints the lists of commands within a given context
157 | func ShowCompletions(c *Context) {
158 | a := c.App
159 | if a != nil && a.BashComplete != nil {
160 | a.BashComplete(c)
161 | }
162 | }
163 |
164 | // Prints the custom completions for a given command
165 | func ShowCommandCompletions(ctx *Context, command string) {
166 | c := ctx.App.Command(command)
167 | if c != nil && c.BashComplete != nil {
168 | c.BashComplete(ctx)
169 | }
170 | }
171 |
172 | func printHelp(out io.Writer, templ string, data interface{}) {
173 | funcMap := template.FuncMap{
174 | "join": strings.Join,
175 | }
176 |
177 | w := tabwriter.NewWriter(out, 0, 8, 1, '\t', 0)
178 | t := template.Must(template.New("help").Funcs(funcMap).Parse(templ))
179 | err := t.Execute(w, data)
180 | if err != nil {
181 | panic(err)
182 | }
183 | w.Flush()
184 | }
185 |
186 | func checkVersion(c *Context) bool {
187 | if c.GlobalBool("version") || c.GlobalBool("v") || c.Bool("version") || c.Bool("v") {
188 | ShowVersion(c)
189 | return true
190 | }
191 |
192 | return false
193 | }
194 |
195 | func checkHelp(c *Context) bool {
196 | if c.GlobalBool("h") || c.GlobalBool("help") || c.Bool("h") || c.Bool("help") {
197 | ShowAppHelp(c)
198 | return true
199 | }
200 |
201 | return false
202 | }
203 |
204 | func checkCommandHelp(c *Context, name string) bool {
205 | if c.Bool("h") || c.Bool("help") {
206 | ShowCommandHelp(c, name)
207 | return true
208 | }
209 |
210 | return false
211 | }
212 |
213 | func checkSubcommandHelp(c *Context) bool {
214 | if c.GlobalBool("h") || c.GlobalBool("help") {
215 | ShowSubcommandHelp(c)
216 | return true
217 | }
218 |
219 | return false
220 | }
221 |
222 | func checkCompletions(c *Context) bool {
223 | if (c.GlobalBool(BashCompletionFlag.Name) || c.Bool(BashCompletionFlag.Name)) && c.App.EnableBashCompletion {
224 | ShowCompletions(c)
225 | return true
226 | }
227 |
228 | return false
229 | }
230 |
231 | func checkCommandCompletions(c *Context, name string) bool {
232 | if c.Bool(BashCompletionFlag.Name) && c.App.EnableBashCompletion {
233 | ShowCommandCompletions(c, name)
234 | return true
235 | }
236 |
237 | return false
238 | }
239 |
--------------------------------------------------------------------------------
/vendor/github.com/Sirupsen/logrus/entry.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | import (
4 | "bytes"
5 | "fmt"
6 | "io"
7 | "os"
8 | "time"
9 | )
10 |
11 | // An entry is the final or intermediate Logrus logging entry. It contains all
12 | // the fields passed with WithField{,s}. It's finally logged when Debug, Info,
13 | // Warn, Error, Fatal or Panic is called on it. These objects can be reused and
14 | // passed around as much as you wish to avoid field duplication.
15 | type Entry struct {
16 | Logger *Logger
17 |
18 | // Contains all the fields set by the user.
19 | Data Fields
20 |
21 | // Time at which the log entry was created
22 | Time time.Time
23 |
24 | // Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic
25 | Level Level
26 |
27 | // Message passed to Debug, Info, Warn, Error, Fatal or Panic
28 | Message string
29 | }
30 |
31 | func NewEntry(logger *Logger) *Entry {
32 | return &Entry{
33 | Logger: logger,
34 | // Default is three fields, give a little extra room
35 | Data: make(Fields, 5),
36 | }
37 | }
38 |
39 | // Returns a reader for the entry, which is a proxy to the formatter.
40 | func (entry *Entry) Reader() (*bytes.Buffer, error) {
41 | serialized, err := entry.Logger.Formatter.Format(entry)
42 | return bytes.NewBuffer(serialized), err
43 | }
44 |
45 | // Returns the string representation from the reader and ultimately the
46 | // formatter.
47 | func (entry *Entry) String() (string, error) {
48 | reader, err := entry.Reader()
49 | if err != nil {
50 | return "", err
51 | }
52 |
53 | return reader.String(), err
54 | }
55 |
56 | // Add a single field to the Entry.
57 | func (entry *Entry) WithField(key string, value interface{}) *Entry {
58 | return entry.WithFields(Fields{key: value})
59 | }
60 |
61 | // Add a map of fields to the Entry.
62 | func (entry *Entry) WithFields(fields Fields) *Entry {
63 | data := Fields{}
64 | for k, v := range entry.Data {
65 | data[k] = v
66 | }
67 | for k, v := range fields {
68 | data[k] = v
69 | }
70 | return &Entry{Logger: entry.Logger, Data: data}
71 | }
72 |
73 | func (entry *Entry) log(level Level, msg string) {
74 | entry.Time = time.Now()
75 | entry.Level = level
76 | entry.Message = msg
77 |
78 | if err := entry.Logger.Hooks.Fire(level, entry); err != nil {
79 | entry.Logger.mu.Lock()
80 | fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
81 | entry.Logger.mu.Unlock()
82 | }
83 |
84 | reader, err := entry.Reader()
85 | if err != nil {
86 | entry.Logger.mu.Lock()
87 | fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
88 | entry.Logger.mu.Unlock()
89 | }
90 |
91 | entry.Logger.mu.Lock()
92 | defer entry.Logger.mu.Unlock()
93 |
94 | _, err = io.Copy(entry.Logger.Out, reader)
95 | if err != nil {
96 | fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
97 | }
98 |
99 | // To avoid Entry#log() returning a value that only would make sense for
100 | // panic() to use in Entry#Panic(), we avoid the allocation by checking
101 | // directly here.
102 | if level <= PanicLevel {
103 | panic(entry)
104 | }
105 | }
106 |
107 | func (entry *Entry) Debug(args ...interface{}) {
108 | if entry.Logger.Level >= DebugLevel {
109 | entry.log(DebugLevel, fmt.Sprint(args...))
110 | }
111 | }
112 |
113 | func (entry *Entry) Print(args ...interface{}) {
114 | entry.Info(args...)
115 | }
116 |
117 | func (entry *Entry) Info(args ...interface{}) {
118 | if entry.Logger.Level >= InfoLevel {
119 | entry.log(InfoLevel, fmt.Sprint(args...))
120 | }
121 | }
122 |
123 | func (entry *Entry) Warn(args ...interface{}) {
124 | if entry.Logger.Level >= WarnLevel {
125 | entry.log(WarnLevel, fmt.Sprint(args...))
126 | }
127 | }
128 |
129 | func (entry *Entry) Warning(args ...interface{}) {
130 | entry.Warn(args...)
131 | }
132 |
133 | func (entry *Entry) Error(args ...interface{}) {
134 | if entry.Logger.Level >= ErrorLevel {
135 | entry.log(ErrorLevel, fmt.Sprint(args...))
136 | }
137 | }
138 |
139 | func (entry *Entry) Fatal(args ...interface{}) {
140 | if entry.Logger.Level >= FatalLevel {
141 | entry.log(FatalLevel, fmt.Sprint(args...))
142 | }
143 | os.Exit(1)
144 | }
145 |
146 | func (entry *Entry) Panic(args ...interface{}) {
147 | if entry.Logger.Level >= PanicLevel {
148 | entry.log(PanicLevel, fmt.Sprint(args...))
149 | }
150 | panic(fmt.Sprint(args...))
151 | }
152 |
153 | // Entry Printf family functions
154 |
155 | func (entry *Entry) Debugf(format string, args ...interface{}) {
156 | if entry.Logger.Level >= DebugLevel {
157 | entry.Debug(fmt.Sprintf(format, args...))
158 | }
159 | }
160 |
161 | func (entry *Entry) Infof(format string, args ...interface{}) {
162 | if entry.Logger.Level >= InfoLevel {
163 | entry.Info(fmt.Sprintf(format, args...))
164 | }
165 | }
166 |
167 | func (entry *Entry) Printf(format string, args ...interface{}) {
168 | entry.Infof(format, args...)
169 | }
170 |
171 | func (entry *Entry) Warnf(format string, args ...interface{}) {
172 | if entry.Logger.Level >= WarnLevel {
173 | entry.Warn(fmt.Sprintf(format, args...))
174 | }
175 | }
176 |
177 | func (entry *Entry) Warningf(format string, args ...interface{}) {
178 | entry.Warnf(format, args...)
179 | }
180 |
181 | func (entry *Entry) Errorf(format string, args ...interface{}) {
182 | if entry.Logger.Level >= ErrorLevel {
183 | entry.Error(fmt.Sprintf(format, args...))
184 | }
185 | }
186 |
187 | func (entry *Entry) Fatalf(format string, args ...interface{}) {
188 | if entry.Logger.Level >= FatalLevel {
189 | entry.Fatal(fmt.Sprintf(format, args...))
190 | }
191 | os.Exit(1)
192 | }
193 |
194 | func (entry *Entry) Panicf(format string, args ...interface{}) {
195 | if entry.Logger.Level >= PanicLevel {
196 | entry.Panic(fmt.Sprintf(format, args...))
197 | }
198 | }
199 |
200 | // Entry Println family functions
201 |
202 | func (entry *Entry) Debugln(args ...interface{}) {
203 | if entry.Logger.Level >= DebugLevel {
204 | entry.Debug(entry.sprintlnn(args...))
205 | }
206 | }
207 |
208 | func (entry *Entry) Infoln(args ...interface{}) {
209 | if entry.Logger.Level >= InfoLevel {
210 | entry.Info(entry.sprintlnn(args...))
211 | }
212 | }
213 |
214 | func (entry *Entry) Println(args ...interface{}) {
215 | entry.Infoln(args...)
216 | }
217 |
218 | func (entry *Entry) Warnln(args ...interface{}) {
219 | if entry.Logger.Level >= WarnLevel {
220 | entry.Warn(entry.sprintlnn(args...))
221 | }
222 | }
223 |
224 | func (entry *Entry) Warningln(args ...interface{}) {
225 | entry.Warnln(args...)
226 | }
227 |
228 | func (entry *Entry) Errorln(args ...interface{}) {
229 | if entry.Logger.Level >= ErrorLevel {
230 | entry.Error(entry.sprintlnn(args...))
231 | }
232 | }
233 |
234 | func (entry *Entry) Fatalln(args ...interface{}) {
235 | if entry.Logger.Level >= FatalLevel {
236 | entry.Fatal(entry.sprintlnn(args...))
237 | }
238 | os.Exit(1)
239 | }
240 |
241 | func (entry *Entry) Panicln(args ...interface{}) {
242 | if entry.Logger.Level >= PanicLevel {
243 | entry.Panic(entry.sprintlnn(args...))
244 | }
245 | }
246 |
247 | // Sprintlnn => Sprint no newline. This is to get the behavior of how
248 | // fmt.Sprintln where spaces are always added between operands, regardless of
249 | // their type. Instead of vendoring the Sprintln implementation to spare a
250 | // string allocation, we do the simplest thing.
251 | func (entry *Entry) sprintlnn(args ...interface{}) string {
252 | msg := fmt.Sprintln(args...)
253 | return msg[:len(msg)-1]
254 | }
255 |
--------------------------------------------------------------------------------
/vendor/github.com/codegangsta/cli/app.go:
--------------------------------------------------------------------------------
1 | package cli
2 |
3 | import (
4 | "fmt"
5 | "io"
6 | "io/ioutil"
7 | "os"
8 | "time"
9 | )
10 |
11 | // App is the main structure of a cli application. It is recomended that
12 | // an app be created with the cli.NewApp() function
13 | type App struct {
14 | // The name of the program. Defaults to os.Args[0]
15 | Name string
16 | // Description of the program.
17 | Usage string
18 | // Version of the program
19 | Version string
20 | // List of commands to execute
21 | Commands []Command
22 | // List of flags to parse
23 | Flags []Flag
24 | // Boolean to enable bash completion commands
25 | EnableBashCompletion bool
26 | // Boolean to hide built-in help command
27 | HideHelp bool
28 | // Boolean to hide built-in version flag
29 | HideVersion bool
30 | // An action to execute when the bash-completion flag is set
31 | BashComplete func(context *Context)
32 | // An action to execute before any subcommands are run, but after the context is ready
33 | // If a non-nil error is returned, no subcommands are run
34 | Before func(context *Context) error
35 | // An action to execute after any subcommands are run, but after the subcommand has finished
36 | // It is run even if Action() panics
37 | After func(context *Context) error
38 | // The action to execute when no subcommands are specified
39 | Action func(context *Context)
40 | // Execute this function if the proper command cannot be found
41 | CommandNotFound func(context *Context, command string)
42 | // Compilation date
43 | Compiled time.Time
44 | // List of all authors who contributed
45 | Authors []Author
46 | // Copyright of the binary if any
47 | Copyright string
48 | // Name of Author (Note: Use App.Authors, this is deprecated)
49 | Author string
50 | // Email of Author (Note: Use App.Authors, this is deprecated)
51 | Email string
52 | // Writer writer to write output to
53 | Writer io.Writer
54 | }
55 |
56 | // Tries to find out when this binary was compiled.
57 | // Returns the current time if it fails to find it.
58 | func compileTime() time.Time {
59 | info, err := os.Stat(os.Args[0])
60 | if err != nil {
61 | return time.Now()
62 | }
63 | return info.ModTime()
64 | }
65 |
66 | // Creates a new cli Application with some reasonable defaults for Name, Usage, Version and Action.
67 | func NewApp() *App {
68 | return &App{
69 | Name: os.Args[0],
70 | Usage: "A new cli application",
71 | Version: "0.0.0",
72 | BashComplete: DefaultAppComplete,
73 | Action: helpCommand.Action,
74 | Compiled: compileTime(),
75 | Writer: os.Stdout,
76 | }
77 | }
78 |
79 | // Entry point to the cli app. Parses the arguments slice and routes to the proper flag/args combination
80 | func (a *App) Run(arguments []string) (err error) {
81 | if a.Author != "" || a.Email != "" {
82 | a.Authors = append(a.Authors, Author{Name: a.Author, Email: a.Email})
83 | }
84 |
85 | // append help to commands
86 | if a.Command(helpCommand.Name) == nil && !a.HideHelp {
87 | a.Commands = append(a.Commands, helpCommand)
88 | if (HelpFlag != BoolFlag{}) {
89 | a.appendFlag(HelpFlag)
90 | }
91 | }
92 |
93 | //append version/help flags
94 | if a.EnableBashCompletion {
95 | a.appendFlag(BashCompletionFlag)
96 | }
97 |
98 | if !a.HideVersion {
99 | a.appendFlag(VersionFlag)
100 | }
101 |
102 | // parse flags
103 | set := flagSet(a.Name, a.Flags)
104 | set.SetOutput(ioutil.Discard)
105 | err = set.Parse(arguments[1:])
106 | nerr := normalizeFlags(a.Flags, set)
107 | if nerr != nil {
108 | fmt.Fprintln(a.Writer, nerr)
109 | context := NewContext(a, set, nil)
110 | ShowAppHelp(context)
111 | return nerr
112 | }
113 | context := NewContext(a, set, nil)
114 |
115 | if err != nil {
116 | fmt.Fprintln(a.Writer, "Incorrect Usage.")
117 | fmt.Fprintln(a.Writer)
118 | ShowAppHelp(context)
119 | return err
120 | }
121 |
122 | if checkCompletions(context) {
123 | return nil
124 | }
125 |
126 | if checkHelp(context) {
127 | return nil
128 | }
129 |
130 | if checkVersion(context) {
131 | return nil
132 | }
133 |
134 | if a.After != nil {
135 | defer func() {
136 | afterErr := a.After(context)
137 | if afterErr != nil {
138 | if err != nil {
139 | err = NewMultiError(err, afterErr)
140 | } else {
141 | err = afterErr
142 | }
143 | }
144 | }()
145 | }
146 |
147 | if a.Before != nil {
148 | err := a.Before(context)
149 | if err != nil {
150 | return err
151 | }
152 | }
153 |
154 | args := context.Args()
155 | if args.Present() {
156 | name := args.First()
157 | c := a.Command(name)
158 | if c != nil {
159 | return c.Run(context)
160 | }
161 | }
162 |
163 | // Run default Action
164 | a.Action(context)
165 | return nil
166 | }
167 |
168 | // Another entry point to the cli app, takes care of passing arguments and error handling
169 | func (a *App) RunAndExitOnError() {
170 | if err := a.Run(os.Args); err != nil {
171 | fmt.Fprintln(os.Stderr, err)
172 | os.Exit(1)
173 | }
174 | }
175 |
176 | // Invokes the subcommand given the context, parses ctx.Args() to generate command-specific flags
177 | func (a *App) RunAsSubcommand(ctx *Context) (err error) {
178 | // append help to commands
179 | if len(a.Commands) > 0 {
180 | if a.Command(helpCommand.Name) == nil && !a.HideHelp {
181 | a.Commands = append(a.Commands, helpCommand)
182 | if (HelpFlag != BoolFlag{}) {
183 | a.appendFlag(HelpFlag)
184 | }
185 | }
186 | }
187 |
188 | // append flags
189 | if a.EnableBashCompletion {
190 | a.appendFlag(BashCompletionFlag)
191 | }
192 |
193 | // parse flags
194 | set := flagSet(a.Name, a.Flags)
195 | set.SetOutput(ioutil.Discard)
196 | err = set.Parse(ctx.Args().Tail())
197 | nerr := normalizeFlags(a.Flags, set)
198 | context := NewContext(a, set, ctx)
199 |
200 | if nerr != nil {
201 | fmt.Fprintln(a.Writer, nerr)
202 | fmt.Fprintln(a.Writer)
203 | if len(a.Commands) > 0 {
204 | ShowSubcommandHelp(context)
205 | } else {
206 | ShowCommandHelp(ctx, context.Args().First())
207 | }
208 | return nerr
209 | }
210 |
211 | if err != nil {
212 | fmt.Fprintln(a.Writer, "Incorrect Usage.")
213 | fmt.Fprintln(a.Writer)
214 | ShowSubcommandHelp(context)
215 | return err
216 | }
217 |
218 | if checkCompletions(context) {
219 | return nil
220 | }
221 |
222 | if len(a.Commands) > 0 {
223 | if checkSubcommandHelp(context) {
224 | return nil
225 | }
226 | } else {
227 | if checkCommandHelp(ctx, context.Args().First()) {
228 | return nil
229 | }
230 | }
231 |
232 | if a.After != nil {
233 | defer func() {
234 | afterErr := a.After(context)
235 | if afterErr != nil {
236 | if err != nil {
237 | err = NewMultiError(err, afterErr)
238 | } else {
239 | err = afterErr
240 | }
241 | }
242 | }()
243 | }
244 |
245 | if a.Before != nil {
246 | err := a.Before(context)
247 | if err != nil {
248 | return err
249 | }
250 | }
251 |
252 | args := context.Args()
253 | if args.Present() {
254 | name := args.First()
255 | c := a.Command(name)
256 | if c != nil {
257 | return c.Run(context)
258 | }
259 | }
260 |
261 | // Run default Action
262 | a.Action(context)
263 |
264 | return nil
265 | }
266 |
267 | // Returns the named command on App. Returns nil if the command does not exist
268 | func (a *App) Command(name string) *Command {
269 | for _, c := range a.Commands {
270 | if c.HasName(name) {
271 | return &c
272 | }
273 | }
274 |
275 | return nil
276 | }
277 |
278 | func (a *App) hasFlag(flag Flag) bool {
279 | for _, f := range a.Flags {
280 | if flag == f {
281 | return true
282 | }
283 | }
284 |
285 | return false
286 | }
287 |
288 | func (a *App) appendFlag(flag Flag) {
289 | if !a.hasFlag(flag) {
290 | a.Flags = append(a.Flags, flag)
291 | }
292 | }
293 |
294 | // Author represents someone who has contributed to a cli project.
295 | type Author struct {
296 | Name string // The Authors name
297 | Email string // The Authors email
298 | }
299 |
300 | // String makes Author comply to the Stringer interface, to allow an easy print in the templating process
301 | func (a Author) String() string {
302 | e := ""
303 | if a.Email != "" {
304 | e = "<" + a.Email + "> "
305 | }
306 |
307 | return fmt.Sprintf("%v %v", a.Name, e)
308 | }
309 |
--------------------------------------------------------------------------------
/vendor/github.com/Sirupsen/logrus/logrus_test.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | import (
4 | "bytes"
5 | "encoding/json"
6 | "strconv"
7 | "strings"
8 | "sync"
9 | "testing"
10 |
11 | "github.com/moul/advanced-ssh-config/vendor/github.com/stretchr/testify/assert"
12 | )
13 |
14 | func LogAndAssertJSON(t *testing.T, log func(*Logger), assertions func(fields Fields)) {
15 | var buffer bytes.Buffer
16 | var fields Fields
17 |
18 | logger := New()
19 | logger.Out = &buffer
20 | logger.Formatter = new(JSONFormatter)
21 |
22 | log(logger)
23 |
24 | err := json.Unmarshal(buffer.Bytes(), &fields)
25 | assert.Nil(t, err)
26 |
27 | assertions(fields)
28 | }
29 |
30 | func LogAndAssertText(t *testing.T, log func(*Logger), assertions func(fields map[string]string)) {
31 | var buffer bytes.Buffer
32 |
33 | logger := New()
34 | logger.Out = &buffer
35 | logger.Formatter = &TextFormatter{
36 | DisableColors: true,
37 | }
38 |
39 | log(logger)
40 |
41 | fields := make(map[string]string)
42 | for _, kv := range strings.Split(buffer.String(), " ") {
43 | if !strings.Contains(kv, "=") {
44 | continue
45 | }
46 | kvArr := strings.Split(kv, "=")
47 | key := strings.TrimSpace(kvArr[0])
48 | val := kvArr[1]
49 | if kvArr[1][0] == '"' {
50 | var err error
51 | val, err = strconv.Unquote(val)
52 | assert.NoError(t, err)
53 | }
54 | fields[key] = val
55 | }
56 | assertions(fields)
57 | }
58 |
59 | func TestPrint(t *testing.T) {
60 | LogAndAssertJSON(t, func(log *Logger) {
61 | log.Print("test")
62 | }, func(fields Fields) {
63 | assert.Equal(t, fields["msg"], "test")
64 | assert.Equal(t, fields["level"], "info")
65 | })
66 | }
67 |
68 | func TestInfo(t *testing.T) {
69 | LogAndAssertJSON(t, func(log *Logger) {
70 | log.Info("test")
71 | }, func(fields Fields) {
72 | assert.Equal(t, fields["msg"], "test")
73 | assert.Equal(t, fields["level"], "info")
74 | })
75 | }
76 |
77 | func TestWarn(t *testing.T) {
78 | LogAndAssertJSON(t, func(log *Logger) {
79 | log.Warn("test")
80 | }, func(fields Fields) {
81 | assert.Equal(t, fields["msg"], "test")
82 | assert.Equal(t, fields["level"], "warning")
83 | })
84 | }
85 |
86 | func TestInfolnShouldAddSpacesBetweenStrings(t *testing.T) {
87 | LogAndAssertJSON(t, func(log *Logger) {
88 | log.Infoln("test", "test")
89 | }, func(fields Fields) {
90 | assert.Equal(t, fields["msg"], "test test")
91 | })
92 | }
93 |
94 | func TestInfolnShouldAddSpacesBetweenStringAndNonstring(t *testing.T) {
95 | LogAndAssertJSON(t, func(log *Logger) {
96 | log.Infoln("test", 10)
97 | }, func(fields Fields) {
98 | assert.Equal(t, fields["msg"], "test 10")
99 | })
100 | }
101 |
102 | func TestInfolnShouldAddSpacesBetweenTwoNonStrings(t *testing.T) {
103 | LogAndAssertJSON(t, func(log *Logger) {
104 | log.Infoln(10, 10)
105 | }, func(fields Fields) {
106 | assert.Equal(t, fields["msg"], "10 10")
107 | })
108 | }
109 |
110 | func TestInfoShouldAddSpacesBetweenTwoNonStrings(t *testing.T) {
111 | LogAndAssertJSON(t, func(log *Logger) {
112 | log.Infoln(10, 10)
113 | }, func(fields Fields) {
114 | assert.Equal(t, fields["msg"], "10 10")
115 | })
116 | }
117 |
118 | func TestInfoShouldNotAddSpacesBetweenStringAndNonstring(t *testing.T) {
119 | LogAndAssertJSON(t, func(log *Logger) {
120 | log.Info("test", 10)
121 | }, func(fields Fields) {
122 | assert.Equal(t, fields["msg"], "test10")
123 | })
124 | }
125 |
126 | func TestInfoShouldNotAddSpacesBetweenStrings(t *testing.T) {
127 | LogAndAssertJSON(t, func(log *Logger) {
128 | log.Info("test", "test")
129 | }, func(fields Fields) {
130 | assert.Equal(t, fields["msg"], "testtest")
131 | })
132 | }
133 |
134 | func TestWithFieldsShouldAllowAssignments(t *testing.T) {
135 | var buffer bytes.Buffer
136 | var fields Fields
137 |
138 | logger := New()
139 | logger.Out = &buffer
140 | logger.Formatter = new(JSONFormatter)
141 |
142 | localLog := logger.WithFields(Fields{
143 | "key1": "value1",
144 | })
145 |
146 | localLog.WithField("key2", "value2").Info("test")
147 | err := json.Unmarshal(buffer.Bytes(), &fields)
148 | assert.Nil(t, err)
149 |
150 | assert.Equal(t, "value2", fields["key2"])
151 | assert.Equal(t, "value1", fields["key1"])
152 |
153 | buffer = bytes.Buffer{}
154 | fields = Fields{}
155 | localLog.Info("test")
156 | err = json.Unmarshal(buffer.Bytes(), &fields)
157 | assert.Nil(t, err)
158 |
159 | _, ok := fields["key2"]
160 | assert.Equal(t, false, ok)
161 | assert.Equal(t, "value1", fields["key1"])
162 | }
163 |
164 | func TestUserSuppliedFieldDoesNotOverwriteDefaults(t *testing.T) {
165 | LogAndAssertJSON(t, func(log *Logger) {
166 | log.WithField("msg", "hello").Info("test")
167 | }, func(fields Fields) {
168 | assert.Equal(t, fields["msg"], "test")
169 | })
170 | }
171 |
172 | func TestUserSuppliedMsgFieldHasPrefix(t *testing.T) {
173 | LogAndAssertJSON(t, func(log *Logger) {
174 | log.WithField("msg", "hello").Info("test")
175 | }, func(fields Fields) {
176 | assert.Equal(t, fields["msg"], "test")
177 | assert.Equal(t, fields["fields.msg"], "hello")
178 | })
179 | }
180 |
181 | func TestUserSuppliedTimeFieldHasPrefix(t *testing.T) {
182 | LogAndAssertJSON(t, func(log *Logger) {
183 | log.WithField("time", "hello").Info("test")
184 | }, func(fields Fields) {
185 | assert.Equal(t, fields["fields.time"], "hello")
186 | })
187 | }
188 |
189 | func TestUserSuppliedLevelFieldHasPrefix(t *testing.T) {
190 | LogAndAssertJSON(t, func(log *Logger) {
191 | log.WithField("level", 1).Info("test")
192 | }, func(fields Fields) {
193 | assert.Equal(t, fields["level"], "info")
194 | assert.Equal(t, fields["fields.level"], 1.0) // JSON has floats only
195 | })
196 | }
197 |
198 | func TestDefaultFieldsAreNotPrefixed(t *testing.T) {
199 | LogAndAssertText(t, func(log *Logger) {
200 | ll := log.WithField("herp", "derp")
201 | ll.Info("hello")
202 | ll.Info("bye")
203 | }, func(fields map[string]string) {
204 | for _, fieldName := range []string{"fields.level", "fields.time", "fields.msg"} {
205 | if _, ok := fields[fieldName]; ok {
206 | t.Fatalf("should not have prefixed %q: %v", fieldName, fields)
207 | }
208 | }
209 | })
210 | }
211 |
212 | func TestDoubleLoggingDoesntPrefixPreviousFields(t *testing.T) {
213 |
214 | var buffer bytes.Buffer
215 | var fields Fields
216 |
217 | logger := New()
218 | logger.Out = &buffer
219 | logger.Formatter = new(JSONFormatter)
220 |
221 | llog := logger.WithField("context", "eating raw fish")
222 |
223 | llog.Info("looks delicious")
224 |
225 | err := json.Unmarshal(buffer.Bytes(), &fields)
226 | assert.NoError(t, err, "should have decoded first message")
227 | assert.Equal(t, len(fields), 4, "should only have msg/time/level/context fields")
228 | assert.Equal(t, fields["msg"], "looks delicious")
229 | assert.Equal(t, fields["context"], "eating raw fish")
230 |
231 | buffer.Reset()
232 |
233 | llog.Warn("omg it is!")
234 |
235 | err = json.Unmarshal(buffer.Bytes(), &fields)
236 | assert.NoError(t, err, "should have decoded second message")
237 | assert.Equal(t, len(fields), 4, "should only have msg/time/level/context fields")
238 | assert.Equal(t, fields["msg"], "omg it is!")
239 | assert.Equal(t, fields["context"], "eating raw fish")
240 | assert.Nil(t, fields["fields.msg"], "should not have prefixed previous `msg` entry")
241 |
242 | }
243 |
244 | func TestConvertLevelToString(t *testing.T) {
245 | assert.Equal(t, "debug", DebugLevel.String())
246 | assert.Equal(t, "info", InfoLevel.String())
247 | assert.Equal(t, "warning", WarnLevel.String())
248 | assert.Equal(t, "error", ErrorLevel.String())
249 | assert.Equal(t, "fatal", FatalLevel.String())
250 | assert.Equal(t, "panic", PanicLevel.String())
251 | }
252 |
253 | func TestParseLevel(t *testing.T) {
254 | l, err := ParseLevel("panic")
255 | assert.Nil(t, err)
256 | assert.Equal(t, PanicLevel, l)
257 |
258 | l, err = ParseLevel("fatal")
259 | assert.Nil(t, err)
260 | assert.Equal(t, FatalLevel, l)
261 |
262 | l, err = ParseLevel("error")
263 | assert.Nil(t, err)
264 | assert.Equal(t, ErrorLevel, l)
265 |
266 | l, err = ParseLevel("warn")
267 | assert.Nil(t, err)
268 | assert.Equal(t, WarnLevel, l)
269 |
270 | l, err = ParseLevel("warning")
271 | assert.Nil(t, err)
272 | assert.Equal(t, WarnLevel, l)
273 |
274 | l, err = ParseLevel("info")
275 | assert.Nil(t, err)
276 | assert.Equal(t, InfoLevel, l)
277 |
278 | l, err = ParseLevel("debug")
279 | assert.Nil(t, err)
280 | assert.Equal(t, DebugLevel, l)
281 |
282 | l, err = ParseLevel("invalid")
283 | assert.Equal(t, "not a valid logrus Level: \"invalid\"", err.Error())
284 | }
285 |
286 | func TestGetSetLevelRace(t *testing.T) {
287 | wg := sync.WaitGroup{}
288 | for i := 0; i < 100; i++ {
289 | wg.Add(1)
290 | go func(i int) {
291 | defer wg.Done()
292 | if i%2 == 0 {
293 | SetLevel(InfoLevel)
294 | } else {
295 | GetLevel()
296 | }
297 | }(i)
298 |
299 | }
300 | wg.Wait()
301 | }
302 |
--------------------------------------------------------------------------------
/vendor/gopkg.in/yaml.v2/encode.go:
--------------------------------------------------------------------------------
1 | package yaml
2 |
3 | import (
4 | "encoding"
5 | "fmt"
6 | "reflect"
7 | "regexp"
8 | "sort"
9 | "strconv"
10 | "strings"
11 | "time"
12 | )
13 |
14 | type encoder struct {
15 | emitter yaml_emitter_t
16 | event yaml_event_t
17 | out []byte
18 | flow bool
19 | }
20 |
21 | func newEncoder() (e *encoder) {
22 | e = &encoder{}
23 | e.must(yaml_emitter_initialize(&e.emitter))
24 | yaml_emitter_set_output_string(&e.emitter, &e.out)
25 | yaml_emitter_set_unicode(&e.emitter, true)
26 | e.must(yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING))
27 | e.emit()
28 | e.must(yaml_document_start_event_initialize(&e.event, nil, nil, true))
29 | e.emit()
30 | return e
31 | }
32 |
33 | func (e *encoder) finish() {
34 | e.must(yaml_document_end_event_initialize(&e.event, true))
35 | e.emit()
36 | e.emitter.open_ended = false
37 | e.must(yaml_stream_end_event_initialize(&e.event))
38 | e.emit()
39 | }
40 |
41 | func (e *encoder) destroy() {
42 | yaml_emitter_delete(&e.emitter)
43 | }
44 |
45 | func (e *encoder) emit() {
46 | // This will internally delete the e.event value.
47 | if !yaml_emitter_emit(&e.emitter, &e.event) && e.event.typ != yaml_DOCUMENT_END_EVENT && e.event.typ != yaml_STREAM_END_EVENT {
48 | e.must(false)
49 | }
50 | }
51 |
52 | func (e *encoder) must(ok bool) {
53 | if !ok {
54 | msg := e.emitter.problem
55 | if msg == "" {
56 | msg = "unknown problem generating YAML content"
57 | }
58 | failf("%s", msg)
59 | }
60 | }
61 |
62 | func (e *encoder) marshal(tag string, in reflect.Value) {
63 | if !in.IsValid() {
64 | e.nilv()
65 | return
66 | }
67 | iface := in.Interface()
68 | if m, ok := iface.(Marshaler); ok {
69 | v, err := m.MarshalYAML()
70 | if err != nil {
71 | fail(err)
72 | }
73 | if v == nil {
74 | e.nilv()
75 | return
76 | }
77 | in = reflect.ValueOf(v)
78 | } else if m, ok := iface.(encoding.TextMarshaler); ok {
79 | text, err := m.MarshalText()
80 | if err != nil {
81 | fail(err)
82 | }
83 | in = reflect.ValueOf(string(text))
84 | }
85 | switch in.Kind() {
86 | case reflect.Interface:
87 | if in.IsNil() {
88 | e.nilv()
89 | } else {
90 | e.marshal(tag, in.Elem())
91 | }
92 | case reflect.Map:
93 | e.mapv(tag, in)
94 | case reflect.Ptr:
95 | if in.IsNil() {
96 | e.nilv()
97 | } else {
98 | e.marshal(tag, in.Elem())
99 | }
100 | case reflect.Struct:
101 | e.structv(tag, in)
102 | case reflect.Slice:
103 | if in.Type().Elem() == mapItemType {
104 | e.itemsv(tag, in)
105 | } else {
106 | e.slicev(tag, in)
107 | }
108 | case reflect.String:
109 | e.stringv(tag, in)
110 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
111 | if in.Type() == durationType {
112 | e.stringv(tag, reflect.ValueOf(iface.(time.Duration).String()))
113 | } else {
114 | e.intv(tag, in)
115 | }
116 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
117 | e.uintv(tag, in)
118 | case reflect.Float32, reflect.Float64:
119 | e.floatv(tag, in)
120 | case reflect.Bool:
121 | e.boolv(tag, in)
122 | default:
123 | panic("cannot marshal type: " + in.Type().String())
124 | }
125 | }
126 |
127 | func (e *encoder) mapv(tag string, in reflect.Value) {
128 | e.mappingv(tag, func() {
129 | keys := keyList(in.MapKeys())
130 | sort.Sort(keys)
131 | for _, k := range keys {
132 | e.marshal("", k)
133 | e.marshal("", in.MapIndex(k))
134 | }
135 | })
136 | }
137 |
138 | func (e *encoder) itemsv(tag string, in reflect.Value) {
139 | e.mappingv(tag, func() {
140 | slice := in.Convert(reflect.TypeOf([]MapItem{})).Interface().([]MapItem)
141 | for _, item := range slice {
142 | e.marshal("", reflect.ValueOf(item.Key))
143 | e.marshal("", reflect.ValueOf(item.Value))
144 | }
145 | })
146 | }
147 |
148 | func (e *encoder) structv(tag string, in reflect.Value) {
149 | sinfo, err := getStructInfo(in.Type())
150 | if err != nil {
151 | panic(err)
152 | }
153 | e.mappingv(tag, func() {
154 | for _, info := range sinfo.FieldsList {
155 | var value reflect.Value
156 | if info.Inline == nil {
157 | value = in.Field(info.Num)
158 | } else {
159 | value = in.FieldByIndex(info.Inline)
160 | }
161 | if info.OmitEmpty && isZero(value) {
162 | continue
163 | }
164 | e.marshal("", reflect.ValueOf(info.Key))
165 | e.flow = info.Flow
166 | e.marshal("", value)
167 | }
168 | if sinfo.InlineMap >= 0 {
169 | m := in.Field(sinfo.InlineMap)
170 | if m.Len() > 0 {
171 | e.flow = false
172 | keys := keyList(m.MapKeys())
173 | sort.Sort(keys)
174 | for _, k := range keys {
175 | if _, found := sinfo.FieldsMap[k.String()]; found {
176 | panic(fmt.Sprintf("Can't have key %q in inlined map; conflicts with struct field", k.String()))
177 | }
178 | e.marshal("", k)
179 | e.flow = false
180 | e.marshal("", m.MapIndex(k))
181 | }
182 | }
183 | }
184 | })
185 | }
186 |
187 | func (e *encoder) mappingv(tag string, f func()) {
188 | implicit := tag == ""
189 | style := yaml_BLOCK_MAPPING_STYLE
190 | if e.flow {
191 | e.flow = false
192 | style = yaml_FLOW_MAPPING_STYLE
193 | }
194 | e.must(yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style))
195 | e.emit()
196 | f()
197 | e.must(yaml_mapping_end_event_initialize(&e.event))
198 | e.emit()
199 | }
200 |
201 | func (e *encoder) slicev(tag string, in reflect.Value) {
202 | implicit := tag == ""
203 | style := yaml_BLOCK_SEQUENCE_STYLE
204 | if e.flow {
205 | e.flow = false
206 | style = yaml_FLOW_SEQUENCE_STYLE
207 | }
208 | e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style))
209 | e.emit()
210 | n := in.Len()
211 | for i := 0; i < n; i++ {
212 | e.marshal("", in.Index(i))
213 | }
214 | e.must(yaml_sequence_end_event_initialize(&e.event))
215 | e.emit()
216 | }
217 |
218 | // isBase60 returns whether s is in base 60 notation as defined in YAML 1.1.
219 | //
220 | // The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported
221 | // in YAML 1.2 and by this package, but these should be marshalled quoted for
222 | // the time being for compatibility with other parsers.
223 | func isBase60Float(s string) (result bool) {
224 | // Fast path.
225 | if s == "" {
226 | return false
227 | }
228 | c := s[0]
229 | if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 {
230 | return false
231 | }
232 | // Do the full match.
233 | return base60float.MatchString(s)
234 | }
235 |
236 | // From http://yaml.org/type/float.html, except the regular expression there
237 | // is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix.
238 | var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`)
239 |
240 | func (e *encoder) stringv(tag string, in reflect.Value) {
241 | var style yaml_scalar_style_t
242 | s := in.String()
243 | rtag, rs := resolve("", s)
244 | if rtag == yaml_BINARY_TAG {
245 | if tag == "" || tag == yaml_STR_TAG {
246 | tag = rtag
247 | s = rs.(string)
248 | } else if tag == yaml_BINARY_TAG {
249 | failf("explicitly tagged !!binary data must be base64-encoded")
250 | } else {
251 | failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag))
252 | }
253 | }
254 | if tag == "" && (rtag != yaml_STR_TAG || isBase60Float(s)) {
255 | style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
256 | } else if strings.Contains(s, "\n") {
257 | style = yaml_LITERAL_SCALAR_STYLE
258 | } else {
259 | style = yaml_PLAIN_SCALAR_STYLE
260 | }
261 | e.emitScalar(s, "", tag, style)
262 | }
263 |
264 | func (e *encoder) boolv(tag string, in reflect.Value) {
265 | var s string
266 | if in.Bool() {
267 | s = "true"
268 | } else {
269 | s = "false"
270 | }
271 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
272 | }
273 |
274 | func (e *encoder) intv(tag string, in reflect.Value) {
275 | s := strconv.FormatInt(in.Int(), 10)
276 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
277 | }
278 |
279 | func (e *encoder) uintv(tag string, in reflect.Value) {
280 | s := strconv.FormatUint(in.Uint(), 10)
281 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
282 | }
283 |
284 | func (e *encoder) floatv(tag string, in reflect.Value) {
285 | // FIXME: Handle 64 bits here.
286 | s := strconv.FormatFloat(float64(in.Float()), 'g', -1, 32)
287 | switch s {
288 | case "+Inf":
289 | s = ".inf"
290 | case "-Inf":
291 | s = "-.inf"
292 | case "NaN":
293 | s = ".nan"
294 | }
295 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
296 | }
297 |
298 | func (e *encoder) nilv() {
299 | e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE)
300 | }
301 |
302 | func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t) {
303 | implicit := tag == ""
304 | e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style))
305 | e.emit()
306 | }
307 |
--------------------------------------------------------------------------------
/vendor/gopkg.in/yaml.v2/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Copyright (c) 2011-2014 - Canonical Inc.
3 |
4 | This software is licensed under the LGPLv3, included below.
5 |
6 | As a special exception to the GNU Lesser General Public License version 3
7 | ("LGPL3"), the copyright holders of this Library give you permission to
8 | convey to a third party a Combined Work that links statically or dynamically
9 | to this Library without providing any Minimal Corresponding Source or
10 | Minimal Application Code as set out in 4d or providing the installation
11 | information set out in section 4e, provided that you comply with the other
12 | provisions of LGPL3 and provided that you meet, for the Application the
13 | terms and conditions of the license(s) which apply to the Application.
14 |
15 | Except as stated in this special exception, the provisions of LGPL3 will
16 | continue to comply in full to this Library. If you modify this Library, you
17 | may apply this exception to your version of this Library, but you are not
18 | obliged to do so. If you do not wish to do so, delete this exception
19 | statement from your version. This exception does not (and cannot) modify any
20 | license terms which apply to the Application, with which you must still
21 | comply.
22 |
23 |
24 | GNU LESSER GENERAL PUBLIC LICENSE
25 | Version 3, 29 June 2007
26 |
27 | Copyright (C) 2007 Free Software Foundation, Inc.
28 | Everyone is permitted to copy and distribute verbatim copies
29 | of this license document, but changing it is not allowed.
30 |
31 |
32 | This version of the GNU Lesser General Public License incorporates
33 | the terms and conditions of version 3 of the GNU General Public
34 | License, supplemented by the additional permissions listed below.
35 |
36 | 0. Additional Definitions.
37 |
38 | As used herein, "this License" refers to version 3 of the GNU Lesser
39 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
40 | General Public License.
41 |
42 | "The Library" refers to a covered work governed by this License,
43 | other than an Application or a Combined Work as defined below.
44 |
45 | An "Application" is any work that makes use of an interface provided
46 | by the Library, but which is not otherwise based on the Library.
47 | Defining a subclass of a class defined by the Library is deemed a mode
48 | of using an interface provided by the Library.
49 |
50 | A "Combined Work" is a work produced by combining or linking an
51 | Application with the Library. The particular version of the Library
52 | with which the Combined Work was made is also called the "Linked
53 | Version".
54 |
55 | The "Minimal Corresponding Source" for a Combined Work means the
56 | Corresponding Source for the Combined Work, excluding any source code
57 | for portions of the Combined Work that, considered in isolation, are
58 | based on the Application, and not on the Linked Version.
59 |
60 | The "Corresponding Application Code" for a Combined Work means the
61 | object code and/or source code for the Application, including any data
62 | and utility programs needed for reproducing the Combined Work from the
63 | Application, but excluding the System Libraries of the Combined Work.
64 |
65 | 1. Exception to Section 3 of the GNU GPL.
66 |
67 | You may convey a covered work under sections 3 and 4 of this License
68 | without being bound by section 3 of the GNU GPL.
69 |
70 | 2. Conveying Modified Versions.
71 |
72 | If you modify a copy of the Library, and, in your modifications, a
73 | facility refers to a function or data to be supplied by an Application
74 | that uses the facility (other than as an argument passed when the
75 | facility is invoked), then you may convey a copy of the modified
76 | version:
77 |
78 | a) under this License, provided that you make a good faith effort to
79 | ensure that, in the event an Application does not supply the
80 | function or data, the facility still operates, and performs
81 | whatever part of its purpose remains meaningful, or
82 |
83 | b) under the GNU GPL, with none of the additional permissions of
84 | this License applicable to that copy.
85 |
86 | 3. Object Code Incorporating Material from Library Header Files.
87 |
88 | The object code form of an Application may incorporate material from
89 | a header file that is part of the Library. You may convey such object
90 | code under terms of your choice, provided that, if the incorporated
91 | material is not limited to numerical parameters, data structure
92 | layouts and accessors, or small macros, inline functions and templates
93 | (ten or fewer lines in length), you do both of the following:
94 |
95 | a) Give prominent notice with each copy of the object code that the
96 | Library is used in it and that the Library and its use are
97 | covered by this License.
98 |
99 | b) Accompany the object code with a copy of the GNU GPL and this license
100 | document.
101 |
102 | 4. Combined Works.
103 |
104 | You may convey a Combined Work under terms of your choice that,
105 | taken together, effectively do not restrict modification of the
106 | portions of the Library contained in the Combined Work and reverse
107 | engineering for debugging such modifications, if you also do each of
108 | the following:
109 |
110 | a) Give prominent notice with each copy of the Combined Work that
111 | the Library is used in it and that the Library and its use are
112 | covered by this License.
113 |
114 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
115 | document.
116 |
117 | c) For a Combined Work that displays copyright notices during
118 | execution, include the copyright notice for the Library among
119 | these notices, as well as a reference directing the user to the
120 | copies of the GNU GPL and this license document.
121 |
122 | d) Do one of the following:
123 |
124 | 0) Convey the Minimal Corresponding Source under the terms of this
125 | License, and the Corresponding Application Code in a form
126 | suitable for, and under terms that permit, the user to
127 | recombine or relink the Application with a modified version of
128 | the Linked Version to produce a modified Combined Work, in the
129 | manner specified by section 6 of the GNU GPL for conveying
130 | Corresponding Source.
131 |
132 | 1) Use a suitable shared library mechanism for linking with the
133 | Library. A suitable mechanism is one that (a) uses at run time
134 | a copy of the Library already present on the user's computer
135 | system, and (b) will operate properly with a modified version
136 | of the Library that is interface-compatible with the Linked
137 | Version.
138 |
139 | e) Provide Installation Information, but only if you would otherwise
140 | be required to provide such information under section 6 of the
141 | GNU GPL, and only to the extent that such information is
142 | necessary to install and execute a modified version of the
143 | Combined Work produced by recombining or relinking the
144 | Application with a modified version of the Linked Version. (If
145 | you use option 4d0, the Installation Information must accompany
146 | the Minimal Corresponding Source and Corresponding Application
147 | Code. If you use option 4d1, you must provide the Installation
148 | Information in the manner specified by section 6 of the GNU GPL
149 | for conveying Corresponding Source.)
150 |
151 | 5. Combined Libraries.
152 |
153 | You may place library facilities that are a work based on the
154 | Library side by side in a single library together with other library
155 | facilities that are not Applications and are not covered by this
156 | License, and convey such a combined library under terms of your
157 | choice, if you do both of the following:
158 |
159 | a) Accompany the combined library with a copy of the same work based
160 | on the Library, uncombined with any other library facilities,
161 | conveyed under the terms of this License.
162 |
163 | b) Give prominent notice with the combined library that part of it
164 | is a work based on the Library, and explaining where to find the
165 | accompanying uncombined form of the same work.
166 |
167 | 6. Revised Versions of the GNU Lesser General Public License.
168 |
169 | The Free Software Foundation may publish revised and/or new versions
170 | of the GNU Lesser General Public License from time to time. Such new
171 | versions will be similar in spirit to the present version, but may
172 | differ in detail to address new problems or concerns.
173 |
174 | Each version is given a distinguishing version number. If the
175 | Library as you received it specifies that a certain numbered version
176 | of the GNU Lesser General Public License "or any later version"
177 | applies to it, you have the option of following the terms and
178 | conditions either of that published version or of any later version
179 | published by the Free Software Foundation. If the Library as you
180 | received it does not specify a version number of the GNU Lesser
181 | General Public License, you may choose any version of the GNU Lesser
182 | General Public License ever published by the Free Software Foundation.
183 |
184 | If the Library as you received it specifies that a proxy can decide
185 | whether future versions of the GNU Lesser General Public License shall
186 | apply, that proxy's public statement of acceptance of any version is
187 | permanent authorization for you to choose that version for the
188 | Library.
189 |
--------------------------------------------------------------------------------
/vendor/github.com/codegangsta/cli/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/codegangsta/cli)
2 |
3 | # cli.go
4 | cli.go is simple, fast, and fun package for building command line apps in Go. The goal is to enable developers to write fast and distributable command line applications in an expressive way.
5 |
6 | You can view the API docs here:
7 | http://godoc.org/github.com/codegangsta/cli
8 |
9 | ## Overview
10 | Command line apps are usually so tiny that there is absolutely no reason why your code should *not* be self-documenting. Things like generating help text and parsing command flags/options should not hinder productivity when writing a command line app.
11 |
12 | **This is where cli.go comes into play.** cli.go makes command line programming fun, organized, and expressive!
13 |
14 | ## Installation
15 | Make sure you have a working Go environment (go 1.1+ is *required*). [See the install instructions](http://golang.org/doc/install.html).
16 |
17 | To install `cli.go`, simply run:
18 | ```
19 | $ go get github.com/codegangsta/cli
20 | ```
21 |
22 | Make sure your `PATH` includes to the `$GOPATH/bin` directory so your commands can be easily used:
23 | ```
24 | export PATH=$PATH:$GOPATH/bin
25 | ```
26 |
27 | ## Getting Started
28 | One of the philosophies behind cli.go is that an API should be playful and full of discovery. So a cli.go app can be as little as one line of code in `main()`.
29 |
30 | ``` go
31 | package main
32 |
33 | import (
34 | "os"
35 | "github.com/codegangsta/cli"
36 | )
37 |
38 | func main() {
39 | cli.NewApp().Run(os.Args)
40 | }
41 | ```
42 |
43 | This app will run and show help text, but is not very useful. Let's give an action to execute and some help documentation:
44 |
45 | ``` go
46 | package main
47 |
48 | import (
49 | "os"
50 | "github.com/codegangsta/cli"
51 | )
52 |
53 | func main() {
54 | app := cli.NewApp()
55 | app.Name = "boom"
56 | app.Usage = "make an explosive entrance"
57 | app.Action = func(c *cli.Context) {
58 | println("boom! I say!")
59 | }
60 |
61 | app.Run(os.Args)
62 | }
63 | ```
64 |
65 | Running this already gives you a ton of functionality, plus support for things like subcommands and flags, which are covered below.
66 |
67 | ## Example
68 |
69 | Being a programmer can be a lonely job. Thankfully by the power of automation that is not the case! Let's create a greeter app to fend off our demons of loneliness!
70 |
71 | Start by creating a directory named `greet`, and within it, add a file, `greet.go` with the following code in it:
72 |
73 | ``` go
74 | package main
75 |
76 | import (
77 | "os"
78 | "github.com/codegangsta/cli"
79 | )
80 |
81 | func main() {
82 | app := cli.NewApp()
83 | app.Name = "greet"
84 | app.Usage = "fight the loneliness!"
85 | app.Action = func(c *cli.Context) {
86 | println("Hello friend!")
87 | }
88 |
89 | app.Run(os.Args)
90 | }
91 | ```
92 |
93 | Install our command to the `$GOPATH/bin` directory:
94 |
95 | ```
96 | $ go install
97 | ```
98 |
99 | Finally run our new command:
100 |
101 | ```
102 | $ greet
103 | Hello friend!
104 | ```
105 |
106 | cli.go also generates some bitchass help text:
107 | ```
108 | $ greet help
109 | NAME:
110 | greet - fight the loneliness!
111 |
112 | USAGE:
113 | greet [global options] command [command options] [arguments...]
114 |
115 | VERSION:
116 | 0.0.0
117 |
118 | COMMANDS:
119 | help, h Shows a list of commands or help for one command
120 |
121 | GLOBAL OPTIONS
122 | --version Shows version information
123 | ```
124 |
125 | ### Arguments
126 | You can lookup arguments by calling the `Args` function on `cli.Context`.
127 |
128 | ``` go
129 | ...
130 | app.Action = func(c *cli.Context) {
131 | println("Hello", c.Args()[0])
132 | }
133 | ...
134 | ```
135 |
136 | ### Flags
137 | Setting and querying flags is simple.
138 | ``` go
139 | ...
140 | app.Flags = []cli.Flag {
141 | cli.StringFlag{
142 | Name: "lang",
143 | Value: "english",
144 | Usage: "language for the greeting",
145 | },
146 | }
147 | app.Action = func(c *cli.Context) {
148 | name := "someone"
149 | if len(c.Args()) > 0 {
150 | name = c.Args()[0]
151 | }
152 | if c.String("lang") == "spanish" {
153 | println("Hola", name)
154 | } else {
155 | println("Hello", name)
156 | }
157 | }
158 | ...
159 | ```
160 |
161 | See full list of flags at http://godoc.org/github.com/codegangsta/cli
162 |
163 | #### Alternate Names
164 |
165 | You can set alternate (or short) names for flags by providing a comma-delimited list for the `Name`. e.g.
166 |
167 | ``` go
168 | app.Flags = []cli.Flag {
169 | cli.StringFlag{
170 | Name: "lang, l",
171 | Value: "english",
172 | Usage: "language for the greeting",
173 | },
174 | }
175 | ```
176 |
177 | That flag can then be set with `--lang spanish` or `-l spanish`. Note that giving two different forms of the same flag in the same command invocation is an error.
178 |
179 | #### Values from the Environment
180 |
181 | You can also have the default value set from the environment via `EnvVar`. e.g.
182 |
183 | ``` go
184 | app.Flags = []cli.Flag {
185 | cli.StringFlag{
186 | Name: "lang, l",
187 | Value: "english",
188 | Usage: "language for the greeting",
189 | EnvVar: "APP_LANG",
190 | },
191 | }
192 | ```
193 |
194 | The `EnvVar` may also be given as a comma-delimited "cascade", where the first environment variable that resolves is used as the default.
195 |
196 | ``` go
197 | app.Flags = []cli.Flag {
198 | cli.StringFlag{
199 | Name: "lang, l",
200 | Value: "english",
201 | Usage: "language for the greeting",
202 | EnvVar: "LEGACY_COMPAT_LANG,APP_LANG,LANG",
203 | },
204 | }
205 | ```
206 |
207 | ### Subcommands
208 |
209 | Subcommands can be defined for a more git-like command line app.
210 | ```go
211 | ...
212 | app.Commands = []cli.Command{
213 | {
214 | Name: "add",
215 | Aliases: []string{"a"},
216 | Usage: "add a task to the list",
217 | Action: func(c *cli.Context) {
218 | println("added task: ", c.Args().First())
219 | },
220 | },
221 | {
222 | Name: "complete",
223 | Aliases: []string{"c"},
224 | Usage: "complete a task on the list",
225 | Action: func(c *cli.Context) {
226 | println("completed task: ", c.Args().First())
227 | },
228 | },
229 | {
230 | Name: "template",
231 | Aliases: []string{"r"},
232 | Usage: "options for task templates",
233 | Subcommands: []cli.Command{
234 | {
235 | Name: "add",
236 | Usage: "add a new template",
237 | Action: func(c *cli.Context) {
238 | println("new task template: ", c.Args().First())
239 | },
240 | },
241 | {
242 | Name: "remove",
243 | Usage: "remove an existing template",
244 | Action: func(c *cli.Context) {
245 | println("removed task template: ", c.Args().First())
246 | },
247 | },
248 | },
249 | },
250 | }
251 | ...
252 | ```
253 |
254 | ### Bash Completion
255 |
256 | You can enable completion commands by setting the `EnableBashCompletion`
257 | flag on the `App` object. By default, this setting will only auto-complete to
258 | show an app's subcommands, but you can write your own completion methods for
259 | the App or its subcommands.
260 | ```go
261 | ...
262 | var tasks = []string{"cook", "clean", "laundry", "eat", "sleep", "code"}
263 | app := cli.NewApp()
264 | app.EnableBashCompletion = true
265 | app.Commands = []cli.Command{
266 | {
267 | Name: "complete",
268 | Aliases: []string{"c"},
269 | Usage: "complete a task on the list",
270 | Action: func(c *cli.Context) {
271 | println("completed task: ", c.Args().First())
272 | },
273 | BashComplete: func(c *cli.Context) {
274 | // This will complete if no args are passed
275 | if len(c.Args()) > 0 {
276 | return
277 | }
278 | for _, t := range tasks {
279 | fmt.Println(t)
280 | }
281 | },
282 | }
283 | }
284 | ...
285 | ```
286 |
287 | #### To Enable
288 |
289 | Source the `autocomplete/bash_autocomplete` file in your `.bashrc` file while
290 | setting the `PROG` variable to the name of your program:
291 |
292 | `PROG=myprogram source /.../cli/autocomplete/bash_autocomplete`
293 |
294 | #### To Distribute
295 |
296 | Copy and modify `autocomplete/bash_autocomplete` to use your program name
297 | rather than `$PROG` and have the user copy the file into
298 | `/etc/bash_completion.d/` (or automatically install it there if you are
299 | distributing a package). Alternatively you can just document that users should
300 | source the generic `autocomplete/bash_autocomplete` with `$PROG` set to your
301 | program name in their bash configuration.
302 |
303 | ## Contribution Guidelines
304 | Feel free to put up a pull request to fix a bug or maybe add a feature. I will give it a code review and make sure that it does not break backwards compatibility. If I or any other collaborators agree that it is in line with the vision of the project, we will work with you to get the code into a mergeable state and merge it into the master branch.
305 |
306 | If you have contributed something significant to the project, I will most likely add you as a collaborator. As a collaborator you are given the ability to merge others pull requests. It is very important that new code does not break existing code, so be careful about what code you do choose to merge. If you have any questions feel free to link @codegangsta to the issue in question and we can review it together.
307 |
308 | If you feel like you have contributed to the project but have not yet been added as a collaborator, I probably forgot to add you. Hit @codegangsta up over email and we will get it figured out.
309 |
--------------------------------------------------------------------------------
/vendor/github.com/codegangsta/cli/context.go:
--------------------------------------------------------------------------------
1 | package cli
2 |
3 | import (
4 | "errors"
5 | "flag"
6 | "strconv"
7 | "strings"
8 | "time"
9 | )
10 |
11 | // Context is a type that is passed through to
12 | // each Handler action in a cli application. Context
13 | // can be used to retrieve context-specific Args and
14 | // parsed command-line options.
15 | type Context struct {
16 | App *App
17 | Command Command
18 | flagSet *flag.FlagSet
19 | setFlags map[string]bool
20 | globalSetFlags map[string]bool
21 | parentContext *Context
22 | }
23 |
24 | // Creates a new context. For use in when invoking an App or Command action.
25 | func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context {
26 | return &Context{App: app, flagSet: set, parentContext: parentCtx}
27 | }
28 |
29 | // Looks up the value of a local int flag, returns 0 if no int flag exists
30 | func (c *Context) Int(name string) int {
31 | return lookupInt(name, c.flagSet)
32 | }
33 |
34 | // Looks up the value of a local time.Duration flag, returns 0 if no time.Duration flag exists
35 | func (c *Context) Duration(name string) time.Duration {
36 | return lookupDuration(name, c.flagSet)
37 | }
38 |
39 | // Looks up the value of a local float64 flag, returns 0 if no float64 flag exists
40 | func (c *Context) Float64(name string) float64 {
41 | return lookupFloat64(name, c.flagSet)
42 | }
43 |
44 | // Looks up the value of a local bool flag, returns false if no bool flag exists
45 | func (c *Context) Bool(name string) bool {
46 | return lookupBool(name, c.flagSet)
47 | }
48 |
49 | // Looks up the value of a local boolT flag, returns false if no bool flag exists
50 | func (c *Context) BoolT(name string) bool {
51 | return lookupBoolT(name, c.flagSet)
52 | }
53 |
54 | // Looks up the value of a local string flag, returns "" if no string flag exists
55 | func (c *Context) String(name string) string {
56 | return lookupString(name, c.flagSet)
57 | }
58 |
59 | // Looks up the value of a local string slice flag, returns nil if no string slice flag exists
60 | func (c *Context) StringSlice(name string) []string {
61 | return lookupStringSlice(name, c.flagSet)
62 | }
63 |
64 | // Looks up the value of a local int slice flag, returns nil if no int slice flag exists
65 | func (c *Context) IntSlice(name string) []int {
66 | return lookupIntSlice(name, c.flagSet)
67 | }
68 |
69 | // Looks up the value of a local generic flag, returns nil if no generic flag exists
70 | func (c *Context) Generic(name string) interface{} {
71 | return lookupGeneric(name, c.flagSet)
72 | }
73 |
74 | // Looks up the value of a global int flag, returns 0 if no int flag exists
75 | func (c *Context) GlobalInt(name string) int {
76 | if fs := lookupGlobalFlagSet(name, c); fs != nil {
77 | return lookupInt(name, fs)
78 | }
79 | return 0
80 | }
81 |
82 | // Looks up the value of a global time.Duration flag, returns 0 if no time.Duration flag exists
83 | func (c *Context) GlobalDuration(name string) time.Duration {
84 | if fs := lookupGlobalFlagSet(name, c); fs != nil {
85 | return lookupDuration(name, fs)
86 | }
87 | return 0
88 | }
89 |
90 | // Looks up the value of a global bool flag, returns false if no bool flag exists
91 | func (c *Context) GlobalBool(name string) bool {
92 | if fs := lookupGlobalFlagSet(name, c); fs != nil {
93 | return lookupBool(name, fs)
94 | }
95 | return false
96 | }
97 |
98 | // Looks up the value of a global string flag, returns "" if no string flag exists
99 | func (c *Context) GlobalString(name string) string {
100 | if fs := lookupGlobalFlagSet(name, c); fs != nil {
101 | return lookupString(name, fs)
102 | }
103 | return ""
104 | }
105 |
106 | // Looks up the value of a global string slice flag, returns nil if no string slice flag exists
107 | func (c *Context) GlobalStringSlice(name string) []string {
108 | if fs := lookupGlobalFlagSet(name, c); fs != nil {
109 | return lookupStringSlice(name, fs)
110 | }
111 | return nil
112 | }
113 |
114 | // Looks up the value of a global int slice flag, returns nil if no int slice flag exists
115 | func (c *Context) GlobalIntSlice(name string) []int {
116 | if fs := lookupGlobalFlagSet(name, c); fs != nil {
117 | return lookupIntSlice(name, fs)
118 | }
119 | return nil
120 | }
121 |
122 | // Looks up the value of a global generic flag, returns nil if no generic flag exists
123 | func (c *Context) GlobalGeneric(name string) interface{} {
124 | if fs := lookupGlobalFlagSet(name, c); fs != nil {
125 | return lookupGeneric(name, fs)
126 | }
127 | return nil
128 | }
129 |
130 | // Returns the number of flags set
131 | func (c *Context) NumFlags() int {
132 | return c.flagSet.NFlag()
133 | }
134 |
135 | // Determines if the flag was actually set
136 | func (c *Context) IsSet(name string) bool {
137 | if c.setFlags == nil {
138 | c.setFlags = make(map[string]bool)
139 | c.flagSet.Visit(func(f *flag.Flag) {
140 | c.setFlags[f.Name] = true
141 | })
142 | }
143 | return c.setFlags[name] == true
144 | }
145 |
146 | // Determines if the global flag was actually set
147 | func (c *Context) GlobalIsSet(name string) bool {
148 | if c.globalSetFlags == nil {
149 | c.globalSetFlags = make(map[string]bool)
150 | ctx := c
151 | if ctx.parentContext != nil {
152 | ctx = ctx.parentContext
153 | }
154 | for ; ctx != nil && c.globalSetFlags[name] == false; ctx = ctx.parentContext {
155 | ctx.flagSet.Visit(func(f *flag.Flag) {
156 | c.globalSetFlags[f.Name] = true
157 | })
158 | }
159 | }
160 | return c.globalSetFlags[name]
161 | }
162 |
163 | // Returns a slice of flag names used in this context.
164 | func (c *Context) FlagNames() (names []string) {
165 | for _, flag := range c.Command.Flags {
166 | name := strings.Split(flag.getName(), ",")[0]
167 | if name == "help" {
168 | continue
169 | }
170 | names = append(names, name)
171 | }
172 | return
173 | }
174 |
175 | // Returns a slice of global flag names used by the app.
176 | func (c *Context) GlobalFlagNames() (names []string) {
177 | for _, flag := range c.App.Flags {
178 | name := strings.Split(flag.getName(), ",")[0]
179 | if name == "help" || name == "version" {
180 | continue
181 | }
182 | names = append(names, name)
183 | }
184 | return
185 | }
186 |
187 | // Returns the parent context, if any
188 | func (c *Context) Parent() *Context {
189 | return c.parentContext
190 | }
191 |
192 | type Args []string
193 |
194 | // Returns the command line arguments associated with the context.
195 | func (c *Context) Args() Args {
196 | args := Args(c.flagSet.Args())
197 | return args
198 | }
199 |
200 | // Returns the nth argument, or else a blank string
201 | func (a Args) Get(n int) string {
202 | if len(a) > n {
203 | return a[n]
204 | }
205 | return ""
206 | }
207 |
208 | // Returns the first argument, or else a blank string
209 | func (a Args) First() string {
210 | return a.Get(0)
211 | }
212 |
213 | // Return the rest of the arguments (not the first one)
214 | // or else an empty string slice
215 | func (a Args) Tail() []string {
216 | if len(a) >= 2 {
217 | return []string(a)[1:]
218 | }
219 | return []string{}
220 | }
221 |
222 | // Checks if there are any arguments present
223 | func (a Args) Present() bool {
224 | return len(a) != 0
225 | }
226 |
227 | // Swaps arguments at the given indexes
228 | func (a Args) Swap(from, to int) error {
229 | if from >= len(a) || to >= len(a) {
230 | return errors.New("index out of range")
231 | }
232 | a[from], a[to] = a[to], a[from]
233 | return nil
234 | }
235 |
236 | func lookupGlobalFlagSet(name string, ctx *Context) *flag.FlagSet {
237 | if ctx.parentContext != nil {
238 | ctx = ctx.parentContext
239 | }
240 | for ; ctx != nil; ctx = ctx.parentContext {
241 | if f := ctx.flagSet.Lookup(name); f != nil {
242 | return ctx.flagSet
243 | }
244 | }
245 | return nil
246 | }
247 |
248 | func lookupInt(name string, set *flag.FlagSet) int {
249 | f := set.Lookup(name)
250 | if f != nil {
251 | val, err := strconv.Atoi(f.Value.String())
252 | if err != nil {
253 | return 0
254 | }
255 | return val
256 | }
257 |
258 | return 0
259 | }
260 |
261 | func lookupDuration(name string, set *flag.FlagSet) time.Duration {
262 | f := set.Lookup(name)
263 | if f != nil {
264 | val, err := time.ParseDuration(f.Value.String())
265 | if err == nil {
266 | return val
267 | }
268 | }
269 |
270 | return 0
271 | }
272 |
273 | func lookupFloat64(name string, set *flag.FlagSet) float64 {
274 | f := set.Lookup(name)
275 | if f != nil {
276 | val, err := strconv.ParseFloat(f.Value.String(), 64)
277 | if err != nil {
278 | return 0
279 | }
280 | return val
281 | }
282 |
283 | return 0
284 | }
285 |
286 | func lookupString(name string, set *flag.FlagSet) string {
287 | f := set.Lookup(name)
288 | if f != nil {
289 | return f.Value.String()
290 | }
291 |
292 | return ""
293 | }
294 |
295 | func lookupStringSlice(name string, set *flag.FlagSet) []string {
296 | f := set.Lookup(name)
297 | if f != nil {
298 | return (f.Value.(*StringSlice)).Value()
299 |
300 | }
301 |
302 | return nil
303 | }
304 |
305 | func lookupIntSlice(name string, set *flag.FlagSet) []int {
306 | f := set.Lookup(name)
307 | if f != nil {
308 | return (f.Value.(*IntSlice)).Value()
309 |
310 | }
311 |
312 | return nil
313 | }
314 |
315 | func lookupGeneric(name string, set *flag.FlagSet) interface{} {
316 | f := set.Lookup(name)
317 | if f != nil {
318 | return f.Value
319 | }
320 | return nil
321 | }
322 |
323 | func lookupBool(name string, set *flag.FlagSet) bool {
324 | f := set.Lookup(name)
325 | if f != nil {
326 | val, err := strconv.ParseBool(f.Value.String())
327 | if err != nil {
328 | return false
329 | }
330 | return val
331 | }
332 |
333 | return false
334 | }
335 |
336 | func lookupBoolT(name string, set *flag.FlagSet) bool {
337 | f := set.Lookup(name)
338 | if f != nil {
339 | val, err := strconv.ParseBool(f.Value.String())
340 | if err != nil {
341 | return true
342 | }
343 | return val
344 | }
345 |
346 | return false
347 | }
348 |
349 | func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) {
350 | switch ff.Value.(type) {
351 | case *StringSlice:
352 | default:
353 | set.Set(name, ff.Value.String())
354 | }
355 | }
356 |
357 | func normalizeFlags(flags []Flag, set *flag.FlagSet) error {
358 | visited := make(map[string]bool)
359 | set.Visit(func(f *flag.Flag) {
360 | visited[f.Name] = true
361 | })
362 | for _, f := range flags {
363 | parts := strings.Split(f.getName(), ",")
364 | if len(parts) == 1 {
365 | continue
366 | }
367 | var ff *flag.Flag
368 | for _, name := range parts {
369 | name = strings.Trim(name, " ")
370 | if visited[name] {
371 | if ff != nil {
372 | return errors.New("Cannot use two forms of the same flag: " + name + " " + ff.Name)
373 | }
374 | ff = set.Lookup(name)
375 | }
376 | }
377 | if ff == nil {
378 | continue
379 | }
380 | for _, name := range parts {
381 | name = strings.Trim(name, " ")
382 | if !visited[name] {
383 | copyFlag(name, ff, set)
384 | }
385 | }
386 | }
387 | return nil
388 | }
389 |
--------------------------------------------------------------------------------
/vendor/github.com/stretchr/testify/assert/forward_assertions.go:
--------------------------------------------------------------------------------
1 | package assert
2 |
3 | import "time"
4 |
5 | // Assertions provides assertion methods around the
6 | // TestingT interface.
7 | type Assertions struct {
8 | t TestingT
9 | }
10 |
11 | // New makes a new Assertions object for the specified TestingT.
12 | func New(t TestingT) *Assertions {
13 | return &Assertions{
14 | t: t,
15 | }
16 | }
17 |
18 | // Fail reports a failure through
19 | func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool {
20 | return Fail(a.t, failureMessage, msgAndArgs...)
21 | }
22 |
23 | // Implements asserts that an object is implemented by the specified interface.
24 | //
25 | // assert.Implements((*MyInterface)(nil), new(MyObject), "MyObject")
26 | func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
27 | return Implements(a.t, interfaceObject, object, msgAndArgs...)
28 | }
29 |
30 | // IsType asserts that the specified objects are of the same type.
31 | func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
32 | return IsType(a.t, expectedType, object, msgAndArgs...)
33 | }
34 |
35 | // Equal asserts that two objects are equal.
36 | //
37 | // assert.Equal(123, 123, "123 and 123 should be equal")
38 | //
39 | // Returns whether the assertion was successful (true) or not (false).
40 | func (a *Assertions) Equal(expected, actual interface{}, msgAndArgs ...interface{}) bool {
41 | return Equal(a.t, expected, actual, msgAndArgs...)
42 | }
43 |
44 | // EqualValues asserts that two objects are equal or convertable to the same types
45 | // and equal.
46 | //
47 | // assert.EqualValues(uint32(123), int32(123), "123 and 123 should be equal")
48 | //
49 | // Returns whether the assertion was successful (true) or not (false).
50 | func (a *Assertions) EqualValues(expected, actual interface{}, msgAndArgs ...interface{}) bool {
51 | return EqualValues(a.t, expected, actual, msgAndArgs...)
52 | }
53 |
54 | // Exactly asserts that two objects are equal is value and type.
55 | //
56 | // assert.Exactly(int32(123), int64(123), "123 and 123 should NOT be equal")
57 | //
58 | // Returns whether the assertion was successful (true) or not (false).
59 | func (a *Assertions) Exactly(expected, actual interface{}, msgAndArgs ...interface{}) bool {
60 | return Exactly(a.t, expected, actual, msgAndArgs...)
61 | }
62 |
63 | // NotNil asserts that the specified object is not nil.
64 | //
65 | // assert.NotNil(err, "err should be something")
66 | //
67 | // Returns whether the assertion was successful (true) or not (false).
68 | func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool {
69 | return NotNil(a.t, object, msgAndArgs...)
70 | }
71 |
72 | // Nil asserts that the specified object is nil.
73 | //
74 | // assert.Nil(err, "err should be nothing")
75 | //
76 | // Returns whether the assertion was successful (true) or not (false).
77 | func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool {
78 | return Nil(a.t, object, msgAndArgs...)
79 | }
80 |
81 | // Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or a
82 | // slice with len == 0.
83 | //
84 | // assert.Empty(obj)
85 | //
86 | // Returns whether the assertion was successful (true) or not (false).
87 | func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool {
88 | return Empty(a.t, object, msgAndArgs...)
89 | }
90 |
91 | // NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or a
92 | // slice with len == 0.
93 | //
94 | // if assert.NotEmpty(obj) {
95 | // assert.Equal("two", obj[1])
96 | // }
97 | //
98 | // Returns whether the assertion was successful (true) or not (false).
99 | func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool {
100 | return NotEmpty(a.t, object, msgAndArgs...)
101 | }
102 |
103 | // Len asserts that the specified object has specific length.
104 | // Len also fails if the object has a type that len() not accept.
105 | //
106 | // assert.Len(mySlice, 3, "The size of slice is not 3")
107 | //
108 | // Returns whether the assertion was successful (true) or not (false).
109 | func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool {
110 | return Len(a.t, object, length, msgAndArgs...)
111 | }
112 |
113 | // True asserts that the specified value is true.
114 | //
115 | // assert.True(myBool, "myBool should be true")
116 | //
117 | // Returns whether the assertion was successful (true) or not (false).
118 | func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool {
119 | return True(a.t, value, msgAndArgs...)
120 | }
121 |
122 | // False asserts that the specified value is true.
123 | //
124 | // assert.False(myBool, "myBool should be false")
125 | //
126 | // Returns whether the assertion was successful (true) or not (false).
127 | func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool {
128 | return False(a.t, value, msgAndArgs...)
129 | }
130 |
131 | // NotEqual asserts that the specified values are NOT equal.
132 | //
133 | // assert.NotEqual(obj1, obj2, "two objects shouldn't be equal")
134 | //
135 | // Returns whether the assertion was successful (true) or not (false).
136 | func (a *Assertions) NotEqual(expected, actual interface{}, msgAndArgs ...interface{}) bool {
137 | return NotEqual(a.t, expected, actual, msgAndArgs...)
138 | }
139 |
140 | // Contains asserts that the specified string contains the specified substring.
141 | //
142 | // assert.Contains("Hello World", "World", "But 'Hello World' does contain 'World'")
143 | //
144 | // Returns whether the assertion was successful (true) or not (false).
145 | func (a *Assertions) Contains(s, contains interface{}, msgAndArgs ...interface{}) bool {
146 | return Contains(a.t, s, contains, msgAndArgs...)
147 | }
148 |
149 | // NotContains asserts that the specified string does NOT contain the specified substring.
150 | //
151 | // assert.NotContains("Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'")
152 | //
153 | // Returns whether the assertion was successful (true) or not (false).
154 | func (a *Assertions) NotContains(s, contains interface{}, msgAndArgs ...interface{}) bool {
155 | return NotContains(a.t, s, contains, msgAndArgs...)
156 | }
157 |
158 | // Condition uses a Comparison to assert a complex condition.
159 | func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool {
160 | return Condition(a.t, comp, msgAndArgs...)
161 | }
162 |
163 | // Panics asserts that the code inside the specified PanicTestFunc panics.
164 | //
165 | // assert.Panics(func(){
166 | // GoCrazy()
167 | // }, "Calling GoCrazy() should panic")
168 | //
169 | // Returns whether the assertion was successful (true) or not (false).
170 | func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
171 | return Panics(a.t, f, msgAndArgs...)
172 | }
173 |
174 | // NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
175 | //
176 | // assert.NotPanics(func(){
177 | // RemainCalm()
178 | // }, "Calling RemainCalm() should NOT panic")
179 | //
180 | // Returns whether the assertion was successful (true) or not (false).
181 | func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
182 | return NotPanics(a.t, f, msgAndArgs...)
183 | }
184 |
185 | // WithinDuration asserts that the two times are within duration delta of each other.
186 | //
187 | // assert.WithinDuration(time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s")
188 | //
189 | // Returns whether the assertion was successful (true) or not (false).
190 | func (a *Assertions) WithinDuration(expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
191 | return WithinDuration(a.t, expected, actual, delta, msgAndArgs...)
192 | }
193 |
194 | // InDelta asserts that the two numerals are within delta of each other.
195 | //
196 | // assert.InDelta(t, math.Pi, (22 / 7.0), 0.01)
197 | //
198 | // Returns whether the assertion was successful (true) or not (false).
199 | func (a *Assertions) InDelta(expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
200 | return InDelta(a.t, expected, actual, delta, msgAndArgs...)
201 | }
202 |
203 | // InEpsilon asserts that expected and actual have a relative error less than epsilon
204 | //
205 | // Returns whether the assertion was successful (true) or not (false).
206 | func (a *Assertions) InEpsilon(expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
207 | return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...)
208 | }
209 |
210 | // NoError asserts that a function returned no error (i.e. `nil`).
211 | //
212 | // actualObj, err := SomeFunction()
213 | // if assert.NoError(err) {
214 | // assert.Equal(actualObj, expectedObj)
215 | // }
216 | //
217 | // Returns whether the assertion was successful (true) or not (false).
218 | func (a *Assertions) NoError(theError error, msgAndArgs ...interface{}) bool {
219 | return NoError(a.t, theError, msgAndArgs...)
220 | }
221 |
222 | // Error asserts that a function returned an error (i.e. not `nil`).
223 | //
224 | // actualObj, err := SomeFunction()
225 | // if assert.Error(err, "An error was expected") {
226 | // assert.Equal(err, expectedError)
227 | // }
228 | //
229 | // Returns whether the assertion was successful (true) or not (false).
230 | func (a *Assertions) Error(theError error, msgAndArgs ...interface{}) bool {
231 | return Error(a.t, theError, msgAndArgs...)
232 | }
233 |
234 | // EqualError asserts that a function returned an error (i.e. not `nil`)
235 | // and that it is equal to the provided error.
236 | //
237 | // actualObj, err := SomeFunction()
238 | // if assert.Error(err, "An error was expected") {
239 | // assert.Equal(err, expectedError)
240 | // }
241 | //
242 | // Returns whether the assertion was successful (true) or not (false).
243 | func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool {
244 | return EqualError(a.t, theError, errString, msgAndArgs...)
245 | }
246 |
247 | // Regexp asserts that a specified regexp matches a string.
248 | //
249 | // assert.Regexp(t, regexp.MustCompile("start"), "it's starting")
250 | // assert.Regexp(t, "start...$", "it's not starting")
251 | //
252 | // Returns whether the assertion was successful (true) or not (false).
253 | func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
254 | return Regexp(a.t, rx, str, msgAndArgs...)
255 | }
256 |
257 | // NotRegexp asserts that a specified regexp does not match a string.
258 | //
259 | // assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting")
260 | // assert.NotRegexp(t, "^start", "it's not starting")
261 | //
262 | // Returns whether the assertion was successful (true) or not (false).
263 | func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
264 | return NotRegexp(a.t, rx, str, msgAndArgs...)
265 | }
266 |
--------------------------------------------------------------------------------
/vendor/gopkg.in/yaml.v2/yaml.go:
--------------------------------------------------------------------------------
1 | // Package yaml implements YAML support for the Go language.
2 | //
3 | // Source code and other details for the project are available at GitHub:
4 | //
5 | // https://github.com/go-yaml/yaml
6 | //
7 | package yaml
8 |
9 | import (
10 | "errors"
11 | "fmt"
12 | "reflect"
13 | "strings"
14 | "sync"
15 | )
16 |
17 | // MapSlice encodes and decodes as a YAML map.
18 | // The order of keys is preserved when encoding and decoding.
19 | type MapSlice []MapItem
20 |
21 | // MapItem is an item in a MapSlice.
22 | type MapItem struct {
23 | Key, Value interface{}
24 | }
25 |
26 | // The Unmarshaler interface may be implemented by types to customize their
27 | // behavior when being unmarshaled from a YAML document. The UnmarshalYAML
28 | // method receives a function that may be called to unmarshal the original
29 | // YAML value into a field or variable. It is safe to call the unmarshal
30 | // function parameter more than once if necessary.
31 | type Unmarshaler interface {
32 | UnmarshalYAML(unmarshal func(interface{}) error) error
33 | }
34 |
35 | // The Marshaler interface may be implemented by types to customize their
36 | // behavior when being marshaled into a YAML document. The returned value
37 | // is marshaled in place of the original value implementing Marshaler.
38 | //
39 | // If an error is returned by MarshalYAML, the marshaling procedure stops
40 | // and returns with the provided error.
41 | type Marshaler interface {
42 | MarshalYAML() (interface{}, error)
43 | }
44 |
45 | // Unmarshal decodes the first document found within the in byte slice
46 | // and assigns decoded values into the out value.
47 | //
48 | // Maps and pointers (to a struct, string, int, etc) are accepted as out
49 | // values. If an internal pointer within a struct is not initialized,
50 | // the yaml package will initialize it if necessary for unmarshalling
51 | // the provided data. The out parameter must not be nil.
52 | //
53 | // The type of the decoded values should be compatible with the respective
54 | // values in out. If one or more values cannot be decoded due to a type
55 | // mismatches, decoding continues partially until the end of the YAML
56 | // content, and a *yaml.TypeError is returned with details for all
57 | // missed values.
58 | //
59 | // Struct fields are only unmarshalled if they are exported (have an
60 | // upper case first letter), and are unmarshalled using the field name
61 | // lowercased as the default key. Custom keys may be defined via the
62 | // "yaml" name in the field tag: the content preceding the first comma
63 | // is used as the key, and the following comma-separated options are
64 | // used to tweak the marshalling process (see Marshal).
65 | // Conflicting names result in a runtime error.
66 | //
67 | // For example:
68 | //
69 | // type T struct {
70 | // F int `yaml:"a,omitempty"`
71 | // B int
72 | // }
73 | // var t T
74 | // yaml.Unmarshal([]byte("a: 1\nb: 2"), &t)
75 | //
76 | // See the documentation of Marshal for the format of tags and a list of
77 | // supported tag options.
78 | //
79 | func Unmarshal(in []byte, out interface{}) (err error) {
80 | defer handleErr(&err)
81 | d := newDecoder()
82 | p := newParser(in)
83 | defer p.destroy()
84 | node := p.parse()
85 | if node != nil {
86 | v := reflect.ValueOf(out)
87 | if v.Kind() == reflect.Ptr && !v.IsNil() {
88 | v = v.Elem()
89 | }
90 | d.unmarshal(node, v)
91 | }
92 | if len(d.terrors) > 0 {
93 | return &TypeError{d.terrors}
94 | }
95 | return nil
96 | }
97 |
98 | // Marshal serializes the value provided into a YAML document. The structure
99 | // of the generated document will reflect the structure of the value itself.
100 | // Maps and pointers (to struct, string, int, etc) are accepted as the in value.
101 | //
102 | // Struct fields are only unmarshalled if they are exported (have an upper case
103 | // first letter), and are unmarshalled using the field name lowercased as the
104 | // default key. Custom keys may be defined via the "yaml" name in the field
105 | // tag: the content preceding the first comma is used as the key, and the
106 | // following comma-separated options are used to tweak the marshalling process.
107 | // Conflicting names result in a runtime error.
108 | //
109 | // The field tag format accepted is:
110 | //
111 | // `(...) yaml:"[][,[,]]" (...)`
112 | //
113 | // The following flags are currently supported:
114 | //
115 | // omitempty Only include the field if it's not set to the zero
116 | // value for the type or to empty slices or maps.
117 | // Does not apply to zero valued structs.
118 | //
119 | // flow Marshal using a flow style (useful for structs,
120 | // sequences and maps).
121 | //
122 | // inline Inline the field, which must be a struct or a map,
123 | // causing all of its fields or keys to be processed as if
124 | // they were part of the outer struct. For maps, keys must
125 | // not conflict with the yaml keys of other struct fields.
126 | //
127 | // In addition, if the key is "-", the field is ignored.
128 | //
129 | // For example:
130 | //
131 | // type T struct {
132 | // F int "a,omitempty"
133 | // B int
134 | // }
135 | // yaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
136 | // yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n"
137 | //
138 | func Marshal(in interface{}) (out []byte, err error) {
139 | defer handleErr(&err)
140 | e := newEncoder()
141 | defer e.destroy()
142 | e.marshal("", reflect.ValueOf(in))
143 | e.finish()
144 | out = e.out
145 | return
146 | }
147 |
148 | func handleErr(err *error) {
149 | if v := recover(); v != nil {
150 | if e, ok := v.(yamlError); ok {
151 | *err = e.err
152 | } else {
153 | panic(v)
154 | }
155 | }
156 | }
157 |
158 | type yamlError struct {
159 | err error
160 | }
161 |
162 | func fail(err error) {
163 | panic(yamlError{err})
164 | }
165 |
166 | func failf(format string, args ...interface{}) {
167 | panic(yamlError{fmt.Errorf("yaml: "+format, args...)})
168 | }
169 |
170 | // A TypeError is returned by Unmarshal when one or more fields in
171 | // the YAML document cannot be properly decoded into the requested
172 | // types. When this error is returned, the value is still
173 | // unmarshaled partially.
174 | type TypeError struct {
175 | Errors []string
176 | }
177 |
178 | func (e *TypeError) Error() string {
179 | return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n "))
180 | }
181 |
182 | // --------------------------------------------------------------------------
183 | // Maintain a mapping of keys to structure field indexes
184 |
185 | // The code in this section was copied from mgo/bson.
186 |
187 | // structInfo holds details for the serialization of fields of
188 | // a given struct.
189 | type structInfo struct {
190 | FieldsMap map[string]fieldInfo
191 | FieldsList []fieldInfo
192 |
193 | // InlineMap is the number of the field in the struct that
194 | // contains an ,inline map, or -1 if there's none.
195 | InlineMap int
196 | }
197 |
198 | type fieldInfo struct {
199 | Key string
200 | Num int
201 | OmitEmpty bool
202 | Flow bool
203 |
204 | // Inline holds the field index if the field is part of an inlined struct.
205 | Inline []int
206 | }
207 |
208 | var structMap = make(map[reflect.Type]*structInfo)
209 | var fieldMapMutex sync.RWMutex
210 |
211 | func getStructInfo(st reflect.Type) (*structInfo, error) {
212 | fieldMapMutex.RLock()
213 | sinfo, found := structMap[st]
214 | fieldMapMutex.RUnlock()
215 | if found {
216 | return sinfo, nil
217 | }
218 |
219 | n := st.NumField()
220 | fieldsMap := make(map[string]fieldInfo)
221 | fieldsList := make([]fieldInfo, 0, n)
222 | inlineMap := -1
223 | for i := 0; i != n; i++ {
224 | field := st.Field(i)
225 | if field.PkgPath != "" {
226 | continue // Private field
227 | }
228 |
229 | info := fieldInfo{Num: i}
230 |
231 | tag := field.Tag.Get("yaml")
232 | if tag == "" && strings.Index(string(field.Tag), ":") < 0 {
233 | tag = string(field.Tag)
234 | }
235 | if tag == "-" {
236 | continue
237 | }
238 |
239 | inline := false
240 | fields := strings.Split(tag, ",")
241 | if len(fields) > 1 {
242 | for _, flag := range fields[1:] {
243 | switch flag {
244 | case "omitempty":
245 | info.OmitEmpty = true
246 | case "flow":
247 | info.Flow = true
248 | case "inline":
249 | inline = true
250 | default:
251 | return nil, errors.New(fmt.Sprintf("Unsupported flag %q in tag %q of type %s", flag, tag, st))
252 | }
253 | }
254 | tag = fields[0]
255 | }
256 |
257 | if inline {
258 | switch field.Type.Kind() {
259 | case reflect.Map:
260 | if inlineMap >= 0 {
261 | return nil, errors.New("Multiple ,inline maps in struct " + st.String())
262 | }
263 | if field.Type.Key() != reflect.TypeOf("") {
264 | return nil, errors.New("Option ,inline needs a map with string keys in struct " + st.String())
265 | }
266 | inlineMap = info.Num
267 | case reflect.Struct:
268 | sinfo, err := getStructInfo(field.Type)
269 | if err != nil {
270 | return nil, err
271 | }
272 | for _, finfo := range sinfo.FieldsList {
273 | if _, found := fieldsMap[finfo.Key]; found {
274 | msg := "Duplicated key '" + finfo.Key + "' in struct " + st.String()
275 | return nil, errors.New(msg)
276 | }
277 | if finfo.Inline == nil {
278 | finfo.Inline = []int{i, finfo.Num}
279 | } else {
280 | finfo.Inline = append([]int{i}, finfo.Inline...)
281 | }
282 | fieldsMap[finfo.Key] = finfo
283 | fieldsList = append(fieldsList, finfo)
284 | }
285 | default:
286 | //return nil, errors.New("Option ,inline needs a struct value or map field")
287 | return nil, errors.New("Option ,inline needs a struct value field")
288 | }
289 | continue
290 | }
291 |
292 | if tag != "" {
293 | info.Key = tag
294 | } else {
295 | info.Key = strings.ToLower(field.Name)
296 | }
297 |
298 | if _, found = fieldsMap[info.Key]; found {
299 | msg := "Duplicated key '" + info.Key + "' in struct " + st.String()
300 | return nil, errors.New(msg)
301 | }
302 |
303 | fieldsList = append(fieldsList, info)
304 | fieldsMap[info.Key] = info
305 | }
306 |
307 | sinfo = &structInfo{fieldsMap, fieldsList, inlineMap}
308 |
309 | fieldMapMutex.Lock()
310 | structMap[st] = sinfo
311 | fieldMapMutex.Unlock()
312 | return sinfo, nil
313 | }
314 |
315 | func isZero(v reflect.Value) bool {
316 | switch v.Kind() {
317 | case reflect.String:
318 | return len(v.String()) == 0
319 | case reflect.Interface, reflect.Ptr:
320 | return v.IsNil()
321 | case reflect.Slice:
322 | return v.Len() == 0
323 | case reflect.Map:
324 | return v.Len() == 0
325 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
326 | return v.Int() == 0
327 | case reflect.Float32, reflect.Float64:
328 | return v.Float() == 0
329 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
330 | return v.Uint() == 0
331 | case reflect.Bool:
332 | return !v.Bool()
333 | case reflect.Struct:
334 | vt := v.Type()
335 | for i := v.NumField() - 1; i >= 0; i-- {
336 | if vt.Field(i).PkgPath != "" {
337 | continue // Private field
338 | }
339 | if !isZero(v.Field(i)) {
340 | return false
341 | }
342 | }
343 | return true
344 | }
345 | return false
346 | }
347 |
--------------------------------------------------------------------------------