├── .gitignore ├── .gopack.yml ├── .travis.yml ├── Godeps ├── Godeps.json └── Readme ├── LICENSE ├── README.md ├── archiver.go ├── cmds ├── build.go ├── build_test.go ├── install.go └── install_test.go ├── config.go ├── main.go ├── pack.go ├── tar.go ├── targz.go ├── vendor ├── github.com │ ├── cheggaaa │ │ └── pb │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── format.go │ │ │ ├── pb.go │ │ │ ├── pb_appengine.go │ │ │ ├── pb_nix.go │ │ │ ├── pb_solaris.go │ │ │ ├── pb_win.go │ │ │ ├── pb_x.go │ │ │ ├── pool.go │ │ │ ├── pool_win.go │ │ │ ├── pool_x.go │ │ │ ├── reader.go │ │ │ ├── runecount.go │ │ │ ├── termios_bsd.go │ │ │ └── termios_nix.go │ ├── codegangsta │ │ ├── cli │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── app.go │ │ │ ├── cli.go │ │ │ ├── command.go │ │ │ ├── context.go │ │ │ ├── flag.go │ │ │ └── help.go │ │ └── inject │ │ │ ├── .gitignore │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── inject.go │ │ │ └── update_readme.sh │ ├── codeskyblue │ │ └── go-sh │ │ │ ├── LICENSE │ │ │ ├── OLD_README.md │ │ │ ├── README.md │ │ │ ├── pipe.go │ │ │ ├── sh.go │ │ │ ├── test.go │ │ │ └── wercker.yml │ ├── gobuild │ │ └── log │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ └── logext.go │ └── qiniu │ │ └── log │ │ ├── .gitignore │ │ ├── README.md │ │ └── logext.go └── gopkg.in │ └── yaml.v2 │ ├── .travis.yml │ ├── LICENSE │ ├── LICENSE.libyaml │ ├── README.md │ ├── apic.go │ ├── decode.go │ ├── emitterc.go │ ├── encode.go │ ├── parserc.go │ ├── readerc.go │ ├── resolve.go │ ├── scannerc.go │ ├── sorter.go │ ├── writerc.go │ ├── yaml.go │ ├── yamlh.go │ └── yamlprivateh.go └── zip.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | *.zip 26 | gopack 27 | -------------------------------------------------------------------------------- /.gopack.yml: -------------------------------------------------------------------------------- 1 | author: shengxiang 2 | description: '...' 3 | os: linux darwin 4 | includes: 5 | - README.md 6 | - LICENSE 7 | excludes: 8 | - \.git 9 | script: 10 | - go get -v 11 | - go build 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.5 4 | script: 5 | - go test -v ./... 6 | after_success: 7 | - bash -c "$(curl -fsSL http://bitly.com/gorelease)" gorelease 8 | -------------------------------------------------------------------------------- /Godeps/Godeps.json: -------------------------------------------------------------------------------- 1 | { 2 | "ImportPath": "github.com/gobuild/gopack", 3 | "GoVersion": "go1.6", 4 | "GodepVersion": "v74", 5 | "Deps": [ 6 | { 7 | "ImportPath": "github.com/cheggaaa/pb", 8 | "Comment": "v1.0.5-2-g6e9d177", 9 | "Rev": "6e9d17711bb763b26b68b3931d47f24c1323abab" 10 | }, 11 | { 12 | "ImportPath": "github.com/codegangsta/cli", 13 | "Comment": "1.2.0-139-g142e6cd", 14 | "Rev": "142e6cd241a4dfbf7f07a018f1f8225180018da4" 15 | }, 16 | { 17 | "ImportPath": "github.com/codegangsta/inject", 18 | "Comment": "v1.0-rc1-10-g33e0aa1", 19 | "Rev": "33e0aa1cb7c019ccc3fbe049a8262a6403d30504" 20 | }, 21 | { 22 | "ImportPath": "github.com/codeskyblue/go-sh", 23 | "Comment": "v0.1-37-g3d593d4", 24 | "Rev": "3d593d477915b4d2f2e74b2e041495345647a46b" 25 | }, 26 | { 27 | "ImportPath": "github.com/gobuild/log", 28 | "Rev": "f1f03dc733eb8acf247f889dd103ee1de1a06caa" 29 | }, 30 | { 31 | "ImportPath": "github.com/qiniu/log", 32 | "Comment": "v1.0.00-2-ge002bc2", 33 | "Rev": "e002bc2020b19bfa61ed378cc5407383dbd2f346" 34 | }, 35 | { 36 | "ImportPath": "gopkg.in/yaml.v2", 37 | "Rev": "e4d366fc3c7938e2958e662b4258c7a89e1f0e3e" 38 | } 39 | ] 40 | } 41 | -------------------------------------------------------------------------------- /Godeps/Readme: -------------------------------------------------------------------------------- 1 | This directory tree is generated automatically by godep. 2 | 3 | Please do not edit. 4 | 5 | See https://github.com/tools/godep for more information. 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 gorelease 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 all 13 | 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 THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gopack 2 | [![Build Status](https://travis-ci.org/gobuild/gopack.svg)](https://travis-ci.org/gobuild/gopack) 3 | [![gorelease](https://dn-gorelease.qbox.me/gorelease-download-blue.svg)](https://gobuild.io/gobuild/gopack) 4 | 5 | Tool for [gobuild](https://gobuild.io) 6 | 7 | ## Features 8 | 1. Create `.gopack.yml` config file 9 | 2. Build and package build into zip 10 | 3. Download and install binary from 11 | 12 | ## Install 13 | go get -v github.com/gobuild/gopack 14 | 15 | ## Usage 16 | $ gopack init 17 | # create .gopack.yml config file 18 | 19 | $ gopack pack 20 | # build go code and package README.md LICENSE ... to a zip file 21 | [golang-sh]$ bash -c go get -v 22 | [golang-sh]$ bash -c go install 23 | 2015/09/16 23:30:35 [Info] pack.go:183 zip add file: gopack 24 | 2015/09/16 23:30:35 [Info] pack.go:183 zip add file: README.md 25 | 2015/09/16 23:30:35 [Info] pack.go:183 zip add file: LICENSE 26 | 2015/09/16 23:30:35 [Info] pack.go:188 finish archive file 27 | 28 | $ unzip -t gopack.zip 29 | Archive: gopack.zip 30 | testing: gopack OK 31 | testing: README.md OK 32 | testing: LICENSE OK 33 | No errors detected in compressed data of gopack.zip. 34 | 35 | $ gopack all 36 | Building linux amd64 -> output/gopack-linux-amd64.zip ... 37 | Building linux 386 -> output/gopack-linux-386.zip ... 38 | Building linux arm -> output/gopack-linux-arm.zip ... 39 | Building darwin amd64 -> output/gopack-darwin-amd64.zip ... 40 | Building windows amd64 -> output/gopack-windows-amd64.zip ... 41 | Building windows 386 -> output/gopack-windows-386.zip ... 42 | 43 | $ gopack install gocode 44 | ==> Repository gobuild-official/gocode 45 | ==> Downloading http://dn-gobuild5.qbox.me/gorelease/gobuild-official/gocode/master/darwin-amd64/gocode.zip 46 | 2.97 MB / 3.04 MB [===============================================>-] 97.75% 0Archive: /Users/skyblue/.gopack/src/gocode.zip 47 | 3.04 MB / 3.04 MB [=================================================] 100.00% 0 48 | inflating: /Users/skyblue/.gopack/opt/gobuild-official/gocode/README.md 49 | inflating: /Users/skyblue/.gopack/opt/gobuild-official/gocode/LICENSE 50 | ==> Symlink /Users/skyblue/Documents/godir/bin/gocode 51 | ==> Program [gobuild-official/gocode] installed 52 | 53 | see more flags in `gopack -h` 54 | 55 | ## LICENSE 56 | Under [MIT](LICENSE) 57 | -------------------------------------------------------------------------------- /archiver.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | "io/ioutil" 7 | "os" 8 | "path/filepath" 9 | "runtime" 10 | "strings" 11 | ) 12 | 13 | func sanitizedName(filename string) string { 14 | if len(filename) > 1 && filename[1] == ':' && 15 | runtime.GOOS == "windows" { 16 | filename = filename[2:] 17 | } 18 | filename = filepath.ToSlash(filename) 19 | filename = filepath.Clean(filename) 20 | return strings.Replace(filename, "../", "", -1) 21 | } 22 | 23 | type Archiver interface { 24 | Add(filename string) error 25 | Close() error 26 | } 27 | 28 | func statFile(filename string) (info os.FileInfo, reader io.ReadCloser, err error) { 29 | info, err = os.Lstat(filename) 30 | if err != nil { 31 | return 32 | } 33 | // content 34 | if info.Mode()&os.ModeSymlink != 0 { 35 | var target string 36 | target, err = os.Readlink(filename) 37 | if err != nil { 38 | return 39 | } 40 | reader = ioutil.NopCloser(bytes.NewBuffer([]byte(target))) 41 | } else if !info.IsDir() { 42 | reader, err = os.Open(filename) 43 | if err != nil { 44 | return 45 | } 46 | } else { 47 | reader = ioutil.NopCloser(bytes.NewBuffer(nil)) 48 | } 49 | return 50 | } 51 | -------------------------------------------------------------------------------- /cmds/build.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | "os/exec" 8 | "strconv" 9 | "time" 10 | 11 | "github.com/codegangsta/cli" 12 | ) 13 | 14 | var BuildFlag = cli.Command{ 15 | Name: "build", 16 | Usage: "Build with version code", 17 | Flags: []cli.Flag{ 18 | cli.StringFlag{ 19 | Name: "version", 20 | Usage: "set version name", 21 | }, 22 | }, 23 | Action: BuildAction, 24 | } 25 | 26 | func BuildAction(c *cli.Context) { 27 | ver := c.String("version") 28 | if ver == "" { 29 | ver = time.Now().Format("2006-01-02_15:04:05") 30 | } 31 | cmd := exec.Command("go", "build", "-ldflags", 32 | fmt.Sprintf("-X main.VERSION=%s", strconv.Quote(ver))) 33 | cmd.Stdout = os.Stdout 34 | cmd.Stderr = os.Stderr 35 | if err := cmd.Run(); err != nil { 36 | log.Fatal(err) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /cmds/build_test.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | -------------------------------------------------------------------------------- /cmds/install.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io" 7 | "net/http" 8 | "os" 9 | "os/exec" 10 | "path/filepath" 11 | "runtime" 12 | "strconv" 13 | "strings" 14 | 15 | "github.com/cheggaaa/pb" 16 | "github.com/codegangsta/cli" 17 | "github.com/qiniu/log" 18 | ) 19 | 20 | var InstallFlag = cli.Command{ 21 | Name: "install", 22 | Aliases: []string{"i"}, 23 | Usage: fmt.Sprintf("Install binary from https://gobuild.io"), 24 | Flags: []cli.Flag{ 25 | cli.BoolFlag{ 26 | Name: "debug", 27 | Usage: "Enable debug log", 28 | }, 29 | }, 30 | Action: InstallAction, 31 | } 32 | 33 | var GOBIN string 34 | 35 | // Determine binary path 36 | func init() { 37 | var paths []string 38 | gobin := os.Getenv("GOBIN") 39 | if gobin != "" { 40 | paths = filepath.SplitList(gobin) 41 | } 42 | if len(paths) > 0 { 43 | GOBIN = paths[0] 44 | return 45 | } 46 | paths = filepath.SplitList(os.Getenv("GOPATH")) 47 | if len(paths) > 0 { 48 | GOBIN = filepath.Join(paths[0], "bin") 49 | return 50 | } 51 | log.Fatal("Make sure you set env GOPATH or GOBIN") 52 | 53 | os.ExpandEnv("$HOME/.gopack/src") 54 | } 55 | 56 | func getInsPath(names ...string) string { 57 | base := os.ExpandEnv("$HOME/.gopack/") 58 | names = append([]string{base}, names...) 59 | target := filepath.Join(names...) 60 | os.MkdirAll(filepath.Dir(target), 0755) 61 | return target 62 | } 63 | 64 | // http://dn-gobuild5.qbox.me/gorelease/gorelease/gorelease/master/darwin-amd64/gorelease.zip 65 | // Need to update 66 | func downloadSource(name string) (dest string, err error) { 67 | parts := strings.Split(name, "/") 68 | if len(parts) != 2 { 69 | return "", fmt.Errorf("name: %s can only contains on /", name) 70 | } 71 | 72 | owner, repo := parts[0], parts[1] 73 | osarch := runtime.GOOS + "-" + runtime.GOARCH 74 | url := fmt.Sprintf("http://dn-gobuild5.qbox.me/gorelease/%s/%s/master/%s/%s.zip", 75 | owner, repo, osarch, repo) 76 | 77 | prompt("Downloading %v", url) 78 | log.Debug("download:", url) 79 | dest = getInsPath("src", fmt.Sprintf("%s.zip", repo)) 80 | 81 | resp, err := http.Get(url) 82 | if err != nil { 83 | return 84 | } 85 | defer resp.Body.Close() 86 | if resp.StatusCode != http.StatusOK { 87 | err = errors.New("Http status not 200") 88 | return 89 | } 90 | 91 | lengthStr := resp.Header.Get("Content-Length") 92 | if lengthStr == "" { 93 | err = errors.New("Content length is empty") 94 | return 95 | } 96 | length, _ := strconv.Atoi(lengthStr) 97 | bar := pb.New(length).SetUnits(pb.U_BYTES) 98 | 99 | outFd, err := os.Create(dest) 100 | if err != nil { 101 | return 102 | } 103 | defer outFd.Close() 104 | 105 | bar.Start() 106 | reader := bar.NewProxyReader(resp.Body) 107 | _, err = io.Copy(outFd, reader) 108 | return 109 | } 110 | 111 | func deployPackage(pkgName, path string, binDir string) error { 112 | cmd := exec.Command("unzip", "-o", "-d", getInsPath("opt", pkgName), path) 113 | log.Debug("zip command:", cmd.Args) 114 | cmd.Stdout = os.Stdout 115 | cmd.Stderr = os.Stderr 116 | if err := cmd.Run(); err != nil { 117 | return err 118 | } 119 | baseName := filepath.Base(pkgName) 120 | symlink := filepath.Join(GOBIN, baseName) 121 | 122 | prompt("Symlink %v", symlink) 123 | // for linux and darwin 124 | os.Remove(symlink) 125 | 126 | // TODO: need to resolve multi binaries 127 | return os.Symlink(getInsPath("opt", pkgName, filepath.Base(pkgName)), symlink) 128 | } 129 | 130 | func prompt(format string, args ...interface{}) { 131 | format = "==> " + strings.TrimPrefix(format, "\n") + "\n" 132 | fmt.Printf(format, args...) 133 | } 134 | 135 | func InstallAction(c *cli.Context) { 136 | if c.Bool("debug") { 137 | log.SetOutputLevel(log.Ldebug) 138 | } 139 | if len(c.Args()) < 1 { 140 | log.Fatal("Need at lease one argument") 141 | } 142 | // log.Println(GOBIN) 143 | pkgName := c.Args().First() 144 | // TODO: use myname for now 145 | if len(strings.Split(pkgName, "/")) == 1 { 146 | pkgName = "gobuild-official/" + pkgName 147 | } 148 | 149 | prompt("Repository %v", pkgName) 150 | dest, err := downloadSource(pkgName) 151 | if err != nil { 152 | log.Fatal(err) 153 | } 154 | 155 | err = deployPackage(pkgName, dest, GOBIN) 156 | if err != nil { 157 | log.Fatal(err) 158 | } 159 | 160 | prompt("Program [%s] installed", pkgName) 161 | } 162 | -------------------------------------------------------------------------------- /cmds/install_test.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import "testing" 4 | 5 | func InstallActionTest(t *testing.T) { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /config.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "io/ioutil" 5 | 6 | "github.com/codeskyblue/go-sh" 7 | "github.com/gobuild/log" 8 | goyaml "gopkg.in/yaml.v2" 9 | ) 10 | 11 | type PackageConfig struct { 12 | Author string `yaml:"author"` 13 | Description string `yaml:"description"` 14 | OS string `yaml:"os"` 15 | Includes []string `yaml:"includes"` 16 | Excludes []string `yaml:"excludes"` 17 | Depth int `yaml:"-"` 18 | Script []string `yaml:"script"` 19 | Settings struct { 20 | TargetDir string `yaml:"targetdir"` // target dir 21 | Outfiles []string `yaml:"outfiles"` 22 | } `yaml:"-"` 23 | } 24 | 25 | const RCFILE = ".gopack.yml" 26 | 27 | var DEFAULT_SCRIPT = []string{"go get -v", "go build"} 28 | var DefaultPcfg *PackageConfig = &PackageConfig{ 29 | OS: "darwin linux windows", 30 | Includes: []string{"README.md", "LICENSE", "conf", "templates", "public", "static", "views"}, 31 | Excludes: []string{"\\.git"}, 32 | Depth: 20, 33 | Script: DEFAULT_SCRIPT, 34 | } 35 | 36 | func init() { 37 | if _, err := ReadPkgConfig(RCFILE); err != nil { 38 | log.Warnf("Read %s err: %v", RCFILE, err) 39 | } 40 | } 41 | 42 | // parse yaml 43 | func ReadPkgConfig(filepath string) (pcfg *PackageConfig, err error) { 44 | pcfg = DefaultPcfg 45 | if sh.Test("file", filepath) { 46 | data, er := ioutil.ReadFile(filepath) 47 | if er != nil { 48 | err = er 49 | return 50 | } 51 | if err = goyaml.Unmarshal(data, &pcfg); err != nil { 52 | return 53 | } 54 | } 55 | return pcfg, nil 56 | } 57 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "fmt" 7 | "io/ioutil" 8 | "log" 9 | "os" 10 | "os/exec" 11 | "path/filepath" 12 | "runtime" 13 | "strings" 14 | "text/template" 15 | "time" 16 | 17 | "github.com/codegangsta/cli" 18 | "github.com/gobuild/gopack/cmds" 19 | goyaml "gopkg.in/yaml.v2" 20 | ) 21 | 22 | var VERSION = "0.2.0915" 23 | 24 | var app = cli.NewApp() 25 | 26 | func inputString(key string, defa string) string { 27 | fmt.Printf("[?] %s: (%s) ", key, defa) 28 | var val string 29 | if _, err := fmt.Scanf("%s", &val); err != nil || val == "" { 30 | return defa 31 | } 32 | return val 33 | } 34 | 35 | func gitUsername() string { 36 | output, _ := exec.Command("git", "config", "user.name").Output() 37 | username := string(output) 38 | if username == "" { 39 | return "unknown" 40 | } 41 | return strings.TrimSpace(username) 42 | } 43 | 44 | func actionInit(ctx *cli.Context) { 45 | if _, err := os.Stat(RCFILE); err == nil && !ctx.Bool("force") { 46 | fmt.Printf("config file %s already exists\n", RCFILE) 47 | return 48 | } 49 | 50 | pcfg := DefaultPcfg 51 | pcfg.Author = inputString("author", gitUsername()) 52 | pcfg.Description = inputString("description", "...") 53 | 54 | data, _ := goyaml.Marshal(DefaultPcfg) 55 | beautiData := strings.Replace(string(data), "\n-", "\n -", -1) 56 | ioutil.WriteFile(RCFILE, []byte(beautiData), 0644) 57 | fmt.Println("Configuration file save to .gopack.yml") 58 | } 59 | 60 | type OSArch struct { 61 | OS string `json:"os"` 62 | Arch string `json:"arch"` 63 | } 64 | 65 | func actionAll(ctx *cli.Context) { 66 | ss := map[string][]string{ 67 | "darwin": {"amd64"}, 68 | "windows": {"amd64", "386"}, 69 | "linux": {"amd64", "386", "arm"}, 70 | } 71 | 72 | oses := strings.Fields(ctx.String("os")) 73 | if len(oses) == 0 { 74 | oses = []string{"linux", "darwin", "windows"} 75 | } 76 | pathTemplate := ctx.String("output") 77 | osarches := make([]OSArch, 0) 78 | for _, os := range oses { 79 | for _, arch := range ss[os] { 80 | osarches = append(osarches, OSArch{os, arch}) 81 | } 82 | } 83 | 84 | for _, oa := range osarches { 85 | tmpl := template.Must(template.New("path").Parse(pathTemplate)) 86 | cwd, _ := os.Getwd() 87 | wr := bytes.NewBuffer(nil) 88 | tmpl.Execute(wr, map[string]string{ 89 | "OS": oa.OS, 90 | "Arch": oa.Arch, 91 | "Dir": filepath.Base(cwd), 92 | }) 93 | fmt.Printf("Building %s %s -> %s ...\n", oa.OS, oa.Arch, wr.String()) 94 | //params := []string{"pack", "--rm", "--os", os.OS, "--arch", oa.Arch} 95 | cmd := exec.Command(os.Args[0], "pack", 96 | "-q", "--rm", "--os", oa.OS, "--arch", oa.Arch, "-o", wr.String()) 97 | cmd.Stdout = os.Stdout 98 | cmd.Stderr = os.Stderr 99 | if err := cmd.Run(); err != nil { 100 | log.Fatal(err) 101 | } 102 | } 103 | outJson := ctx.String("json") 104 | if outJson == "" { 105 | return 106 | } 107 | comment, err := exec.Command("git", "log", "-1", "--oneline").Output() 108 | var commentStr string 109 | if err != nil { 110 | commentStr = os.Getenv("TRAVIS_COMMIT") 111 | } else { 112 | commentStr = string(comment) 113 | } 114 | vv := map[string]interface{}{ 115 | "go_version": runtime.Version(), 116 | "update_time": time.Now().Unix(), 117 | "format": "zip", 118 | "comment": commentStr, 119 | "builds": osarches, 120 | } 121 | outfd, err := os.Create(outJson) 122 | if err != nil { 123 | log.Fatal(err) 124 | } 125 | defer outfd.Close() 126 | json.NewEncoder(outfd).Encode(vv) 127 | } 128 | 129 | func init() { 130 | cwd, _ := os.Getwd() 131 | program := filepath.Base(cwd) 132 | 133 | app.Name = "gopack" 134 | app.Usage = "Build and pack file into tgz or zip" 135 | 136 | app.Commands = []cli.Command{ 137 | { 138 | Name: "init", 139 | Usage: fmt.Sprintf("Generate %v file", RCFILE), 140 | Flags: []cli.Flag{ 141 | cli.BoolFlag{ 142 | Name: "force, f", 143 | Usage: "Might rewrite config file", 144 | }, 145 | }, 146 | Action: actionInit, 147 | }, 148 | { 149 | Name: "all", 150 | Usage: fmt.Sprintf("Package all platform packages"), 151 | Flags: []cli.Flag{ 152 | cli.StringFlag{ 153 | Name: "os", 154 | Usage: "Space-separated list of operating systems to build for", 155 | Value: DefaultPcfg.OS, 156 | }, 157 | cli.StringFlag{ 158 | Name: "output, o", 159 | Usage: "Output path template", 160 | Value: "output/{{.Dir}}-{{.OS}}-{{.Arch}}.zip", 161 | }, 162 | cli.StringFlag{ 163 | Name: "json", 164 | Usage: "Output json builds", 165 | Value: "", 166 | }, 167 | }, 168 | Action: actionAll, 169 | }, 170 | { 171 | Name: "pack", 172 | Usage: "Package file to zip or other format", 173 | Flags: []cli.Flag{ 174 | cli.StringFlag{Name: "os", EnvVar: "GOOS", Value: runtime.GOOS, Usage: "operation system"}, 175 | cli.StringFlag{Name: "arch", EnvVar: "GOARCH", Value: runtime.GOARCH, Usage: "arch eg amd64|386|arm"}, 176 | cli.StringFlag{Name: "output,o", Value: program + ".zip", Usage: "target file"}, 177 | cli.StringFlag{Name: "gom", Value: "go", Usage: "go package manage program"}, 178 | cli.BoolFlag{Name: "nobuild", Usage: "donot call go build when pack"}, 179 | cli.BoolFlag{Name: "rm", Usage: "remove build files when done"}, 180 | cli.BoolFlag{Name: "init", Usage: "generate sample .gobuild.yml"}, 181 | cli.BoolFlag{Name: "quiet, q", Usage: "quiet console info"}, 182 | cli.StringSliceFlag{Name: "add,a", Value: &cli.StringSlice{}, Usage: "add file"}, 183 | //cli.StringFlag{Name: "depth", Value: "3", Usage: "depth of file to walk"}, 184 | }, 185 | Action: actionPack, 186 | }, 187 | cmds.InstallFlag, 188 | cmds.BuildFlag, 189 | } 190 | app.Version = VERSION 191 | app.Flags = []cli.Flag{ 192 | cli.BoolFlag{ 193 | Name: "debug, d", 194 | Usage: "show debug information", 195 | }, 196 | } 197 | } 198 | 199 | func main() { 200 | //app.Run(os.Args) 201 | app.RunAndExitOnError() 202 | } 203 | -------------------------------------------------------------------------------- /pack.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | "regexp" 7 | "runtime" 8 | "strings" 9 | 10 | "github.com/codegangsta/cli" 11 | sh "github.com/codeskyblue/go-sh" 12 | "github.com/gobuild/log" 13 | ) 14 | 15 | func shExecString(sess *sh.Session, command string) error { 16 | if runtime.GOOS == "windows" { 17 | return sess.Command("cmd", "/c", command).Run() 18 | } 19 | return sess.Command("bash", "-c", command).Run() 20 | } 21 | 22 | func findFiles(path string, depth int, skips []*regexp.Regexp) ([]string, error) { 23 | baseNumSeps := strings.Count(path, string(os.PathSeparator)) 24 | var files []string 25 | err := filepath.Walk(path, func(path string, info os.FileInfo, err error) error { 26 | if err != nil { 27 | log.Debugf("filewalk: %s", err) 28 | return nil 29 | } 30 | if info.IsDir() { 31 | pathDepth := strings.Count(path, string(os.PathSeparator)) - baseNumSeps 32 | //log.Println("Skip", info, pathDepth, depth) 33 | if pathDepth > depth { 34 | return filepath.SkipDir 35 | } 36 | } 37 | name := info.Name() 38 | isSkip := false 39 | for _, skip := range skips { 40 | if skip.MatchString(name) || skip.MatchString(path) { 41 | isSkip = true 42 | break 43 | } 44 | } 45 | if isSkip { 46 | log.Debug("skip:", path) 47 | } 48 | if !isSkip { 49 | files = append(files, path) 50 | } 51 | if isSkip && info.IsDir() { 52 | return filepath.SkipDir 53 | } 54 | return nil 55 | }) 56 | return files, err 57 | } 58 | 59 | func actionPack(c *cli.Context) { 60 | var goos, goarch = c.String("os"), c.String("arch") 61 | //var depth = c.Int("depth") 62 | var output = c.String("output") 63 | var gom = c.String("gom") 64 | var nobuild = c.Bool("nobuild") 65 | var adds = c.StringSlice("add") 66 | var rmflag = c.Bool("rm") 67 | 68 | if c.GlobalBool("debug") { 69 | log.SetOutputLevel(log.Ldebug) 70 | } 71 | if c.Bool("quiet") { 72 | log.SetOutputLevel(log.Lwarn) 73 | } 74 | 75 | log.Debugf("os: %s, arch: %s", goos, goarch) 76 | 77 | var err error 78 | defer func() { 79 | if err != nil { 80 | log.Fatal(err) 81 | } 82 | }() 83 | sess := sh.NewSession() 84 | sess.SetEnv("GOOS", goos) 85 | sess.SetEnv("GOARCH", goarch) 86 | sess.ShowCMD = !c.Bool("quiet") 87 | 88 | gomarr := strings.Fields(gom) 89 | if len(gomarr) >= 1 { 90 | sess.Alias("go", gomarr[0], gomarr[1:]...) 91 | } 92 | 93 | // parse yaml 94 | pcfg := DefaultPcfg 95 | log.Debug("config:", pcfg) 96 | 97 | var skips []*regexp.Regexp 98 | for _, str := range pcfg.Excludes { 99 | skips = append(skips, regexp.MustCompile("^"+str+"$")) 100 | } 101 | var needs []*regexp.Regexp 102 | for _, str := range pcfg.Includes { 103 | needs = append(needs, regexp.MustCompile("^"+str+"$")) 104 | } 105 | 106 | os.MkdirAll(filepath.Dir(output), 0755) 107 | 108 | var z Archiver 109 | hasExt := func(ext string) bool { return strings.HasSuffix(output, ext) } 110 | switch { 111 | case hasExt(".zip"): 112 | log.Println("zip format") 113 | z, err = CreateZip(output) 114 | case hasExt(".tar"): 115 | log.Println("tar format") 116 | z, err = CreateTar(output) 117 | case hasExt(".tgz"): 118 | fallthrough 119 | case hasExt(".tar.gz"): 120 | log.Println("tar.gz format") 121 | z, err = CreateTgz(output) 122 | default: 123 | log.Println("unsupport file archive format") 124 | os.Exit(1) 125 | } 126 | if err != nil { 127 | return 128 | } 129 | 130 | var files = []string{} 131 | var buildFiles = pcfg.Settings.Outfiles 132 | // build source 133 | if !nobuild { 134 | targetDir := sanitizedName(pcfg.Settings.TargetDir) 135 | if !sh.Test("dir", targetDir) { 136 | os.MkdirAll(targetDir, 0755) 137 | } 138 | 139 | //gobin := filepath.Join(pwd, sanitizedName(pcfg.Settings.TargetDir)) 140 | //sess.SetEnv("GOBIN", gobin) 141 | //log.Debugf("set env GOBIN=%s", gobin) 142 | /* 143 | symdir := filepath.Join(targetDir, goos+"_"+goarch) 144 | if err = os.Symlink(gobin, symdir); err != nil { 145 | log.Fatalf("os symlink error: %s", err) 146 | } 147 | */ 148 | //defer os.Remove(symdir) 149 | // opts := []string{"install", "-v"} 150 | // opts = append(opts, strings.Fields(pcfg.Settings.Addopts)...) // TODO: here need to use shell args parse lib 151 | //if pcfg.Settings.Build == "" { 152 | //pcfg.Settings.Build = DEFAULT_BUILD 153 | //} 154 | 155 | for _, command := range pcfg.Script { 156 | if err = shExecString(sess, command); err != nil { 157 | return 158 | } 159 | } 160 | //os.Remove(symdir) // I have to do it twice 161 | 162 | if len(buildFiles) == 0 { 163 | cwd, _ := os.Getwd() 164 | program := filepath.Base(cwd) 165 | buildFiles = append(buildFiles, program) 166 | } 167 | 168 | for _, filename := range buildFiles { 169 | if goos == "windows" { 170 | filename += ".exe" 171 | } 172 | files = append(files, filename) 173 | } 174 | } 175 | 176 | log.Debug("archive files") 177 | depth := pcfg.Depth 178 | for _, filename := range pcfg.Includes { 179 | fs, err := findFiles(filename, depth, skips) 180 | if err != nil { 181 | return 182 | } 183 | files = append(files, fs...) 184 | } 185 | 186 | // adds - parse by cli 187 | files = append(files, adds...) 188 | uniqset := make(map[string]bool, len(files)) 189 | for _, file := range files { 190 | file = sanitizedName(file) 191 | if uniqset[file] { 192 | continue 193 | } 194 | uniqset[file] = true 195 | log.Infof("zip add file: %v", file) 196 | if err = z.Add(file); err != nil { 197 | return 198 | } 199 | } 200 | log.Info("finish archive file") 201 | err = z.Close() 202 | 203 | if rmflag { 204 | for _, filename := range buildFiles { 205 | if goos == "windows" { 206 | filename += ".exe" 207 | } 208 | os.Remove(filename) 209 | } 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /tar.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "archive/tar" 5 | "fmt" 6 | "io" 7 | "os" 8 | ) 9 | 10 | type Tar struct { 11 | *tar.Writer 12 | } 13 | 14 | func CreateTar(filename string) (*Tar, error) { 15 | file, err := os.Create(filename) 16 | if err != nil { 17 | return nil, err 18 | } 19 | return NewTarWriter(file), nil 20 | } 21 | 22 | func NewTarWriter(wr io.WriteCloser) *Tar { 23 | writer := tar.NewWriter(wr) 24 | return &Tar{Writer: writer} 25 | } 26 | 27 | func (t *Tar) Add(filename string) error { 28 | info, rdc, err := statFile(filename) 29 | if err != nil { 30 | return err 31 | } 32 | defer rdc.Close() 33 | 34 | link := "" 35 | if info.Mode()&os.ModeSymlink != 0 { 36 | link, _ = os.Readlink(filename) 37 | } 38 | // header 39 | hdr, err := tar.FileInfoHeader(info, link) 40 | if err != nil { 41 | return err 42 | } 43 | hdr.Name = sanitizedName(filename) 44 | if info.IsDir() { 45 | hdr.Name += "/" 46 | } 47 | if err = t.WriteHeader(hdr); err != nil { 48 | return fmt.Errorf("header: %v", err) 49 | } 50 | if info.Mode().IsRegular() { 51 | _, err = io.Copy(t, rdc) 52 | } 53 | return err 54 | } 55 | -------------------------------------------------------------------------------- /targz.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "compress/gzip" 5 | "io" 6 | "os" 7 | ) 8 | 9 | type Tgz struct { 10 | *Tar 11 | writer io.WriteCloser 12 | } 13 | 14 | func CreateTgz(filename string) (*Tgz, error) { 15 | file, err := os.Create(filename) 16 | if err != nil { 17 | return nil, err 18 | } 19 | writer := gzip.NewWriter(file) 20 | return &Tgz{Tar: NewTarWriter(writer), writer: writer}, nil 21 | } 22 | 23 | func (t *Tgz) Close() error { 24 | t.Tar.Close() 25 | return t.writer.Close() 26 | } 27 | -------------------------------------------------------------------------------- /vendor/github.com/cheggaaa/pb/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.4.2 4 | sudo: false 5 | os: 6 | - linux 7 | - osx 8 | -------------------------------------------------------------------------------- /vendor/github.com/cheggaaa/pb/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2015, Sergey Cherepanov 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | * Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /vendor/github.com/cheggaaa/pb/README.md: -------------------------------------------------------------------------------- 1 | # Terminal progress bar for Go 2 | 3 | Simple progress bar for console programs. 4 | 5 | 6 | ## Installation 7 | 8 | ``` 9 | go get gopkg.in/cheggaaa/pb.v1 10 | ``` 11 | 12 | ## Usage 13 | 14 | ```Go 15 | package main 16 | 17 | import ( 18 | "gopkg.in/cheggaaa/pb.v1" 19 | "time" 20 | ) 21 | 22 | func main() { 23 | count := 100000 24 | bar := pb.StartNew(count) 25 | for i := 0; i < count; i++ { 26 | bar.Increment() 27 | time.Sleep(time.Millisecond) 28 | } 29 | bar.FinishPrint("The End!") 30 | } 31 | 32 | ``` 33 | 34 | Result will be like this: 35 | 36 | ``` 37 | > go run test.go 38 | 37158 / 100000 [================>_______________________________] 37.16% 1m11s 39 | ``` 40 | 41 | ## Customization 42 | 43 | ```Go 44 | // create bar 45 | bar := pb.New(count) 46 | 47 | // refresh info every second (default 200ms) 48 | bar.SetRefreshRate(time.Second) 49 | 50 | // show percents (by default already true) 51 | bar.ShowPercent = true 52 | 53 | // show bar (by default already true) 54 | bar.ShowBar = true 55 | 56 | // no counters 57 | bar.ShowCounters = false 58 | 59 | // show "time left" 60 | bar.ShowTimeLeft = true 61 | 62 | // show average speed 63 | bar.ShowSpeed = true 64 | 65 | // sets the width of the progress bar 66 | bar.SetWidth(80) 67 | 68 | // sets the width of the progress bar, but if terminal size smaller will be ignored 69 | bar.SetMaxWidth(80) 70 | 71 | // convert output to readable format (like KB, MB) 72 | bar.SetUnits(pb.U_BYTES) 73 | 74 | // and start 75 | bar.Start() 76 | ``` 77 | 78 | ## Progress bar for IO Operations 79 | 80 | ```go 81 | // create and start bar 82 | bar := pb.New(myDataLen).SetUnits(pb.U_BYTES) 83 | bar.Start() 84 | 85 | // my io.Reader 86 | r := myReader 87 | 88 | // my io.Writer 89 | w := myWriter 90 | 91 | // create proxy reader 92 | reader := bar.NewProxyReader(r) 93 | 94 | // and copy from pb reader 95 | io.Copy(w, reader) 96 | 97 | ``` 98 | 99 | ```go 100 | // create and start bar 101 | bar := pb.New(myDataLen).SetUnits(pb.U_BYTES) 102 | bar.Start() 103 | 104 | // my io.Reader 105 | r := myReader 106 | 107 | // my io.Writer 108 | w := myWriter 109 | 110 | // create multi writer 111 | writer := io.MultiWriter(w, bar) 112 | 113 | // and copy 114 | io.Copy(writer, r) 115 | 116 | bar.Finish() 117 | ``` 118 | 119 | ## Custom Progress Bar Look-and-feel 120 | 121 | ```go 122 | bar.Format("<.- >") 123 | ``` 124 | 125 | ## Multiple Progress Bars (experimental and unstable) 126 | 127 | Do not print to terminal while pool is active. 128 | 129 | ```go 130 | package main 131 | 132 | import ( 133 | "math/rand" 134 | "sync" 135 | "time" 136 | 137 | "gopkg.in/cheggaaa/pb.v1" 138 | ) 139 | 140 | func main() { 141 | // create bars 142 | first := pb.New(200).Prefix("First ") 143 | second := pb.New(200).Prefix("Second ") 144 | third := pb.New(200).Prefix("Third ") 145 | // start pool 146 | pool, err := pb.StartPool(first, second, third) 147 | if err != nil { 148 | panic(err) 149 | } 150 | // update bars 151 | wg := new(sync.WaitGroup) 152 | for _, bar := range []*pb.ProgressBar{first, second, third} { 153 | wg.Add(1) 154 | go func(cb *pb.ProgressBar) { 155 | for n := 0; n < 200; n++ { 156 | cb.Increment() 157 | time.Sleep(time.Millisecond * time.Duration(rand.Intn(100))) 158 | } 159 | cb.Finish() 160 | wg.Done() 161 | }(bar) 162 | } 163 | wg.Wait() 164 | // close pool 165 | pool.Stop() 166 | } 167 | ``` 168 | 169 | The result will be as follows: 170 | 171 | ``` 172 | $ go run example/multiple.go 173 | First 141 / 1000 [===============>---------------------------------------] 14.10 % 44s 174 | Second 139 / 1000 [==============>---------------------------------------] 13.90 % 44s 175 | Third 152 / 1000 [================>--------------------------------------] 15.20 % 40s 176 | ``` 177 | -------------------------------------------------------------------------------- /vendor/github.com/cheggaaa/pb/format.go: -------------------------------------------------------------------------------- 1 | package pb 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | "time" 7 | ) 8 | 9 | type Units int 10 | 11 | const ( 12 | // U_NO are default units, they represent a simple value and are not formatted at all. 13 | U_NO Units = iota 14 | // U_BYTES units are formatted in a human readable way (b, Bb, Mb, ...) 15 | U_BYTES 16 | // U_DURATION units are formatted in a human readable way (3h14m15s) 17 | U_DURATION 18 | ) 19 | 20 | func Format(i int64) *formatter { 21 | return &formatter{n: i} 22 | } 23 | 24 | type formatter struct { 25 | n int64 26 | unit Units 27 | width int 28 | perSec bool 29 | } 30 | 31 | func (f *formatter) Value(n int64) *formatter { 32 | f.n = n 33 | return f 34 | } 35 | 36 | func (f *formatter) To(unit Units) *formatter { 37 | f.unit = unit 38 | return f 39 | } 40 | 41 | func (f *formatter) Width(width int) *formatter { 42 | f.width = width 43 | return f 44 | } 45 | 46 | func (f *formatter) PerSec() *formatter { 47 | f.perSec = true 48 | return f 49 | } 50 | 51 | func (f *formatter) String() (out string) { 52 | switch f.unit { 53 | case U_BYTES: 54 | out = formatBytes(f.n) 55 | case U_DURATION: 56 | d := time.Duration(f.n) 57 | if d > time.Hour*24 { 58 | out = fmt.Sprintf("%dd", d/24/time.Hour) 59 | d -= (d / time.Hour / 24) * (time.Hour * 24) 60 | } 61 | out = fmt.Sprintf("%s%v", out, d) 62 | default: 63 | out = fmt.Sprintf(fmt.Sprintf("%%%dd", f.width), f.n) 64 | } 65 | if f.perSec { 66 | out += "/s" 67 | } 68 | return 69 | } 70 | 71 | // Convert bytes to human readable string. Like a 2 MB, 64.2 KB, 52 B 72 | func formatBytes(i int64) (result string) { 73 | switch { 74 | case i > (1024 * 1024 * 1024 * 1024): 75 | result = fmt.Sprintf("%.02f TB", float64(i)/1024/1024/1024/1024) 76 | case i > (1024 * 1024 * 1024): 77 | result = fmt.Sprintf("%.02f GB", float64(i)/1024/1024/1024) 78 | case i > (1024 * 1024): 79 | result = fmt.Sprintf("%.02f MB", float64(i)/1024/1024) 80 | case i > 1024: 81 | result = fmt.Sprintf("%.02f KB", float64(i)/1024) 82 | default: 83 | result = fmt.Sprintf("%d B", i) 84 | } 85 | result = strings.Trim(result, " ") 86 | return 87 | } 88 | -------------------------------------------------------------------------------- /vendor/github.com/cheggaaa/pb/pb.go: -------------------------------------------------------------------------------- 1 | // Simple console progress bars 2 | package pb 3 | 4 | import ( 5 | "fmt" 6 | "io" 7 | "math" 8 | "strings" 9 | "sync" 10 | "sync/atomic" 11 | "time" 12 | "unicode/utf8" 13 | ) 14 | 15 | // Current version 16 | const Version = "1.0.5" 17 | 18 | const ( 19 | // Default refresh rate - 200ms 20 | DEFAULT_REFRESH_RATE = time.Millisecond * 200 21 | FORMAT = "[=>-]" 22 | ) 23 | 24 | // DEPRECATED 25 | // variables for backward compatibility, from now do not work 26 | // use pb.Format and pb.SetRefreshRate 27 | var ( 28 | DefaultRefreshRate = DEFAULT_REFRESH_RATE 29 | BarStart, BarEnd, Empty, Current, CurrentN string 30 | ) 31 | 32 | // Create new progress bar object 33 | func New(total int) *ProgressBar { 34 | return New64(int64(total)) 35 | } 36 | 37 | // Create new progress bar object using int64 as total 38 | func New64(total int64) *ProgressBar { 39 | pb := &ProgressBar{ 40 | Total: total, 41 | RefreshRate: DEFAULT_REFRESH_RATE, 42 | ShowPercent: true, 43 | ShowCounters: true, 44 | ShowBar: true, 45 | ShowTimeLeft: true, 46 | ShowFinalTime: true, 47 | Units: U_NO, 48 | ManualUpdate: false, 49 | finish: make(chan struct{}), 50 | currentValue: -1, 51 | mu: new(sync.Mutex), 52 | } 53 | return pb.Format(FORMAT) 54 | } 55 | 56 | // Create new object and start 57 | func StartNew(total int) *ProgressBar { 58 | return New(total).Start() 59 | } 60 | 61 | // Callback for custom output 62 | // For example: 63 | // bar.Callback = func(s string) { 64 | // mySuperPrint(s) 65 | // } 66 | // 67 | type Callback func(out string) 68 | 69 | type ProgressBar struct { 70 | current int64 // current must be first member of struct (https://code.google.com/p/go/issues/detail?id=5278) 71 | 72 | Total int64 73 | RefreshRate time.Duration 74 | ShowPercent, ShowCounters bool 75 | ShowSpeed, ShowTimeLeft, ShowBar bool 76 | ShowFinalTime bool 77 | Output io.Writer 78 | Callback Callback 79 | NotPrint bool 80 | Units Units 81 | Width int 82 | ForceWidth bool 83 | ManualUpdate bool 84 | AutoStat bool 85 | 86 | // Default width for the time box. 87 | UnitsWidth int 88 | TimeBoxWidth int 89 | 90 | finishOnce sync.Once //Guards isFinish 91 | finish chan struct{} 92 | isFinish bool 93 | 94 | startTime time.Time 95 | startValue int64 96 | currentValue int64 97 | 98 | prefix, postfix string 99 | 100 | mu *sync.Mutex 101 | lastPrint string 102 | 103 | BarStart string 104 | BarEnd string 105 | Empty string 106 | Current string 107 | CurrentN string 108 | 109 | AlwaysUpdate bool 110 | } 111 | 112 | // Start print 113 | func (pb *ProgressBar) Start() *ProgressBar { 114 | pb.startTime = time.Now() 115 | pb.startValue = pb.current 116 | if pb.Total == 0 { 117 | pb.ShowTimeLeft = false 118 | pb.ShowPercent = false 119 | pb.AutoStat = false 120 | } 121 | if !pb.ManualUpdate { 122 | pb.Update() // Initial printing of the bar before running the bar refresher. 123 | go pb.refresher() 124 | } 125 | return pb 126 | } 127 | 128 | // Increment current value 129 | func (pb *ProgressBar) Increment() int { 130 | return pb.Add(1) 131 | } 132 | 133 | // Get current value 134 | func (pb *ProgressBar) Get() int64 { 135 | c := atomic.LoadInt64(&pb.current) 136 | return c 137 | } 138 | 139 | // Set current value 140 | func (pb *ProgressBar) Set(current int) *ProgressBar { 141 | return pb.Set64(int64(current)) 142 | } 143 | 144 | // Set64 sets the current value as int64 145 | func (pb *ProgressBar) Set64(current int64) *ProgressBar { 146 | atomic.StoreInt64(&pb.current, current) 147 | return pb 148 | } 149 | 150 | // Add to current value 151 | func (pb *ProgressBar) Add(add int) int { 152 | return int(pb.Add64(int64(add))) 153 | } 154 | 155 | func (pb *ProgressBar) Add64(add int64) int64 { 156 | return atomic.AddInt64(&pb.current, add) 157 | } 158 | 159 | // Set prefix string 160 | func (pb *ProgressBar) Prefix(prefix string) *ProgressBar { 161 | pb.prefix = prefix 162 | return pb 163 | } 164 | 165 | // Set postfix string 166 | func (pb *ProgressBar) Postfix(postfix string) *ProgressBar { 167 | pb.postfix = postfix 168 | return pb 169 | } 170 | 171 | // Set custom format for bar 172 | // Example: bar.Format("[=>_]") 173 | // Example: bar.Format("[\x00=\x00>\x00-\x00]") // \x00 is the delimiter 174 | func (pb *ProgressBar) Format(format string) *ProgressBar { 175 | var formatEntries []string 176 | if len(format) == 5 { 177 | formatEntries = strings.Split(format, "") 178 | } else { 179 | formatEntries = strings.Split(format, "\x00") 180 | } 181 | if len(formatEntries) == 5 { 182 | pb.BarStart = formatEntries[0] 183 | pb.BarEnd = formatEntries[4] 184 | pb.Empty = formatEntries[3] 185 | pb.Current = formatEntries[1] 186 | pb.CurrentN = formatEntries[2] 187 | } 188 | return pb 189 | } 190 | 191 | // Set bar refresh rate 192 | func (pb *ProgressBar) SetRefreshRate(rate time.Duration) *ProgressBar { 193 | pb.RefreshRate = rate 194 | return pb 195 | } 196 | 197 | // Set units 198 | // bar.SetUnits(U_NO) - by default 199 | // bar.SetUnits(U_BYTES) - for Mb, Kb, etc 200 | func (pb *ProgressBar) SetUnits(units Units) *ProgressBar { 201 | pb.Units = units 202 | return pb 203 | } 204 | 205 | // Set max width, if width is bigger than terminal width, will be ignored 206 | func (pb *ProgressBar) SetMaxWidth(width int) *ProgressBar { 207 | pb.Width = width 208 | pb.ForceWidth = false 209 | return pb 210 | } 211 | 212 | // Set bar width 213 | func (pb *ProgressBar) SetWidth(width int) *ProgressBar { 214 | pb.Width = width 215 | pb.ForceWidth = true 216 | return pb 217 | } 218 | 219 | // End print 220 | func (pb *ProgressBar) Finish() { 221 | //Protect multiple calls 222 | pb.finishOnce.Do(func() { 223 | close(pb.finish) 224 | pb.write(atomic.LoadInt64(&pb.current)) 225 | if !pb.NotPrint { 226 | fmt.Println() 227 | } 228 | pb.isFinish = true 229 | }) 230 | } 231 | 232 | // End print and write string 'str' 233 | func (pb *ProgressBar) FinishPrint(str string) { 234 | pb.Finish() 235 | fmt.Println(str) 236 | } 237 | 238 | // implement io.Writer 239 | func (pb *ProgressBar) Write(p []byte) (n int, err error) { 240 | n = len(p) 241 | pb.Add(n) 242 | return 243 | } 244 | 245 | // implement io.Reader 246 | func (pb *ProgressBar) Read(p []byte) (n int, err error) { 247 | n = len(p) 248 | pb.Add(n) 249 | return 250 | } 251 | 252 | // Create new proxy reader over bar 253 | // Takes io.Reader or io.ReadCloser 254 | func (pb *ProgressBar) NewProxyReader(r io.Reader) *Reader { 255 | return &Reader{r, pb} 256 | } 257 | 258 | func (pb *ProgressBar) write(current int64) { 259 | width := pb.GetWidth() 260 | 261 | var percentBox, countersBox, timeLeftBox, speedBox, barBox, end, out string 262 | 263 | // percents 264 | if pb.ShowPercent { 265 | var percent float64 266 | if pb.Total > 0 { 267 | percent = float64(current) / (float64(pb.Total) / float64(100)) 268 | } else { 269 | percent = float64(current) / float64(100) 270 | } 271 | percentBox = fmt.Sprintf(" %6.02f%%", percent) 272 | } 273 | 274 | // counters 275 | if pb.ShowCounters { 276 | current := Format(current).To(pb.Units).Width(pb.UnitsWidth) 277 | if pb.Total > 0 { 278 | total := Format(pb.Total).To(pb.Units).Width(pb.UnitsWidth) 279 | countersBox = fmt.Sprintf(" %s / %s ", current, total) 280 | } else { 281 | countersBox = fmt.Sprintf(" %s / ? ", current) 282 | } 283 | } 284 | 285 | // time left 286 | fromStart := time.Now().Sub(pb.startTime) 287 | currentFromStart := current - pb.startValue 288 | select { 289 | case <-pb.finish: 290 | if pb.ShowFinalTime { 291 | var left time.Duration 292 | if pb.Total > 0 { 293 | left = (fromStart / time.Second) * time.Second 294 | } else { 295 | left = (time.Duration(currentFromStart) / time.Second) * time.Second 296 | } 297 | timeLeftBox = fmt.Sprintf(" %s", left.String()) 298 | } 299 | default: 300 | if pb.ShowTimeLeft && currentFromStart > 0 { 301 | perEntry := fromStart / time.Duration(currentFromStart) 302 | var left time.Duration 303 | if pb.Total > 0 { 304 | left = time.Duration(pb.Total-currentFromStart) * perEntry 305 | left = (left / time.Second) * time.Second 306 | } else { 307 | left = time.Duration(currentFromStart) * perEntry 308 | left = (left / time.Second) * time.Second 309 | } 310 | timeLeft := Format(int64(left)).To(U_DURATION).String() 311 | timeLeftBox = fmt.Sprintf(" %s", timeLeft) 312 | } 313 | } 314 | 315 | if len(timeLeftBox) < pb.TimeBoxWidth { 316 | timeLeftBox = fmt.Sprintf("%s%s", strings.Repeat(" ", pb.TimeBoxWidth-len(timeLeftBox)), timeLeftBox) 317 | } 318 | 319 | // speed 320 | if pb.ShowSpeed && currentFromStart > 0 { 321 | fromStart := time.Now().Sub(pb.startTime) 322 | speed := float64(currentFromStart) / (float64(fromStart) / float64(time.Second)) 323 | speedBox = " " + Format(int64(speed)).To(pb.Units).Width(pb.UnitsWidth).PerSec().String() 324 | } 325 | 326 | barWidth := escapeAwareRuneCountInString(countersBox + pb.BarStart + pb.BarEnd + percentBox + timeLeftBox + speedBox + pb.prefix + pb.postfix) 327 | // bar 328 | if pb.ShowBar { 329 | size := width - barWidth 330 | if size > 0 { 331 | if pb.Total > 0 { 332 | curCount := int(math.Ceil((float64(current) / float64(pb.Total)) * float64(size))) 333 | emptCount := size - curCount 334 | barBox = pb.BarStart 335 | if emptCount < 0 { 336 | emptCount = 0 337 | } 338 | if curCount > size { 339 | curCount = size 340 | } 341 | if emptCount <= 0 { 342 | barBox += strings.Repeat(pb.Current, curCount) 343 | } else if curCount > 0 { 344 | barBox += strings.Repeat(pb.Current, curCount-1) + pb.CurrentN 345 | } 346 | barBox += strings.Repeat(pb.Empty, emptCount) + pb.BarEnd 347 | } else { 348 | barBox = pb.BarStart 349 | pos := size - int(current)%int(size) 350 | if pos-1 > 0 { 351 | barBox += strings.Repeat(pb.Empty, pos-1) 352 | } 353 | barBox += pb.Current 354 | if size-pos-1 > 0 { 355 | barBox += strings.Repeat(pb.Empty, size-pos-1) 356 | } 357 | barBox += pb.BarEnd 358 | } 359 | } 360 | } 361 | 362 | // check len 363 | out = pb.prefix + countersBox + barBox + percentBox + speedBox + timeLeftBox + pb.postfix 364 | if escapeAwareRuneCountInString(out) < width { 365 | end = strings.Repeat(" ", width-utf8.RuneCountInString(out)) 366 | } 367 | 368 | // and print! 369 | pb.mu.Lock() 370 | pb.lastPrint = out + end 371 | pb.mu.Unlock() 372 | switch { 373 | case pb.isFinish: 374 | return 375 | case pb.Output != nil: 376 | fmt.Fprint(pb.Output, "\r"+out+end) 377 | case pb.Callback != nil: 378 | pb.Callback(out + end) 379 | case !pb.NotPrint: 380 | fmt.Print("\r" + out + end) 381 | } 382 | } 383 | 384 | // GetTerminalWidth - returns terminal width for all platforms. 385 | func GetTerminalWidth() (int, error) { 386 | return terminalWidth() 387 | } 388 | 389 | func (pb *ProgressBar) GetWidth() int { 390 | if pb.ForceWidth { 391 | return pb.Width 392 | } 393 | 394 | width := pb.Width 395 | termWidth, _ := terminalWidth() 396 | if width == 0 || termWidth <= width { 397 | width = termWidth 398 | } 399 | 400 | return width 401 | } 402 | 403 | // Write the current state of the progressbar 404 | func (pb *ProgressBar) Update() { 405 | c := atomic.LoadInt64(&pb.current) 406 | if pb.AlwaysUpdate || c != pb.currentValue { 407 | pb.write(c) 408 | pb.currentValue = c 409 | } 410 | if pb.AutoStat { 411 | if c == 0 { 412 | pb.startTime = time.Now() 413 | pb.startValue = 0 414 | } else if c >= pb.Total && pb.isFinish != true { 415 | pb.Finish() 416 | } 417 | } 418 | } 419 | 420 | func (pb *ProgressBar) String() string { 421 | return pb.lastPrint 422 | } 423 | 424 | // Internal loop for refreshing the progressbar 425 | func (pb *ProgressBar) refresher() { 426 | for { 427 | select { 428 | case <-pb.finish: 429 | return 430 | case <-time.After(pb.RefreshRate): 431 | pb.Update() 432 | } 433 | } 434 | } 435 | 436 | type window struct { 437 | Row uint16 438 | Col uint16 439 | Xpixel uint16 440 | Ypixel uint16 441 | } 442 | -------------------------------------------------------------------------------- /vendor/github.com/cheggaaa/pb/pb_appengine.go: -------------------------------------------------------------------------------- 1 | // +build appengine 2 | 3 | package pb 4 | 5 | import "errors" 6 | 7 | // terminalWidth returns width of the terminal, which is not supported 8 | // and should always failed on appengine classic which is a sandboxed PaaS. 9 | func terminalWidth() (int, error) { 10 | return 0, errors.New("Not supported") 11 | } 12 | -------------------------------------------------------------------------------- /vendor/github.com/cheggaaa/pb/pb_nix.go: -------------------------------------------------------------------------------- 1 | // +build linux darwin freebsd netbsd openbsd dragonfly 2 | // +build !appengine 3 | 4 | package pb 5 | 6 | import "syscall" 7 | 8 | const sysIoctl = syscall.SYS_IOCTL 9 | -------------------------------------------------------------------------------- /vendor/github.com/cheggaaa/pb/pb_solaris.go: -------------------------------------------------------------------------------- 1 | // +build solaris 2 | // +build !appengine 3 | 4 | package pb 5 | 6 | const sysIoctl = 54 7 | -------------------------------------------------------------------------------- /vendor/github.com/cheggaaa/pb/pb_win.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package pb 4 | 5 | import ( 6 | "errors" 7 | "fmt" 8 | "os" 9 | "sync" 10 | "syscall" 11 | "unsafe" 12 | ) 13 | 14 | var tty = os.Stdin 15 | 16 | var ( 17 | kernel32 = syscall.NewLazyDLL("kernel32.dll") 18 | 19 | // GetConsoleScreenBufferInfo retrieves information about the 20 | // specified console screen buffer. 21 | // http://msdn.microsoft.com/en-us/library/windows/desktop/ms683171(v=vs.85).aspx 22 | procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo") 23 | 24 | // GetConsoleMode retrieves the current input mode of a console's 25 | // input buffer or the current output mode of a console screen buffer. 26 | // https://msdn.microsoft.com/en-us/library/windows/desktop/ms683167(v=vs.85).aspx 27 | getConsoleMode = kernel32.NewProc("GetConsoleMode") 28 | 29 | // SetConsoleMode sets the input mode of a console's input buffer 30 | // or the output mode of a console screen buffer. 31 | // https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx 32 | setConsoleMode = kernel32.NewProc("SetConsoleMode") 33 | 34 | // SetConsoleCursorPosition sets the cursor position in the 35 | // specified console screen buffer. 36 | // https://msdn.microsoft.com/en-us/library/windows/desktop/ms686025(v=vs.85).aspx 37 | setConsoleCursorPosition = kernel32.NewProc("SetConsoleCursorPosition") 38 | ) 39 | 40 | type ( 41 | // Defines the coordinates of the upper left and lower right corners 42 | // of a rectangle. 43 | // See 44 | // http://msdn.microsoft.com/en-us/library/windows/desktop/ms686311(v=vs.85).aspx 45 | smallRect struct { 46 | Left, Top, Right, Bottom int16 47 | } 48 | 49 | // Defines the coordinates of a character cell in a console screen 50 | // buffer. The origin of the coordinate system (0,0) is at the top, left cell 51 | // of the buffer. 52 | // See 53 | // http://msdn.microsoft.com/en-us/library/windows/desktop/ms682119(v=vs.85).aspx 54 | coordinates struct { 55 | X, Y int16 56 | } 57 | 58 | word int16 59 | 60 | // Contains information about a console screen buffer. 61 | // http://msdn.microsoft.com/en-us/library/windows/desktop/ms682093(v=vs.85).aspx 62 | consoleScreenBufferInfo struct { 63 | dwSize coordinates 64 | dwCursorPosition coordinates 65 | wAttributes word 66 | srWindow smallRect 67 | dwMaximumWindowSize coordinates 68 | } 69 | ) 70 | 71 | // terminalWidth returns width of the terminal. 72 | func terminalWidth() (width int, err error) { 73 | var info consoleScreenBufferInfo 74 | _, _, e := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(syscall.Stdout), uintptr(unsafe.Pointer(&info)), 0) 75 | if e != 0 { 76 | return 0, error(e) 77 | } 78 | return int(info.dwSize.X) - 1, nil 79 | } 80 | 81 | func getCursorPos() (pos coordinates, err error) { 82 | var info consoleScreenBufferInfo 83 | _, _, e := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(syscall.Stdout), uintptr(unsafe.Pointer(&info)), 0) 84 | if e != 0 { 85 | return info.dwCursorPosition, error(e) 86 | } 87 | return info.dwCursorPosition, nil 88 | } 89 | 90 | func setCursorPos(pos coordinates) error { 91 | _, _, e := syscall.Syscall(setConsoleCursorPosition.Addr(), 2, uintptr(syscall.Stdout), uintptr(uint32(uint16(pos.Y))<<16|uint32(uint16(pos.X))), 0) 92 | if e != 0 { 93 | return error(e) 94 | } 95 | return nil 96 | } 97 | 98 | var ErrPoolWasStarted = errors.New("Bar pool was started") 99 | 100 | var echoLocked bool 101 | var echoLockMutex sync.Mutex 102 | 103 | var oldState word 104 | 105 | func lockEcho() (quit chan int, err error) { 106 | echoLockMutex.Lock() 107 | defer echoLockMutex.Unlock() 108 | if echoLocked { 109 | err = ErrPoolWasStarted 110 | return 111 | } 112 | echoLocked = true 113 | 114 | if _, _, e := syscall.Syscall(getConsoleMode.Addr(), 2, uintptr(syscall.Stdout), uintptr(unsafe.Pointer(&oldState)), 0); e != 0 { 115 | err = fmt.Errorf("Can't get terminal settings: %v", e) 116 | return 117 | } 118 | 119 | newState := oldState 120 | const ENABLE_ECHO_INPUT = 0x0004 121 | const ENABLE_LINE_INPUT = 0x0002 122 | newState = newState & (^(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT)) 123 | if _, _, e := syscall.Syscall(setConsoleMode.Addr(), 2, uintptr(syscall.Stdout), uintptr(newState), 0); e != 0 { 124 | err = fmt.Errorf("Can't set terminal settings: %v", e) 125 | return 126 | } 127 | return 128 | } 129 | 130 | func unlockEcho() (err error) { 131 | echoLockMutex.Lock() 132 | defer echoLockMutex.Unlock() 133 | if !echoLocked { 134 | return 135 | } 136 | echoLocked = false 137 | if _, _, e := syscall.Syscall(setConsoleMode.Addr(), 2, uintptr(syscall.Stdout), uintptr(oldState), 0); e != 0 { 138 | err = fmt.Errorf("Can't set terminal settings") 139 | } 140 | return 141 | } 142 | -------------------------------------------------------------------------------- /vendor/github.com/cheggaaa/pb/pb_x.go: -------------------------------------------------------------------------------- 1 | // +build linux darwin freebsd netbsd openbsd solaris dragonfly 2 | // +build !appengine 3 | 4 | package pb 5 | 6 | import ( 7 | "errors" 8 | "fmt" 9 | "os" 10 | "os/signal" 11 | "runtime" 12 | "sync" 13 | "syscall" 14 | "unsafe" 15 | ) 16 | 17 | const ( 18 | TIOCGWINSZ = 0x5413 19 | TIOCGWINSZ_OSX = 1074295912 20 | ) 21 | 22 | var tty *os.File 23 | 24 | var ErrPoolWasStarted = errors.New("Bar pool was started") 25 | 26 | var echoLocked bool 27 | var echoLockMutex sync.Mutex 28 | 29 | func init() { 30 | var err error 31 | tty, err = os.Open("/dev/tty") 32 | if err != nil { 33 | tty = os.Stdin 34 | } 35 | } 36 | 37 | // terminalWidth returns width of the terminal. 38 | func terminalWidth() (int, error) { 39 | w := new(window) 40 | tio := syscall.TIOCGWINSZ 41 | if runtime.GOOS == "darwin" { 42 | tio = TIOCGWINSZ_OSX 43 | } 44 | res, _, err := syscall.Syscall(sysIoctl, 45 | tty.Fd(), 46 | uintptr(tio), 47 | uintptr(unsafe.Pointer(w)), 48 | ) 49 | if int(res) == -1 { 50 | return 0, err 51 | } 52 | return int(w.Col), nil 53 | } 54 | 55 | var oldState syscall.Termios 56 | 57 | func lockEcho() (quit chan int, err error) { 58 | echoLockMutex.Lock() 59 | defer echoLockMutex.Unlock() 60 | if echoLocked { 61 | err = ErrPoolWasStarted 62 | return 63 | } 64 | echoLocked = true 65 | 66 | fd := tty.Fd() 67 | if _, _, e := syscall.Syscall6(sysIoctl, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0); e != 0 { 68 | err = fmt.Errorf("Can't get terminal settings: %v", e) 69 | return 70 | } 71 | 72 | newState := oldState 73 | newState.Lflag &^= syscall.ECHO 74 | newState.Lflag |= syscall.ICANON | syscall.ISIG 75 | newState.Iflag |= syscall.ICRNL 76 | if _, _, e := syscall.Syscall6(sysIoctl, fd, ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); e != 0 { 77 | err = fmt.Errorf("Can't set terminal settings: %v", e) 78 | return 79 | } 80 | quit = make(chan int, 1) 81 | go catchTerminate(quit) 82 | return 83 | } 84 | 85 | func unlockEcho() (err error) { 86 | echoLockMutex.Lock() 87 | defer echoLockMutex.Unlock() 88 | if !echoLocked { 89 | return 90 | } 91 | echoLocked = false 92 | fd := tty.Fd() 93 | if _, _, e := syscall.Syscall6(sysIoctl, fd, ioctlWriteTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0); e != 0 { 94 | err = fmt.Errorf("Can't set terminal settings") 95 | } 96 | return 97 | } 98 | 99 | // listen exit signals and restore terminal state 100 | func catchTerminate(quit chan int) { 101 | sig := make(chan os.Signal, 1) 102 | signal.Notify(sig, os.Interrupt, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGKILL) 103 | defer signal.Stop(sig) 104 | select { 105 | case <-quit: 106 | unlockEcho() 107 | case <-sig: 108 | unlockEcho() 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /vendor/github.com/cheggaaa/pb/pool.go: -------------------------------------------------------------------------------- 1 | // +build linux darwin freebsd netbsd openbsd solaris dragonfly windows 2 | 3 | package pb 4 | 5 | import ( 6 | "sync" 7 | "time" 8 | ) 9 | 10 | // Create and start new pool with given bars 11 | // You need call pool.Stop() after work 12 | func StartPool(pbs ...*ProgressBar) (pool *Pool, err error) { 13 | pool = new(Pool) 14 | if err = pool.start(); err != nil { 15 | return 16 | } 17 | pool.Add(pbs...) 18 | return 19 | } 20 | 21 | type Pool struct { 22 | RefreshRate time.Duration 23 | bars []*ProgressBar 24 | quit chan int 25 | finishOnce sync.Once 26 | } 27 | 28 | // Add progress bars. 29 | func (p *Pool) Add(pbs ...*ProgressBar) { 30 | for _, bar := range pbs { 31 | bar.ManualUpdate = true 32 | bar.NotPrint = true 33 | bar.Start() 34 | p.bars = append(p.bars, bar) 35 | } 36 | } 37 | 38 | func (p *Pool) start() (err error) { 39 | p.RefreshRate = DefaultRefreshRate 40 | quit, err := lockEcho() 41 | if err != nil { 42 | return 43 | } 44 | p.quit = make(chan int) 45 | go p.writer(quit) 46 | return 47 | } 48 | 49 | func (p *Pool) writer(finish chan int) { 50 | var first = true 51 | for { 52 | select { 53 | case <-time.After(p.RefreshRate): 54 | if p.print(first) { 55 | p.print(false) 56 | finish <- 1 57 | return 58 | } 59 | first = false 60 | case <-p.quit: 61 | finish <- 1 62 | return 63 | } 64 | } 65 | } 66 | 67 | // Restore terminal state and close pool 68 | func (p *Pool) Stop() error { 69 | // Wait until one final refresh has passed. 70 | time.Sleep(p.RefreshRate) 71 | 72 | p.finishOnce.Do(func() { 73 | close(p.quit) 74 | }) 75 | return unlockEcho() 76 | } 77 | -------------------------------------------------------------------------------- /vendor/github.com/cheggaaa/pb/pool_win.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package pb 4 | 5 | import ( 6 | "fmt" 7 | "log" 8 | ) 9 | 10 | func (p *Pool) print(first bool) bool { 11 | var out string 12 | if !first { 13 | coords, err := getCursorPos() 14 | if err != nil { 15 | log.Panic(err) 16 | } 17 | coords.Y -= int16(len(p.bars)) 18 | coords.X = 0 19 | 20 | err = setCursorPos(coords) 21 | if err != nil { 22 | log.Panic(err) 23 | } 24 | } 25 | isFinished := true 26 | for _, bar := range p.bars { 27 | if !bar.isFinish { 28 | isFinished = false 29 | } 30 | bar.Update() 31 | out += fmt.Sprintf("\r%s\n", bar.String()) 32 | } 33 | fmt.Print(out) 34 | return isFinished 35 | } 36 | -------------------------------------------------------------------------------- /vendor/github.com/cheggaaa/pb/pool_x.go: -------------------------------------------------------------------------------- 1 | // +build linux darwin freebsd netbsd openbsd solaris dragonfly 2 | 3 | package pb 4 | 5 | import "fmt" 6 | 7 | func (p *Pool) print(first bool) bool { 8 | var out string 9 | if !first { 10 | out = fmt.Sprintf("\033[%dA", len(p.bars)) 11 | } 12 | isFinished := true 13 | for _, bar := range p.bars { 14 | if !bar.isFinish { 15 | isFinished = false 16 | } 17 | bar.Update() 18 | out += fmt.Sprintf("\r%s\n", bar.String()) 19 | } 20 | fmt.Print(out) 21 | return isFinished 22 | } 23 | -------------------------------------------------------------------------------- /vendor/github.com/cheggaaa/pb/reader.go: -------------------------------------------------------------------------------- 1 | package pb 2 | 3 | import ( 4 | "io" 5 | ) 6 | 7 | // It's proxy reader, implement io.Reader 8 | type Reader struct { 9 | io.Reader 10 | bar *ProgressBar 11 | } 12 | 13 | func (r *Reader) Read(p []byte) (n int, err error) { 14 | n, err = r.Reader.Read(p) 15 | r.bar.Add(n) 16 | return 17 | } 18 | 19 | // Close the reader when it implements io.Closer 20 | func (r *Reader) Close() (err error) { 21 | if closer, ok := r.Reader.(io.Closer); ok { 22 | return closer.Close() 23 | } 24 | return 25 | } 26 | -------------------------------------------------------------------------------- /vendor/github.com/cheggaaa/pb/runecount.go: -------------------------------------------------------------------------------- 1 | package pb 2 | 3 | import ( 4 | "regexp" 5 | "unicode/utf8" 6 | ) 7 | 8 | // Finds the control character sequences (like colors) 9 | var ctrlFinder = regexp.MustCompile("\x1b\x5b[0-9]+\x6d") 10 | 11 | func escapeAwareRuneCountInString(s string) int { 12 | n := utf8.RuneCountInString(s) 13 | for _, sm := range ctrlFinder.FindAllString(s, -1) { 14 | n -= len(sm) 15 | } 16 | return n 17 | } 18 | -------------------------------------------------------------------------------- /vendor/github.com/cheggaaa/pb/termios_bsd.go: -------------------------------------------------------------------------------- 1 | // +build darwin freebsd netbsd openbsd dragonfly 2 | // +build !appengine 3 | 4 | package pb 5 | 6 | import "syscall" 7 | 8 | const ioctlReadTermios = syscall.TIOCGETA 9 | const ioctlWriteTermios = syscall.TIOCSETA 10 | -------------------------------------------------------------------------------- /vendor/github.com/cheggaaa/pb/termios_nix.go: -------------------------------------------------------------------------------- 1 | // +build linux solaris 2 | // +build !appengine 3 | 4 | package pb 5 | 6 | const ioctlReadTermios = 0x5401 // syscall.TCGETS 7 | const ioctlWriteTermios = 0x5402 // syscall.TCSETS 8 | -------------------------------------------------------------------------------- /vendor/github.com/codegangsta/cli/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | 4 | go: 5 | - 1.0.3 6 | - 1.1.2 7 | - 1.2.2 8 | - 1.3.3 9 | - 1.4.2 10 | 11 | script: 12 | - go vet ./... 13 | - go test -v ./... 14 | -------------------------------------------------------------------------------- /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/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/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/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/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/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/codegangsta/cli/flag.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | "strconv" 8 | "strings" 9 | "time" 10 | ) 11 | 12 | // This flag enables bash-completion for all commands and subcommands 13 | var BashCompletionFlag = BoolFlag{ 14 | Name: "generate-bash-completion", 15 | } 16 | 17 | // This flag prints the version for the application 18 | var VersionFlag = BoolFlag{ 19 | Name: "version, v", 20 | Usage: "print the version", 21 | } 22 | 23 | // This flag prints the help for all commands and subcommands 24 | // Set to the zero value (BoolFlag{}) to disable flag -- keeps subcommand 25 | // unless HideHelp is set to true) 26 | var HelpFlag = BoolFlag{ 27 | Name: "help, h", 28 | Usage: "show help", 29 | } 30 | 31 | // Flag is a common interface related to parsing flags in cli. 32 | // For more advanced flag parsing techniques, it is recomended that 33 | // this interface be implemented. 34 | type Flag interface { 35 | fmt.Stringer 36 | // Apply Flag settings to the given flag set 37 | Apply(*flag.FlagSet) 38 | getName() string 39 | } 40 | 41 | func flagSet(name string, flags []Flag) *flag.FlagSet { 42 | set := flag.NewFlagSet(name, flag.ContinueOnError) 43 | 44 | for _, f := range flags { 45 | f.Apply(set) 46 | } 47 | return set 48 | } 49 | 50 | func eachName(longName string, fn func(string)) { 51 | parts := strings.Split(longName, ",") 52 | for _, name := range parts { 53 | name = strings.Trim(name, " ") 54 | fn(name) 55 | } 56 | } 57 | 58 | // Generic is a generic parseable type identified by a specific flag 59 | type Generic interface { 60 | Set(value string) error 61 | String() string 62 | } 63 | 64 | // GenericFlag is the flag type for types implementing Generic 65 | type GenericFlag struct { 66 | Name string 67 | Value Generic 68 | Usage string 69 | EnvVar string 70 | } 71 | 72 | // String returns the string representation of the generic flag to display the 73 | // help text to the user (uses the String() method of the generic flag to show 74 | // the value) 75 | func (f GenericFlag) String() string { 76 | return withEnvHint(f.EnvVar, fmt.Sprintf("%s%s \"%v\"\t%v", prefixFor(f.Name), f.Name, f.Value, f.Usage)) 77 | } 78 | 79 | // Apply takes the flagset and calls Set on the generic flag with the value 80 | // provided by the user for parsing by the flag 81 | func (f GenericFlag) Apply(set *flag.FlagSet) { 82 | val := f.Value 83 | if f.EnvVar != "" { 84 | for _, envVar := range strings.Split(f.EnvVar, ",") { 85 | envVar = strings.TrimSpace(envVar) 86 | if envVal := os.Getenv(envVar); envVal != "" { 87 | val.Set(envVal) 88 | break 89 | } 90 | } 91 | } 92 | 93 | eachName(f.Name, func(name string) { 94 | set.Var(f.Value, name, f.Usage) 95 | }) 96 | } 97 | 98 | func (f GenericFlag) getName() string { 99 | return f.Name 100 | } 101 | 102 | // StringSlice is an opaque type for []string to satisfy flag.Value 103 | type StringSlice []string 104 | 105 | // Set appends the string value to the list of values 106 | func (f *StringSlice) Set(value string) error { 107 | *f = append(*f, value) 108 | return nil 109 | } 110 | 111 | // String returns a readable representation of this value (for usage defaults) 112 | func (f *StringSlice) String() string { 113 | return fmt.Sprintf("%s", *f) 114 | } 115 | 116 | // Value returns the slice of strings set by this flag 117 | func (f *StringSlice) Value() []string { 118 | return *f 119 | } 120 | 121 | // StringSlice is a string flag that can be specified multiple times on the 122 | // command-line 123 | type StringSliceFlag struct { 124 | Name string 125 | Value *StringSlice 126 | Usage string 127 | EnvVar string 128 | } 129 | 130 | // String returns the usage 131 | func (f StringSliceFlag) String() string { 132 | firstName := strings.Trim(strings.Split(f.Name, ",")[0], " ") 133 | pref := prefixFor(firstName) 134 | return withEnvHint(f.EnvVar, fmt.Sprintf("%s [%v]\t%v", prefixedNames(f.Name), pref+firstName+" option "+pref+firstName+" option", f.Usage)) 135 | } 136 | 137 | // Apply populates the flag given the flag set and environment 138 | func (f StringSliceFlag) Apply(set *flag.FlagSet) { 139 | if f.EnvVar != "" { 140 | for _, envVar := range strings.Split(f.EnvVar, ",") { 141 | envVar = strings.TrimSpace(envVar) 142 | if envVal := os.Getenv(envVar); envVal != "" { 143 | newVal := &StringSlice{} 144 | for _, s := range strings.Split(envVal, ",") { 145 | s = strings.TrimSpace(s) 146 | newVal.Set(s) 147 | } 148 | f.Value = newVal 149 | break 150 | } 151 | } 152 | } 153 | 154 | eachName(f.Name, func(name string) { 155 | if f.Value == nil { 156 | f.Value = &StringSlice{} 157 | } 158 | set.Var(f.Value, name, f.Usage) 159 | }) 160 | } 161 | 162 | func (f StringSliceFlag) getName() string { 163 | return f.Name 164 | } 165 | 166 | // StringSlice is an opaque type for []int to satisfy flag.Value 167 | type IntSlice []int 168 | 169 | // Set parses the value into an integer and appends it to the list of values 170 | func (f *IntSlice) Set(value string) error { 171 | tmp, err := strconv.Atoi(value) 172 | if err != nil { 173 | return err 174 | } else { 175 | *f = append(*f, tmp) 176 | } 177 | return nil 178 | } 179 | 180 | // String returns a readable representation of this value (for usage defaults) 181 | func (f *IntSlice) String() string { 182 | return fmt.Sprintf("%d", *f) 183 | } 184 | 185 | // Value returns the slice of ints set by this flag 186 | func (f *IntSlice) Value() []int { 187 | return *f 188 | } 189 | 190 | // IntSliceFlag is an int flag that can be specified multiple times on the 191 | // command-line 192 | type IntSliceFlag struct { 193 | Name string 194 | Value *IntSlice 195 | Usage string 196 | EnvVar string 197 | } 198 | 199 | // String returns the usage 200 | func (f IntSliceFlag) String() string { 201 | firstName := strings.Trim(strings.Split(f.Name, ",")[0], " ") 202 | pref := prefixFor(firstName) 203 | return withEnvHint(f.EnvVar, fmt.Sprintf("%s [%v]\t%v", prefixedNames(f.Name), pref+firstName+" option "+pref+firstName+" option", f.Usage)) 204 | } 205 | 206 | // Apply populates the flag given the flag set and environment 207 | func (f IntSliceFlag) Apply(set *flag.FlagSet) { 208 | if f.EnvVar != "" { 209 | for _, envVar := range strings.Split(f.EnvVar, ",") { 210 | envVar = strings.TrimSpace(envVar) 211 | if envVal := os.Getenv(envVar); envVal != "" { 212 | newVal := &IntSlice{} 213 | for _, s := range strings.Split(envVal, ",") { 214 | s = strings.TrimSpace(s) 215 | err := newVal.Set(s) 216 | if err != nil { 217 | fmt.Fprintf(os.Stderr, err.Error()) 218 | } 219 | } 220 | f.Value = newVal 221 | break 222 | } 223 | } 224 | } 225 | 226 | eachName(f.Name, func(name string) { 227 | if f.Value == nil { 228 | f.Value = &IntSlice{} 229 | } 230 | set.Var(f.Value, name, f.Usage) 231 | }) 232 | } 233 | 234 | func (f IntSliceFlag) getName() string { 235 | return f.Name 236 | } 237 | 238 | // BoolFlag is a switch that defaults to false 239 | type BoolFlag struct { 240 | Name string 241 | Usage string 242 | EnvVar string 243 | } 244 | 245 | // String returns a readable representation of this value (for usage defaults) 246 | func (f BoolFlag) String() string { 247 | return withEnvHint(f.EnvVar, fmt.Sprintf("%s\t%v", prefixedNames(f.Name), f.Usage)) 248 | } 249 | 250 | // Apply populates the flag given the flag set and environment 251 | func (f BoolFlag) Apply(set *flag.FlagSet) { 252 | val := false 253 | if f.EnvVar != "" { 254 | for _, envVar := range strings.Split(f.EnvVar, ",") { 255 | envVar = strings.TrimSpace(envVar) 256 | if envVal := os.Getenv(envVar); envVal != "" { 257 | envValBool, err := strconv.ParseBool(envVal) 258 | if err == nil { 259 | val = envValBool 260 | } 261 | break 262 | } 263 | } 264 | } 265 | 266 | eachName(f.Name, func(name string) { 267 | set.Bool(name, val, f.Usage) 268 | }) 269 | } 270 | 271 | func (f BoolFlag) getName() string { 272 | return f.Name 273 | } 274 | 275 | // BoolTFlag this represents a boolean flag that is true by default, but can 276 | // still be set to false by --some-flag=false 277 | type BoolTFlag struct { 278 | Name string 279 | Usage string 280 | EnvVar string 281 | } 282 | 283 | // String returns a readable representation of this value (for usage defaults) 284 | func (f BoolTFlag) String() string { 285 | return withEnvHint(f.EnvVar, fmt.Sprintf("%s\t%v", prefixedNames(f.Name), f.Usage)) 286 | } 287 | 288 | // Apply populates the flag given the flag set and environment 289 | func (f BoolTFlag) Apply(set *flag.FlagSet) { 290 | val := true 291 | if f.EnvVar != "" { 292 | for _, envVar := range strings.Split(f.EnvVar, ",") { 293 | envVar = strings.TrimSpace(envVar) 294 | if envVal := os.Getenv(envVar); envVal != "" { 295 | envValBool, err := strconv.ParseBool(envVal) 296 | if err == nil { 297 | val = envValBool 298 | break 299 | } 300 | } 301 | } 302 | } 303 | 304 | eachName(f.Name, func(name string) { 305 | set.Bool(name, val, f.Usage) 306 | }) 307 | } 308 | 309 | func (f BoolTFlag) getName() string { 310 | return f.Name 311 | } 312 | 313 | // StringFlag represents a flag that takes as string value 314 | type StringFlag struct { 315 | Name string 316 | Value string 317 | Usage string 318 | EnvVar string 319 | } 320 | 321 | // String returns the usage 322 | func (f StringFlag) String() string { 323 | var fmtString string 324 | fmtString = "%s %v\t%v" 325 | 326 | if len(f.Value) > 0 { 327 | fmtString = "%s \"%v\"\t%v" 328 | } else { 329 | fmtString = "%s %v\t%v" 330 | } 331 | 332 | return withEnvHint(f.EnvVar, fmt.Sprintf(fmtString, prefixedNames(f.Name), f.Value, f.Usage)) 333 | } 334 | 335 | // Apply populates the flag given the flag set and environment 336 | func (f StringFlag) Apply(set *flag.FlagSet) { 337 | if f.EnvVar != "" { 338 | for _, envVar := range strings.Split(f.EnvVar, ",") { 339 | envVar = strings.TrimSpace(envVar) 340 | if envVal := os.Getenv(envVar); envVal != "" { 341 | f.Value = envVal 342 | break 343 | } 344 | } 345 | } 346 | 347 | eachName(f.Name, func(name string) { 348 | set.String(name, f.Value, f.Usage) 349 | }) 350 | } 351 | 352 | func (f StringFlag) getName() string { 353 | return f.Name 354 | } 355 | 356 | // IntFlag is a flag that takes an integer 357 | // Errors if the value provided cannot be parsed 358 | type IntFlag struct { 359 | Name string 360 | Value int 361 | Usage string 362 | EnvVar string 363 | } 364 | 365 | // String returns the usage 366 | func (f IntFlag) String() string { 367 | return withEnvHint(f.EnvVar, fmt.Sprintf("%s \"%v\"\t%v", prefixedNames(f.Name), f.Value, f.Usage)) 368 | } 369 | 370 | // Apply populates the flag given the flag set and environment 371 | func (f IntFlag) Apply(set *flag.FlagSet) { 372 | if f.EnvVar != "" { 373 | for _, envVar := range strings.Split(f.EnvVar, ",") { 374 | envVar = strings.TrimSpace(envVar) 375 | if envVal := os.Getenv(envVar); envVal != "" { 376 | envValInt, err := strconv.ParseInt(envVal, 0, 64) 377 | if err == nil { 378 | f.Value = int(envValInt) 379 | break 380 | } 381 | } 382 | } 383 | } 384 | 385 | eachName(f.Name, func(name string) { 386 | set.Int(name, f.Value, f.Usage) 387 | }) 388 | } 389 | 390 | func (f IntFlag) getName() string { 391 | return f.Name 392 | } 393 | 394 | // DurationFlag is a flag that takes a duration specified in Go's duration 395 | // format: https://golang.org/pkg/time/#ParseDuration 396 | type DurationFlag struct { 397 | Name string 398 | Value time.Duration 399 | Usage string 400 | EnvVar string 401 | } 402 | 403 | // String returns a readable representation of this value (for usage defaults) 404 | func (f DurationFlag) String() string { 405 | return withEnvHint(f.EnvVar, fmt.Sprintf("%s \"%v\"\t%v", prefixedNames(f.Name), f.Value, f.Usage)) 406 | } 407 | 408 | // Apply populates the flag given the flag set and environment 409 | func (f DurationFlag) Apply(set *flag.FlagSet) { 410 | if f.EnvVar != "" { 411 | for _, envVar := range strings.Split(f.EnvVar, ",") { 412 | envVar = strings.TrimSpace(envVar) 413 | if envVal := os.Getenv(envVar); envVal != "" { 414 | envValDuration, err := time.ParseDuration(envVal) 415 | if err == nil { 416 | f.Value = envValDuration 417 | break 418 | } 419 | } 420 | } 421 | } 422 | 423 | eachName(f.Name, func(name string) { 424 | set.Duration(name, f.Value, f.Usage) 425 | }) 426 | } 427 | 428 | func (f DurationFlag) getName() string { 429 | return f.Name 430 | } 431 | 432 | // Float64Flag is a flag that takes an float value 433 | // Errors if the value provided cannot be parsed 434 | type Float64Flag struct { 435 | Name string 436 | Value float64 437 | Usage string 438 | EnvVar string 439 | } 440 | 441 | // String returns the usage 442 | func (f Float64Flag) String() string { 443 | return withEnvHint(f.EnvVar, fmt.Sprintf("%s \"%v\"\t%v", prefixedNames(f.Name), f.Value, f.Usage)) 444 | } 445 | 446 | // Apply populates the flag given the flag set and environment 447 | func (f Float64Flag) Apply(set *flag.FlagSet) { 448 | if f.EnvVar != "" { 449 | for _, envVar := range strings.Split(f.EnvVar, ",") { 450 | envVar = strings.TrimSpace(envVar) 451 | if envVal := os.Getenv(envVar); envVal != "" { 452 | envValFloat, err := strconv.ParseFloat(envVal, 10) 453 | if err == nil { 454 | f.Value = float64(envValFloat) 455 | } 456 | } 457 | } 458 | } 459 | 460 | eachName(f.Name, func(name string) { 461 | set.Float64(name, f.Value, f.Usage) 462 | }) 463 | } 464 | 465 | func (f Float64Flag) getName() string { 466 | return f.Name 467 | } 468 | 469 | func prefixFor(name string) (prefix string) { 470 | if len(name) == 1 { 471 | prefix = "-" 472 | } else { 473 | prefix = "--" 474 | } 475 | 476 | return 477 | } 478 | 479 | func prefixedNames(fullName string) (prefixed string) { 480 | parts := strings.Split(fullName, ",") 481 | for i, name := range parts { 482 | name = strings.Trim(name, " ") 483 | prefixed += prefixFor(name) + name 484 | if i < len(parts)-1 { 485 | prefixed += ", " 486 | } 487 | } 488 | return 489 | } 490 | 491 | func withEnvHint(envVar, str string) string { 492 | envText := "" 493 | if envVar != "" { 494 | envText = fmt.Sprintf(" [$%s]", strings.Join(strings.Split(envVar, ","), ", $")) 495 | } 496 | return str + envText 497 | } 498 | -------------------------------------------------------------------------------- /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/codegangsta/inject/.gitignore: -------------------------------------------------------------------------------- 1 | inject 2 | inject.test 3 | -------------------------------------------------------------------------------- /vendor/github.com/codegangsta/inject/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Jeremy Saenz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /vendor/github.com/codegangsta/inject/README.md: -------------------------------------------------------------------------------- 1 | # inject 2 | -- 3 | import "github.com/codegangsta/inject" 4 | 5 | Package inject provides utilities for mapping and injecting dependencies in 6 | various ways. 7 | 8 | Language Translations: 9 | * [简体中文](translations/README_zh_cn.md) 10 | 11 | ## Usage 12 | 13 | #### func InterfaceOf 14 | 15 | ```go 16 | func InterfaceOf(value interface{}) reflect.Type 17 | ``` 18 | InterfaceOf dereferences a pointer to an Interface type. It panics if value is 19 | not an pointer to an interface. 20 | 21 | #### type Applicator 22 | 23 | ```go 24 | type Applicator interface { 25 | // Maps dependencies in the Type map to each field in the struct 26 | // that is tagged with 'inject'. Returns an error if the injection 27 | // fails. 28 | Apply(interface{}) error 29 | } 30 | ``` 31 | 32 | Applicator represents an interface for mapping dependencies to a struct. 33 | 34 | #### type Injector 35 | 36 | ```go 37 | type Injector interface { 38 | Applicator 39 | Invoker 40 | TypeMapper 41 | // SetParent sets the parent of the injector. If the injector cannot find a 42 | // dependency in its Type map it will check its parent before returning an 43 | // error. 44 | SetParent(Injector) 45 | } 46 | ``` 47 | 48 | Injector represents an interface for mapping and injecting dependencies into 49 | structs and function arguments. 50 | 51 | #### func New 52 | 53 | ```go 54 | func New() Injector 55 | ``` 56 | New returns a new Injector. 57 | 58 | #### type Invoker 59 | 60 | ```go 61 | type Invoker interface { 62 | // Invoke attempts to call the interface{} provided as a function, 63 | // providing dependencies for function arguments based on Type. Returns 64 | // a slice of reflect.Value representing the returned values of the function. 65 | // Returns an error if the injection fails. 66 | Invoke(interface{}) ([]reflect.Value, error) 67 | } 68 | ``` 69 | 70 | Invoker represents an interface for calling functions via reflection. 71 | 72 | #### type TypeMapper 73 | 74 | ```go 75 | type TypeMapper interface { 76 | // Maps the interface{} value based on its immediate type from reflect.TypeOf. 77 | Map(interface{}) TypeMapper 78 | // Maps the interface{} value based on the pointer of an Interface provided. 79 | // This is really only useful for mapping a value as an interface, as interfaces 80 | // cannot at this time be referenced directly without a pointer. 81 | MapTo(interface{}, interface{}) TypeMapper 82 | // Provides a possibility to directly insert a mapping based on type and value. 83 | // This makes it possible to directly map type arguments not possible to instantiate 84 | // with reflect like unidirectional channels. 85 | Set(reflect.Type, reflect.Value) TypeMapper 86 | // Returns the Value that is mapped to the current type. Returns a zeroed Value if 87 | // the Type has not been mapped. 88 | Get(reflect.Type) reflect.Value 89 | } 90 | ``` 91 | 92 | TypeMapper represents an interface for mapping interface{} values based on type. 93 | -------------------------------------------------------------------------------- /vendor/github.com/codegangsta/inject/inject.go: -------------------------------------------------------------------------------- 1 | // Package inject provides utilities for mapping and injecting dependencies in various ways. 2 | package inject 3 | 4 | import ( 5 | "fmt" 6 | "reflect" 7 | ) 8 | 9 | // Injector represents an interface for mapping and injecting dependencies into structs 10 | // and function arguments. 11 | type Injector interface { 12 | Applicator 13 | Invoker 14 | TypeMapper 15 | // SetParent sets the parent of the injector. If the injector cannot find a 16 | // dependency in its Type map it will check its parent before returning an 17 | // error. 18 | SetParent(Injector) 19 | } 20 | 21 | // Applicator represents an interface for mapping dependencies to a struct. 22 | type Applicator interface { 23 | // Maps dependencies in the Type map to each field in the struct 24 | // that is tagged with 'inject'. Returns an error if the injection 25 | // fails. 26 | Apply(interface{}) error 27 | } 28 | 29 | // Invoker represents an interface for calling functions via reflection. 30 | type Invoker interface { 31 | // Invoke attempts to call the interface{} provided as a function, 32 | // providing dependencies for function arguments based on Type. Returns 33 | // a slice of reflect.Value representing the returned values of the function. 34 | // Returns an error if the injection fails. 35 | Invoke(interface{}) ([]reflect.Value, error) 36 | } 37 | 38 | // TypeMapper represents an interface for mapping interface{} values based on type. 39 | type TypeMapper interface { 40 | // Maps the interface{} value based on its immediate type from reflect.TypeOf. 41 | Map(interface{}) TypeMapper 42 | // Maps the interface{} value based on the pointer of an Interface provided. 43 | // This is really only useful for mapping a value as an interface, as interfaces 44 | // cannot at this time be referenced directly without a pointer. 45 | MapTo(interface{}, interface{}) TypeMapper 46 | // Provides a possibility to directly insert a mapping based on type and value. 47 | // This makes it possible to directly map type arguments not possible to instantiate 48 | // with reflect like unidirectional channels. 49 | Set(reflect.Type, reflect.Value) TypeMapper 50 | // Returns the Value that is mapped to the current type. Returns a zeroed Value if 51 | // the Type has not been mapped. 52 | Get(reflect.Type) reflect.Value 53 | } 54 | 55 | type injector struct { 56 | values map[reflect.Type]reflect.Value 57 | parent Injector 58 | } 59 | 60 | // InterfaceOf dereferences a pointer to an Interface type. 61 | // It panics if value is not an pointer to an interface. 62 | func InterfaceOf(value interface{}) reflect.Type { 63 | t := reflect.TypeOf(value) 64 | 65 | for t.Kind() == reflect.Ptr { 66 | t = t.Elem() 67 | } 68 | 69 | if t.Kind() != reflect.Interface { 70 | panic("Called inject.InterfaceOf with a value that is not a pointer to an interface. (*MyInterface)(nil)") 71 | } 72 | 73 | return t 74 | } 75 | 76 | // New returns a new Injector. 77 | func New() Injector { 78 | return &injector{ 79 | values: make(map[reflect.Type]reflect.Value), 80 | } 81 | } 82 | 83 | // Invoke attempts to call the interface{} provided as a function, 84 | // providing dependencies for function arguments based on Type. 85 | // Returns a slice of reflect.Value representing the returned values of the function. 86 | // Returns an error if the injection fails. 87 | // It panics if f is not a function 88 | func (inj *injector) Invoke(f interface{}) ([]reflect.Value, error) { 89 | t := reflect.TypeOf(f) 90 | 91 | var in = make([]reflect.Value, t.NumIn()) //Panic if t is not kind of Func 92 | for i := 0; i < t.NumIn(); i++ { 93 | argType := t.In(i) 94 | val := inj.Get(argType) 95 | if !val.IsValid() { 96 | return nil, fmt.Errorf("Value not found for type %v", argType) 97 | } 98 | 99 | in[i] = val 100 | } 101 | 102 | return reflect.ValueOf(f).Call(in), nil 103 | } 104 | 105 | // Maps dependencies in the Type map to each field in the struct 106 | // that is tagged with 'inject'. 107 | // Returns an error if the injection fails. 108 | func (inj *injector) Apply(val interface{}) error { 109 | v := reflect.ValueOf(val) 110 | 111 | for v.Kind() == reflect.Ptr { 112 | v = v.Elem() 113 | } 114 | 115 | if v.Kind() != reflect.Struct { 116 | return nil // Should not panic here ? 117 | } 118 | 119 | t := v.Type() 120 | 121 | for i := 0; i < v.NumField(); i++ { 122 | f := v.Field(i) 123 | structField := t.Field(i) 124 | if f.CanSet() && (structField.Tag == "inject" || structField.Tag.Get("inject") != "") { 125 | ft := f.Type() 126 | v := inj.Get(ft) 127 | if !v.IsValid() { 128 | return fmt.Errorf("Value not found for type %v", ft) 129 | } 130 | 131 | f.Set(v) 132 | } 133 | 134 | } 135 | 136 | return nil 137 | } 138 | 139 | // Maps the concrete value of val to its dynamic type using reflect.TypeOf, 140 | // It returns the TypeMapper registered in. 141 | func (i *injector) Map(val interface{}) TypeMapper { 142 | i.values[reflect.TypeOf(val)] = reflect.ValueOf(val) 143 | return i 144 | } 145 | 146 | func (i *injector) MapTo(val interface{}, ifacePtr interface{}) TypeMapper { 147 | i.values[InterfaceOf(ifacePtr)] = reflect.ValueOf(val) 148 | return i 149 | } 150 | 151 | // Maps the given reflect.Type to the given reflect.Value and returns 152 | // the Typemapper the mapping has been registered in. 153 | func (i *injector) Set(typ reflect.Type, val reflect.Value) TypeMapper { 154 | i.values[typ] = val 155 | return i 156 | } 157 | 158 | func (i *injector) Get(t reflect.Type) reflect.Value { 159 | val := i.values[t] 160 | 161 | if val.IsValid() { 162 | return val 163 | } 164 | 165 | // no concrete types found, try to find implementors 166 | // if t is an interface 167 | if t.Kind() == reflect.Interface { 168 | for k, v := range i.values { 169 | if k.Implements(t) { 170 | val = v 171 | break 172 | } 173 | } 174 | } 175 | 176 | // Still no type found, try to look it up on the parent 177 | if !val.IsValid() && i.parent != nil { 178 | val = i.parent.Get(t) 179 | } 180 | 181 | return val 182 | 183 | } 184 | 185 | func (i *injector) SetParent(parent Injector) { 186 | i.parent = parent 187 | } 188 | -------------------------------------------------------------------------------- /vendor/github.com/codegangsta/inject/update_readme.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | go get github.com/robertkrimen/godocdown/godocdown 3 | godocdown > README.md 4 | -------------------------------------------------------------------------------- /vendor/github.com/codeskyblue/go-sh/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /vendor/github.com/codeskyblue/go-sh/OLD_README.md: -------------------------------------------------------------------------------- 1 | ## OLD README 2 | First give you a full example, I will explain every command below. 3 | 4 | session := sh.NewSession() 5 | session.Env["PATH"] = "/usr/bin:/bin" 6 | session.Stdout = os.Stdout 7 | session.Stderr = os.Stderr 8 | session.Alias("ll", "ls", "-l") 9 | session.ShowCMD = true // enable for debug 10 | var err error 11 | err = session.Call("ll", "/") 12 | if err != nil { 13 | log.Fatal(err) 14 | } 15 | ret, err := session.Capture("pwd", sh.Dir("/home")) # wraper of session.Call 16 | if err != nil { 17 | log.Fatal(err) 18 | } 19 | # ret is "/home\n" 20 | fmt.Println(ret) 21 | 22 | create a new Session 23 | 24 | session := sh.NewSession() 25 | 26 | use alias like this 27 | 28 | session.Alias("ll", "ls", "-l") # like alias ll='ls -l' 29 | 30 | set current env like this 31 | 32 | session.Env["BUILD_ID"] = "123" # like export BUILD_ID=123 33 | 34 | set current directory 35 | 36 | session.Set(sh.Dir("/")) # like cd / 37 | 38 | pipe is also supported 39 | 40 | session.Command("echo", "hello\tworld").Command("cut", "-f2") 41 | // output should be "world" 42 | session.Run() 43 | 44 | test, the build in command support 45 | 46 | session.Test("d", "dir") // test dir 47 | session.Test("f", "file) // test regular file 48 | 49 | with `Alias Env Set Call Capture Command` a shell scripts can be easily converted into golang program. below is a shell script. 50 | 51 | #!/bin/bash - 52 | # 53 | export PATH=/usr/bin:/bin 54 | alias ll='ls -l' 55 | cd /usr 56 | if test -d "local" 57 | then 58 | ll local | awk '{print $1, $NF}' 59 | fi 60 | 61 | convert to golang, will be 62 | 63 | s := sh.NewSession() 64 | s.Env["PATH"] = "/usr/bin:/bin" 65 | s.Set(sh.Dir("/usr")) 66 | s.Alias("ll", "ls", "-l") 67 | if s.Test("d", "local") { 68 | s.Command("ll", "local").Command("awk", "{print $1, $NF}").Run() 69 | } 70 | -------------------------------------------------------------------------------- /vendor/github.com/codeskyblue/go-sh/README.md: -------------------------------------------------------------------------------- 1 | ## go-sh 2 | [![wercker status](https://app.wercker.com/status/009acbd4f00ccc6de7e2554e12a50d84/s "wercker status")](https://app.wercker.com/project/bykey/009acbd4f00ccc6de7e2554e12a50d84) 3 | [![Go Walker](http://gowalker.org/api/v1/badge)](http://gowalker.org/github.com/codeskyblue/go-sh) 4 | 5 | *If you depend on the old api, see tag: v.0.1* 6 | 7 | install: `go get github.com/codeskyblue/go-sh` 8 | 9 | Pipe Example: 10 | 11 | package main 12 | 13 | import "github.com/codeskyblue/go-sh" 14 | 15 | func main() { 16 | sh.Command("echo", "hello\tworld").Command("cut", "-f2").Run() 17 | } 18 | 19 | Because I like os/exec, `go-sh` is very much modelled after it. However, `go-sh` provides a better experience. 20 | 21 | These are some of its features: 22 | 23 | * keep the variable environment (e.g. export) 24 | * alias support (e.g. alias in shell) 25 | * remember current dir 26 | * pipe command 27 | * shell build-in commands echo & test 28 | * timeout support 29 | 30 | Examples are important: 31 | 32 | sh: echo hello 33 | go: sh.Command("echo", "hello").Run() 34 | 35 | sh: export BUILD_ID=123 36 | go: s = sh.NewSession().SetEnv("BUILD_ID", "123") 37 | 38 | sh: alias ll='ls -l' 39 | go: s = sh.NewSession().Alias('ll', 'ls', '-l') 40 | 41 | sh: (cd /; pwd) 42 | go: sh.Command("pwd", sh.Dir("/")).Run() 43 | 44 | sh: test -d data || mkdir data 45 | go: if ! sh.Test("dir", "data") { sh.Command("mkdir", "data").Run() } 46 | 47 | sh: cat first second | awk '{print $1}' 48 | go: sh.Command("cat", "first", "second").Command("awk", "{print $1}").Run() 49 | 50 | sh: count=$(echo "one two three" | wc -w) 51 | go: count, err := sh.Echo("one two three").Command("wc", "-w").Output() 52 | 53 | sh(in ubuntu): timeout 1s sleep 3 54 | go: c := sh.Command("sleep", "3"); c.Start(); c.WaitTimeout(time.Seocnd) # default SIGKILL 55 | go: out, err := sh.Command("sleep", "3").SetTimeout(time.Second).Output() # set session timeout and get output) 56 | 57 | sh: echo hello | cat 58 | go: out, err := sh.Command("cat").SetInput("hello").Output() 59 | 60 | sh: cat # read from stdin 61 | go: out, err := sh.Command("cat").SetStdin(os.Stdin).Output() 62 | 63 | If you need to keep env and dir, it is better to create a session 64 | 65 | session := sh.NewSession() 66 | session.SetEnv("BUILD_ID", "123") 67 | session.SetDir("/") 68 | # then call cmd 69 | session.Command("echo", "hello").Run() 70 | # set ShowCMD to true for easily debug 71 | session.ShowCMD = true 72 | 73 | for more information, it better to see docs. 74 | [![Go Walker](http://gowalker.org/api/v1/badge)](http://gowalker.org/github.com/codeskyblue/go-sh) 75 | 76 | ### contribute 77 | If you love this project, starring it will encourage the coder. Pull requests are welcome. 78 | 79 | support the author: [alipay](https://me.alipay.com/goskyblue) 80 | 81 | ### thanks 82 | this project is based on . thanks for the author. 83 | 84 | # the reason to use Go shell 85 | Sometimes we need to write shell scripts, but shell scripts are not good at working cross platform, Go, on the other hand, is good at that. Is there a good way to use Go to write shell like scripts? Using go-sh we can do this now. 86 | -------------------------------------------------------------------------------- /vendor/github.com/codeskyblue/go-sh/pipe.go: -------------------------------------------------------------------------------- 1 | package sh 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "encoding/xml" 7 | "errors" 8 | "io" 9 | "os" 10 | "strings" 11 | "syscall" 12 | "time" 13 | ) 14 | 15 | var ErrExecTimeout = errors.New("execute timeout") 16 | 17 | // unmarshal shell output to decode json 18 | func (s *Session) UnmarshalJSON(data interface{}) (err error) { 19 | bufrw := bytes.NewBuffer(nil) 20 | s.Stdout = bufrw 21 | if err = s.Run(); err != nil { 22 | return 23 | } 24 | return json.NewDecoder(bufrw).Decode(data) 25 | } 26 | 27 | // unmarshal command output into xml 28 | func (s *Session) UnmarshalXML(data interface{}) (err error) { 29 | bufrw := bytes.NewBuffer(nil) 30 | s.Stdout = bufrw 31 | if err = s.Run(); err != nil { 32 | return 33 | } 34 | return xml.NewDecoder(bufrw).Decode(data) 35 | } 36 | 37 | // start command 38 | func (s *Session) Start() (err error) { 39 | s.started = true 40 | var rd *io.PipeReader 41 | var wr *io.PipeWriter 42 | var length = len(s.cmds) 43 | if s.ShowCMD { 44 | var cmds = make([]string, 0, 4) 45 | for _, cmd := range s.cmds { 46 | cmds = append(cmds, strings.Join(cmd.Args, " ")) 47 | } 48 | s.writePrompt(strings.Join(cmds, " | ")) 49 | } 50 | for index, cmd := range s.cmds { 51 | if index == 0 { 52 | cmd.Stdin = s.Stdin 53 | } else { 54 | cmd.Stdin = rd 55 | } 56 | if index != length { 57 | rd, wr = io.Pipe() // create pipe 58 | cmd.Stdout = wr 59 | cmd.Stderr = os.Stderr 60 | } 61 | if index == length-1 { 62 | cmd.Stdout = s.Stdout 63 | cmd.Stderr = s.Stderr 64 | } 65 | err = cmd.Start() 66 | if err != nil { 67 | return 68 | } 69 | } 70 | return 71 | } 72 | 73 | // Should be call after Start() 74 | // only catch the last command error 75 | func (s *Session) Wait() (err error) { 76 | for _, cmd := range s.cmds { 77 | err = cmd.Wait() 78 | wr, ok := cmd.Stdout.(*io.PipeWriter) 79 | if ok { 80 | wr.Close() 81 | } 82 | } 83 | return err 84 | } 85 | 86 | func (s *Session) Kill(sig os.Signal) { 87 | for _, cmd := range s.cmds { 88 | if cmd.Process != nil { 89 | cmd.Process.Signal(sig) 90 | } 91 | } 92 | } 93 | 94 | func (s *Session) WaitTimeout(timeout time.Duration) (err error) { 95 | select { 96 | case <-time.After(timeout): 97 | s.Kill(syscall.SIGKILL) 98 | return ErrExecTimeout 99 | case err = <-Go(s.Wait): 100 | return err 101 | } 102 | } 103 | 104 | func Go(f func() error) chan error { 105 | ch := make(chan error) 106 | go func() { 107 | ch <- f() 108 | }() 109 | return ch 110 | } 111 | 112 | func (s *Session) Run() (err error) { 113 | if err = s.Start(); err != nil { 114 | return 115 | } 116 | if s.timeout != time.Duration(0) { 117 | return s.WaitTimeout(s.timeout) 118 | } 119 | return s.Wait() 120 | } 121 | 122 | func (s *Session) Output() (out []byte, err error) { 123 | oldout := s.Stdout 124 | defer func() { 125 | s.Stdout = oldout 126 | }() 127 | stdout := bytes.NewBuffer(nil) 128 | s.Stdout = stdout 129 | err = s.Run() 130 | out = stdout.Bytes() 131 | return 132 | } 133 | 134 | func (s *Session) CombinedOutput() (out []byte, err error) { 135 | oldout := s.Stdout 136 | olderr := s.Stderr 137 | defer func() { 138 | s.Stdout = oldout 139 | s.Stderr = olderr 140 | }() 141 | stdout := bytes.NewBuffer(nil) 142 | s.Stdout = stdout 143 | s.Stderr = stdout 144 | 145 | err = s.Run() 146 | out = stdout.Bytes() 147 | return 148 | } 149 | -------------------------------------------------------------------------------- /vendor/github.com/codeskyblue/go-sh/sh.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package go-sh is intented to make shell call with golang more easily. 3 | Some usage is more similar to os/exec, eg: Run(), Output(), Command(name, args...) 4 | 5 | But with these similar function, pipe is added in and this package also got shell-session support. 6 | 7 | Why I love golang so much, because the usage of golang is simple, but the power is unlimited. I want to make this pakcage got the sample style like golang. 8 | 9 | // just like os/exec 10 | sh.Command("echo", "hello").Run() 11 | 12 | // support pipe 13 | sh.Command("echo", "hello").Command("wc", "-c").Run() 14 | 15 | // create a session to store dir and env 16 | sh.NewSession().SetDir("/").Command("pwd") 17 | 18 | // shell buildin command - "test" 19 | sh.Test("dir", "mydir") 20 | 21 | // like shell call: (cd /; pwd) 22 | sh.Command("pwd", sh.Dir("/")) same with sh.Command(sh.Dir("/"), "pwd") 23 | 24 | // output to json and xml easily 25 | v := map[string] int {} 26 | err = sh.Command("echo", `{"number": 1}`).UnmarshalJSON(&v) 27 | */ 28 | package sh 29 | 30 | import ( 31 | "fmt" 32 | "io" 33 | "os" 34 | "os/exec" 35 | "reflect" 36 | "strings" 37 | "time" 38 | 39 | "github.com/codegangsta/inject" 40 | ) 41 | 42 | type Dir string 43 | 44 | type Session struct { 45 | inj inject.Injector 46 | alias map[string][]string 47 | cmds []*exec.Cmd 48 | dir Dir 49 | started bool 50 | Env map[string]string 51 | Stdin io.Reader 52 | Stdout io.Writer 53 | Stderr io.Writer 54 | ShowCMD bool // enable for debug 55 | timeout time.Duration 56 | } 57 | 58 | func (s *Session) writePrompt(args ...interface{}) { 59 | var ps1 = fmt.Sprintf("[golang-sh]$") 60 | args = append([]interface{}{ps1}, args...) 61 | fmt.Fprintln(s.Stderr, args...) 62 | } 63 | 64 | func NewSession() *Session { 65 | env := make(map[string]string) 66 | for _, key := range []string{"PATH"} { 67 | env[key] = os.Getenv(key) 68 | } 69 | s := &Session{ 70 | inj: inject.New(), 71 | alias: make(map[string][]string), 72 | dir: Dir(""), 73 | Stdin: strings.NewReader(""), 74 | Stdout: os.Stdout, 75 | Stderr: os.Stderr, 76 | Env: env, 77 | } 78 | return s 79 | } 80 | 81 | func Command(name string, a ...interface{}) *Session { 82 | s := NewSession() 83 | return s.Command(name, a...) 84 | } 85 | 86 | func Echo(in string) *Session { 87 | s := NewSession() 88 | return s.SetInput(in) 89 | } 90 | 91 | func (s *Session) Alias(alias, cmd string, args ...string) { 92 | v := []string{cmd} 93 | v = append(v, args...) 94 | s.alias[alias] = v 95 | } 96 | 97 | func (s *Session) Command(name string, a ...interface{}) *Session { 98 | var args = make([]string, 0) 99 | var sType = reflect.TypeOf("") 100 | 101 | // init cmd, args, dir, envs 102 | // if not init, program may panic 103 | s.inj.Map(name).Map(args).Map(s.dir).Map(map[string]string{}) 104 | for _, v := range a { 105 | switch reflect.TypeOf(v) { 106 | case sType: 107 | args = append(args, v.(string)) 108 | default: 109 | s.inj.Map(v) 110 | } 111 | } 112 | if len(args) != 0 { 113 | s.inj.Map(args) 114 | } 115 | s.inj.Invoke(s.appendCmd) 116 | return s 117 | } 118 | 119 | // combine Command and Run 120 | func (s *Session) Call(name string, a ...interface{}) error { 121 | return s.Command(name, a...).Run() 122 | } 123 | 124 | /* 125 | func (s *Session) Exec(cmd string, args ...string) error { 126 | return s.Call(cmd, args) 127 | } 128 | */ 129 | 130 | func (s *Session) SetEnv(key, value string) *Session { 131 | s.Env[key] = value 132 | return s 133 | } 134 | 135 | func (s *Session) SetDir(dir string) *Session { 136 | s.dir = Dir(dir) 137 | return s 138 | } 139 | 140 | func (s *Session) SetInput(in string) *Session { 141 | s.Stdin = strings.NewReader(in) 142 | return s 143 | } 144 | 145 | func (s *Session) SetStdin(r io.Reader) *Session { 146 | s.Stdin = r 147 | return s 148 | } 149 | 150 | func (s *Session) SetTimeout(d time.Duration) *Session { 151 | s.timeout = d 152 | return s 153 | } 154 | 155 | func newEnviron(env map[string]string, inherit bool) []string { //map[string]string { 156 | environ := make([]string, 0, len(env)) 157 | if inherit { 158 | for _, line := range os.Environ() { 159 | for k, _ := range env { 160 | if strings.HasPrefix(line, k+"=") { 161 | goto CONTINUE 162 | } 163 | } 164 | environ = append(environ, line) 165 | CONTINUE: 166 | } 167 | } 168 | for k, v := range env { 169 | environ = append(environ, k+"="+v) 170 | } 171 | return environ 172 | } 173 | 174 | func (s *Session) appendCmd(cmd string, args []string, cwd Dir, env map[string]string) { 175 | if s.started { 176 | s.started = false 177 | s.cmds = make([]*exec.Cmd, 0) 178 | } 179 | for k, v := range s.Env { 180 | if _, ok := env[k]; !ok { 181 | env[k] = v 182 | } 183 | } 184 | environ := newEnviron(s.Env, true) // true: inherit sys-env 185 | v, ok := s.alias[cmd] 186 | if ok { 187 | cmd = v[0] 188 | args = append(v[1:], args...) 189 | } 190 | c := exec.Command(cmd, args...) 191 | c.Env = environ 192 | c.Dir = string(cwd) 193 | s.cmds = append(s.cmds, c) 194 | } 195 | -------------------------------------------------------------------------------- /vendor/github.com/codeskyblue/go-sh/test.go: -------------------------------------------------------------------------------- 1 | package sh 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | ) 7 | 8 | func filetest(name string, modemask os.FileMode) (match bool, err error) { 9 | fi, err := os.Stat(name) 10 | if err != nil { 11 | return 12 | } 13 | match = (fi.Mode() & modemask) == modemask 14 | return 15 | } 16 | 17 | func (s *Session) pwd() string { 18 | dir := string(s.dir) 19 | if dir == "" { 20 | dir, _ = os.Getwd() 21 | } 22 | return dir 23 | } 24 | 25 | func (s *Session) abspath(name string) string { 26 | if filepath.IsAbs(name) { 27 | return name 28 | } 29 | return filepath.Join(s.pwd(), name) 30 | } 31 | 32 | func init() { 33 | //log.SetFlags(log.Lshortfile | log.LstdFlags) 34 | } 35 | 36 | // expression can be dir, file, link 37 | func (s *Session) Test(expression string, argument string) bool { 38 | var err error 39 | var fi os.FileInfo 40 | fi, err = os.Lstat(s.abspath(argument)) 41 | switch expression { 42 | case "d", "dir": 43 | return err == nil && fi.IsDir() 44 | case "f", "file": 45 | return err == nil && fi.Mode().IsRegular() 46 | case "x", "executable": 47 | /* 48 | fmt.Println(expression, argument) 49 | if err == nil { 50 | fmt.Println(fi.Mode()) 51 | } 52 | */ 53 | return err == nil && fi.Mode()&os.FileMode(0100) != 0 54 | case "L", "link": 55 | return err == nil && fi.Mode()&os.ModeSymlink != 0 56 | } 57 | return false 58 | } 59 | 60 | // expression can be d,dir, f,file, link 61 | func Test(exp string, arg string) bool { 62 | s := NewSession() 63 | return s.Test(exp, arg) 64 | } 65 | -------------------------------------------------------------------------------- /vendor/github.com/codeskyblue/go-sh/wercker.yml: -------------------------------------------------------------------------------- 1 | box: wercker/golang 2 | # Build definition 3 | build: 4 | # The steps that will be executed on build 5 | steps: 6 | # Sets the go workspace and places you package 7 | # at the right place in the workspace tree 8 | - setup-go-workspace 9 | 10 | # Gets the dependencies 11 | - script: 12 | name: go get 13 | code: | 14 | cd $WERCKER_SOURCE_DIR 15 | go version 16 | go get -t . 17 | 18 | # Build the project 19 | - script: 20 | name: go build 21 | code: | 22 | go build . 23 | 24 | # Test the project 25 | - script: 26 | name: go test 27 | code: | 28 | go test -v ./... 29 | -------------------------------------------------------------------------------- /vendor/github.com/gobuild/log/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | -------------------------------------------------------------------------------- /vendor/github.com/gobuild/log/README.md: -------------------------------------------------------------------------------- 1 | ## log 2 | [![GoDoc](https://godoc.org/github.com/gobuild/log?status.png)](https://godoc.org/github.com/gobuild/log) 3 | 4 | Extension module of golang logging, 5 | Most code came from [qiniu/log](https://github.com/qiniu/log) 6 | 7 | Improment: Add color support 8 | -------------------------------------------------------------------------------- /vendor/github.com/qiniu/log/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | -------------------------------------------------------------------------------- /vendor/github.com/qiniu/log/README.md: -------------------------------------------------------------------------------- 1 | log 2 | === 3 | 4 | Extension module of golang logging -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.4 5 | - 1.5 6 | - 1.6 7 | - tip 8 | 9 | go_import_path: gopkg.in/yaml.v2 10 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2011-2016 Canonical Ltd. 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 { 71 | RenamedC int `yaml:"c"` 72 | D []int `yaml:",flow"` 73 | } 74 | } 75 | 76 | func main() { 77 | t := T{} 78 | 79 | err := yaml.Unmarshal([]byte(data), &t) 80 | if err != nil { 81 | log.Fatalf("error: %v", err) 82 | } 83 | fmt.Printf("--- t:\n%v\n\n", t) 84 | 85 | d, err := yaml.Marshal(&t) 86 | if err != nil { 87 | log.Fatalf("error: %v", err) 88 | } 89 | fmt.Printf("--- t dump:\n%s\n\n", string(d)) 90 | 91 | m := make(map[interface{}]interface{}) 92 | 93 | err = yaml.Unmarshal([]byte(data), &m) 94 | if err != nil { 95 | log.Fatalf("error: %v", err) 96 | } 97 | fmt.Printf("--- m:\n%v\n\n", m) 98 | 99 | d, err = yaml.Marshal(&m) 100 | if err != nil { 101 | log.Fatalf("error: %v", err) 102 | } 103 | fmt.Printf("--- m dump:\n%s\n\n", string(d)) 104 | } 105 | ``` 106 | 107 | This example will generate the following output: 108 | 109 | ``` 110 | --- t: 111 | {Easy! {2 [3 4]}} 112 | 113 | --- t dump: 114 | a: Easy! 115 | b: 116 | c: 2 117 | d: [3, 4] 118 | 119 | 120 | --- m: 121 | map[a:Easy! b:map[c:2 d:[3 4]]] 122 | 123 | --- m dump: 124 | a: Easy! 125 | b: 126 | c: 2 127 | d: 128 | - 3 129 | - 4 130 | ``` 131 | 132 | -------------------------------------------------------------------------------- /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/readerc.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "io" 5 | ) 6 | 7 | // Set the reader error and return 0. 8 | func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool { 9 | parser.error = yaml_READER_ERROR 10 | parser.problem = problem 11 | parser.problem_offset = offset 12 | parser.problem_value = value 13 | return false 14 | } 15 | 16 | // Byte order marks. 17 | const ( 18 | bom_UTF8 = "\xef\xbb\xbf" 19 | bom_UTF16LE = "\xff\xfe" 20 | bom_UTF16BE = "\xfe\xff" 21 | ) 22 | 23 | // Determine the input stream encoding by checking the BOM symbol. If no BOM is 24 | // found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure. 25 | func yaml_parser_determine_encoding(parser *yaml_parser_t) bool { 26 | // Ensure that we had enough bytes in the raw buffer. 27 | for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 { 28 | if !yaml_parser_update_raw_buffer(parser) { 29 | return false 30 | } 31 | } 32 | 33 | // Determine the encoding. 34 | buf := parser.raw_buffer 35 | pos := parser.raw_buffer_pos 36 | avail := len(buf) - pos 37 | if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] { 38 | parser.encoding = yaml_UTF16LE_ENCODING 39 | parser.raw_buffer_pos += 2 40 | parser.offset += 2 41 | } else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] { 42 | parser.encoding = yaml_UTF16BE_ENCODING 43 | parser.raw_buffer_pos += 2 44 | parser.offset += 2 45 | } else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] { 46 | parser.encoding = yaml_UTF8_ENCODING 47 | parser.raw_buffer_pos += 3 48 | parser.offset += 3 49 | } else { 50 | parser.encoding = yaml_UTF8_ENCODING 51 | } 52 | return true 53 | } 54 | 55 | // Update the raw buffer. 56 | func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool { 57 | size_read := 0 58 | 59 | // Return if the raw buffer is full. 60 | if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) { 61 | return true 62 | } 63 | 64 | // Return on EOF. 65 | if parser.eof { 66 | return true 67 | } 68 | 69 | // Move the remaining bytes in the raw buffer to the beginning. 70 | if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) { 71 | copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:]) 72 | } 73 | parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos] 74 | parser.raw_buffer_pos = 0 75 | 76 | // Call the read handler to fill the buffer. 77 | size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)]) 78 | parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read] 79 | if err == io.EOF { 80 | parser.eof = true 81 | } else if err != nil { 82 | return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1) 83 | } 84 | return true 85 | } 86 | 87 | // Ensure that the buffer contains at least `length` characters. 88 | // Return true on success, false on failure. 89 | // 90 | // The length is supposed to be significantly less that the buffer size. 91 | func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool { 92 | if parser.read_handler == nil { 93 | panic("read handler must be set") 94 | } 95 | 96 | // If the EOF flag is set and the raw buffer is empty, do nothing. 97 | if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) { 98 | return true 99 | } 100 | 101 | // Return if the buffer contains enough characters. 102 | if parser.unread >= length { 103 | return true 104 | } 105 | 106 | // Determine the input encoding if it is not known yet. 107 | if parser.encoding == yaml_ANY_ENCODING { 108 | if !yaml_parser_determine_encoding(parser) { 109 | return false 110 | } 111 | } 112 | 113 | // Move the unread characters to the beginning of the buffer. 114 | buffer_len := len(parser.buffer) 115 | if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len { 116 | copy(parser.buffer, parser.buffer[parser.buffer_pos:]) 117 | buffer_len -= parser.buffer_pos 118 | parser.buffer_pos = 0 119 | } else if parser.buffer_pos == buffer_len { 120 | buffer_len = 0 121 | parser.buffer_pos = 0 122 | } 123 | 124 | // Open the whole buffer for writing, and cut it before returning. 125 | parser.buffer = parser.buffer[:cap(parser.buffer)] 126 | 127 | // Fill the buffer until it has enough characters. 128 | first := true 129 | for parser.unread < length { 130 | 131 | // Fill the raw buffer if necessary. 132 | if !first || parser.raw_buffer_pos == len(parser.raw_buffer) { 133 | if !yaml_parser_update_raw_buffer(parser) { 134 | parser.buffer = parser.buffer[:buffer_len] 135 | return false 136 | } 137 | } 138 | first = false 139 | 140 | // Decode the raw buffer. 141 | inner: 142 | for parser.raw_buffer_pos != len(parser.raw_buffer) { 143 | var value rune 144 | var width int 145 | 146 | raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos 147 | 148 | // Decode the next character. 149 | switch parser.encoding { 150 | case yaml_UTF8_ENCODING: 151 | // Decode a UTF-8 character. Check RFC 3629 152 | // (http://www.ietf.org/rfc/rfc3629.txt) for more details. 153 | // 154 | // The following table (taken from the RFC) is used for 155 | // decoding. 156 | // 157 | // Char. number range | UTF-8 octet sequence 158 | // (hexadecimal) | (binary) 159 | // --------------------+------------------------------------ 160 | // 0000 0000-0000 007F | 0xxxxxxx 161 | // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx 162 | // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx 163 | // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 164 | // 165 | // Additionally, the characters in the range 0xD800-0xDFFF 166 | // are prohibited as they are reserved for use with UTF-16 167 | // surrogate pairs. 168 | 169 | // Determine the length of the UTF-8 sequence. 170 | octet := parser.raw_buffer[parser.raw_buffer_pos] 171 | switch { 172 | case octet&0x80 == 0x00: 173 | width = 1 174 | case octet&0xE0 == 0xC0: 175 | width = 2 176 | case octet&0xF0 == 0xE0: 177 | width = 3 178 | case octet&0xF8 == 0xF0: 179 | width = 4 180 | default: 181 | // The leading octet is invalid. 182 | return yaml_parser_set_reader_error(parser, 183 | "invalid leading UTF-8 octet", 184 | parser.offset, int(octet)) 185 | } 186 | 187 | // Check if the raw buffer contains an incomplete character. 188 | if width > raw_unread { 189 | if parser.eof { 190 | return yaml_parser_set_reader_error(parser, 191 | "incomplete UTF-8 octet sequence", 192 | parser.offset, -1) 193 | } 194 | break inner 195 | } 196 | 197 | // Decode the leading octet. 198 | switch { 199 | case octet&0x80 == 0x00: 200 | value = rune(octet & 0x7F) 201 | case octet&0xE0 == 0xC0: 202 | value = rune(octet & 0x1F) 203 | case octet&0xF0 == 0xE0: 204 | value = rune(octet & 0x0F) 205 | case octet&0xF8 == 0xF0: 206 | value = rune(octet & 0x07) 207 | default: 208 | value = 0 209 | } 210 | 211 | // Check and decode the trailing octets. 212 | for k := 1; k < width; k++ { 213 | octet = parser.raw_buffer[parser.raw_buffer_pos+k] 214 | 215 | // Check if the octet is valid. 216 | if (octet & 0xC0) != 0x80 { 217 | return yaml_parser_set_reader_error(parser, 218 | "invalid trailing UTF-8 octet", 219 | parser.offset+k, int(octet)) 220 | } 221 | 222 | // Decode the octet. 223 | value = (value << 6) + rune(octet&0x3F) 224 | } 225 | 226 | // Check the length of the sequence against the value. 227 | switch { 228 | case width == 1: 229 | case width == 2 && value >= 0x80: 230 | case width == 3 && value >= 0x800: 231 | case width == 4 && value >= 0x10000: 232 | default: 233 | return yaml_parser_set_reader_error(parser, 234 | "invalid length of a UTF-8 sequence", 235 | parser.offset, -1) 236 | } 237 | 238 | // Check the range of the value. 239 | if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF { 240 | return yaml_parser_set_reader_error(parser, 241 | "invalid Unicode character", 242 | parser.offset, int(value)) 243 | } 244 | 245 | case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING: 246 | var low, high int 247 | if parser.encoding == yaml_UTF16LE_ENCODING { 248 | low, high = 0, 1 249 | } else { 250 | low, high = 1, 0 251 | } 252 | 253 | // The UTF-16 encoding is not as simple as one might 254 | // naively think. Check RFC 2781 255 | // (http://www.ietf.org/rfc/rfc2781.txt). 256 | // 257 | // Normally, two subsequent bytes describe a Unicode 258 | // character. However a special technique (called a 259 | // surrogate pair) is used for specifying character 260 | // values larger than 0xFFFF. 261 | // 262 | // A surrogate pair consists of two pseudo-characters: 263 | // high surrogate area (0xD800-0xDBFF) 264 | // low surrogate area (0xDC00-0xDFFF) 265 | // 266 | // The following formulas are used for decoding 267 | // and encoding characters using surrogate pairs: 268 | // 269 | // U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF) 270 | // U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF) 271 | // W1 = 110110yyyyyyyyyy 272 | // W2 = 110111xxxxxxxxxx 273 | // 274 | // where U is the character value, W1 is the high surrogate 275 | // area, W2 is the low surrogate area. 276 | 277 | // Check for incomplete UTF-16 character. 278 | if raw_unread < 2 { 279 | if parser.eof { 280 | return yaml_parser_set_reader_error(parser, 281 | "incomplete UTF-16 character", 282 | parser.offset, -1) 283 | } 284 | break inner 285 | } 286 | 287 | // Get the character. 288 | value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) + 289 | (rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8) 290 | 291 | // Check for unexpected low surrogate area. 292 | if value&0xFC00 == 0xDC00 { 293 | return yaml_parser_set_reader_error(parser, 294 | "unexpected low surrogate area", 295 | parser.offset, int(value)) 296 | } 297 | 298 | // Check for a high surrogate area. 299 | if value&0xFC00 == 0xD800 { 300 | width = 4 301 | 302 | // Check for incomplete surrogate pair. 303 | if raw_unread < 4 { 304 | if parser.eof { 305 | return yaml_parser_set_reader_error(parser, 306 | "incomplete UTF-16 surrogate pair", 307 | parser.offset, -1) 308 | } 309 | break inner 310 | } 311 | 312 | // Get the next character. 313 | value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) + 314 | (rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8) 315 | 316 | // Check for a low surrogate area. 317 | if value2&0xFC00 != 0xDC00 { 318 | return yaml_parser_set_reader_error(parser, 319 | "expected low surrogate area", 320 | parser.offset+2, int(value2)) 321 | } 322 | 323 | // Generate the value of the surrogate pair. 324 | value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF) 325 | } else { 326 | width = 2 327 | } 328 | 329 | default: 330 | panic("impossible") 331 | } 332 | 333 | // Check if the character is in the allowed range: 334 | // #x9 | #xA | #xD | [#x20-#x7E] (8 bit) 335 | // | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit) 336 | // | [#x10000-#x10FFFF] (32 bit) 337 | switch { 338 | case value == 0x09: 339 | case value == 0x0A: 340 | case value == 0x0D: 341 | case value >= 0x20 && value <= 0x7E: 342 | case value == 0x85: 343 | case value >= 0xA0 && value <= 0xD7FF: 344 | case value >= 0xE000 && value <= 0xFFFD: 345 | case value >= 0x10000 && value <= 0x10FFFF: 346 | default: 347 | return yaml_parser_set_reader_error(parser, 348 | "control characters are not allowed", 349 | parser.offset, int(value)) 350 | } 351 | 352 | // Move the raw pointers. 353 | parser.raw_buffer_pos += width 354 | parser.offset += width 355 | 356 | // Finally put the character into the buffer. 357 | if value <= 0x7F { 358 | // 0000 0000-0000 007F . 0xxxxxxx 359 | parser.buffer[buffer_len+0] = byte(value) 360 | buffer_len += 1 361 | } else if value <= 0x7FF { 362 | // 0000 0080-0000 07FF . 110xxxxx 10xxxxxx 363 | parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6)) 364 | parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F)) 365 | buffer_len += 2 366 | } else if value <= 0xFFFF { 367 | // 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx 368 | parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12)) 369 | parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F)) 370 | parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F)) 371 | buffer_len += 3 372 | } else { 373 | // 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 374 | parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18)) 375 | parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F)) 376 | parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F)) 377 | parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F)) 378 | buffer_len += 4 379 | } 380 | 381 | parser.unread++ 382 | } 383 | 384 | // On EOF, put NUL into the buffer and return. 385 | if parser.eof { 386 | parser.buffer[buffer_len] = 0 387 | buffer_len++ 388 | parser.unread++ 389 | break 390 | } 391 | } 392 | parser.buffer = parser.buffer[:buffer_len] 393 | return true 394 | } 395 | -------------------------------------------------------------------------------- /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/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/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/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 != "" && !field.Anonymous { 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /zip.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "archive/zip" 5 | "io" 6 | "os" 7 | ) 8 | 9 | type Zip struct { 10 | *zip.Writer 11 | } 12 | 13 | func CreateZip(filename string) (*Zip, error) { 14 | fd, err := os.Create(filename) 15 | if err != nil { 16 | return nil, err 17 | } 18 | zipper := zip.NewWriter(fd) 19 | return &Zip{Writer: zipper}, nil 20 | } 21 | 22 | func (z *Zip) Add(filename string) error { 23 | info, rdc, err := statFile(filename) 24 | if err != nil { 25 | return err 26 | } 27 | defer rdc.Close() 28 | 29 | hdr, err := zip.FileInfoHeader(info) 30 | if err != nil { 31 | return err 32 | } 33 | hdr.Name = sanitizedName(filename) 34 | if info.IsDir() { 35 | hdr.Name += "/" 36 | } 37 | hdr.Method = zip.Deflate // compress method 38 | writer, err := z.CreateHeader(hdr) 39 | if err != nil { 40 | return err 41 | } 42 | _, err = io.Copy(writer, rdc) 43 | return err 44 | } 45 | --------------------------------------------------------------------------------