├── 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 | [![Build Status](https://travis-ci.org/codegangsta/cli.png?branch=master)](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 | --------------------------------------------------------------------------------