├── .github └── workflows │ └── semgrep.yml ├── .gitignore ├── Godeps ├── Godeps.json └── Readme ├── LICENSE ├── README.md ├── debian └── control ├── docs ├── getting-started.md └── images │ └── cf-screenshot.png ├── src ├── admin.go ├── cli.go ├── deploy.go ├── rollback.go └── utils.go ├── utils ├── build.sh ├── create_site.sh ├── release.sh └── xc.sh └── vendor ├── github.com ├── cenk │ └── backoff │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── README.md │ │ ├── backoff.go │ │ ├── exponential.go │ │ ├── retry.go │ │ └── ticker.go ├── imdario │ └── mergo │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── README.md │ │ ├── doc.go │ │ ├── map.go │ │ ├── merge.go │ │ └── mergo.go ├── mitchellh │ └── go-homedir │ │ ├── LICENSE │ │ ├── README.md │ │ └── homedir.go ├── wsxiaoys │ └── terminal │ │ ├── LICENSE │ │ └── color │ │ └── color.go └── zackbloom │ ├── go-ini │ ├── .gitignore │ ├── README.md │ ├── decode.go │ └── stack.go │ └── goamz │ ├── LICENSE │ ├── aws │ ├── attempt.go │ ├── aws.go │ ├── client.go │ ├── regions.go │ ├── retry.go │ └── sign.go │ ├── cloudfront │ └── cloudfront.go │ ├── iam │ ├── iam.go │ └── sign.go │ ├── route53 │ └── route53.go │ └── s3 │ ├── lifecycle.go │ ├── multi.go │ ├── s3.go │ └── sign.go ├── golang.org └── x │ ├── crypto │ ├── LICENSE │ ├── PATENTS │ └── ssh │ │ └── terminal │ │ ├── terminal.go │ │ ├── util.go │ │ ├── util_bsd.go │ │ ├── util_linux.go │ │ ├── util_plan9.go │ │ └── util_windows.go │ └── net │ ├── LICENSE │ ├── PATENTS │ ├── html │ ├── atom │ │ ├── atom.go │ │ ├── gen.go │ │ └── table.go │ ├── const.go │ ├── doc.go │ ├── doctype.go │ ├── entity.go │ ├── escape.go │ ├── foreign.go │ ├── node.go │ ├── parse.go │ ├── render.go │ └── token.go │ └── publicsuffix │ ├── gen.go │ ├── list.go │ └── table.go └── gopkg.in └── yaml.v1 ├── 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 /.github/workflows/semgrep.yml: -------------------------------------------------------------------------------- 1 | on: 2 | pull_request: {} 3 | workflow_dispatch: {} 4 | push: 5 | branches: 6 | - main 7 | - master 8 | schedule: 9 | - cron: '0 0 * * *' 10 | name: Semgrep config 11 | jobs: 12 | semgrep: 13 | name: semgrep/ci 14 | runs-on: ubuntu-latest 15 | env: 16 | SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} 17 | SEMGREP_URL: https://cloudflare.semgrep.dev 18 | SEMGREP_APP_URL: https://cloudflare.semgrep.dev 19 | SEMGREP_VERSION_CHECK_URL: https://cloudflare.semgrep.dev/api/check-version 20 | container: 21 | image: semgrep/semgrep 22 | steps: 23 | - uses: actions/checkout@v4 24 | - run: semgrep ci 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | builds/ 3 | debian/ 4 | -------------------------------------------------------------------------------- /Godeps/Godeps.json: -------------------------------------------------------------------------------- 1 | { 2 | "ImportPath": "github.com/eagerio/stout", 3 | "GoVersion": "go1.6", 4 | "GodepVersion": "v63", 5 | "Packages": [ 6 | "./..." 7 | ], 8 | "Deps": [ 9 | { 10 | "ImportPath": "github.com/cenk/backoff", 11 | "Comment": "v1.0.0-7-gcdf48bb", 12 | "Rev": "cdf48bbc1eb78d1349cbda326a4a037f7ba565c6" 13 | }, 14 | { 15 | "ImportPath": "github.com/imdario/mergo", 16 | "Comment": "0.2.2-6-g50d4dbd", 17 | "Rev": "50d4dbd4eb0e84778abe37cefef140271d96fade" 18 | }, 19 | { 20 | "ImportPath": "github.com/mitchellh/go-homedir", 21 | "Rev": "1111e456ffea841564ac0fa5f69c26ef44dafec9" 22 | }, 23 | { 24 | "ImportPath": "github.com/wsxiaoys/terminal/color", 25 | "Rev": "0940f3fc43a0ed42d04916b1c04578462c650b09" 26 | }, 27 | { 28 | "ImportPath": "github.com/zackbloom/go-ini", 29 | "Rev": "3db81f263990ac57212cfdc3ce9a65e8af8af966" 30 | }, 31 | { 32 | "ImportPath": "github.com/zackbloom/goamz/aws", 33 | "Rev": "0f589c21f1937992b2952e1f4ce0d31f132b685d" 34 | }, 35 | { 36 | "ImportPath": "github.com/zackbloom/goamz/cloudfront", 37 | "Rev": "0f589c21f1937992b2952e1f4ce0d31f132b685d" 38 | }, 39 | { 40 | "ImportPath": "github.com/zackbloom/goamz/iam", 41 | "Rev": "0f589c21f1937992b2952e1f4ce0d31f132b685d" 42 | }, 43 | { 44 | "ImportPath": "github.com/zackbloom/goamz/route53", 45 | "Rev": "0f589c21f1937992b2952e1f4ce0d31f132b685d" 46 | }, 47 | { 48 | "ImportPath": "github.com/zackbloom/goamz/s3", 49 | "Rev": "0f589c21f1937992b2952e1f4ce0d31f132b685d" 50 | }, 51 | { 52 | "ImportPath": "golang.org/x/crypto/ssh/terminal", 53 | "Rev": "5bcd134fee4dd1475da17714aac19c0aa0142e2f" 54 | }, 55 | { 56 | "ImportPath": "golang.org/x/net/html", 57 | "Rev": "8a52c78636f6b7be1b1e5cb58b01a85f1e082659" 58 | }, 59 | { 60 | "ImportPath": "golang.org/x/net/html/atom", 61 | "Rev": "8a52c78636f6b7be1b1e5cb58b01a85f1e082659" 62 | }, 63 | { 64 | "ImportPath": "golang.org/x/net/publicsuffix", 65 | "Rev": "8a52c78636f6b7be1b1e5cb58b01a85f1e082659" 66 | }, 67 | { 68 | "ImportPath": "gopkg.in/yaml.v1", 69 | "Rev": "9f9df34309c04878acc86042b16630b0f696e1de" 70 | } 71 | ] 72 | } 73 | -------------------------------------------------------------------------------- /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 | Copyright (c) 2014 Eager Platform Co. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Package: stout 2 | Source: stout 3 | Version: v1.0.0 4 | Architecture: all 5 | Maintainer: Zack Bloom 6 | Description: The Reliable Static Deploy Tool 7 | -------------------------------------------------------------------------------- /docs/getting-started.md: -------------------------------------------------------------------------------- 1 | ### Setting Up Your Site 2 | 3 | If you don't already have an S3-hosted site, start here. 4 | 5 | We're going to create a basic site config which uses CloudFront's CDN to deliver high performance at a minimal cost. Once you run the setup, you'll end up with a configuration which looks like this: 6 | 7 | ``` 8 | The Deploy Tool -> S3 <- CloudFront's Global CDN <- DNS <- Your Users 9 | ``` 10 | 11 | The simplest way to get started is to run the `create_site.sh` script in the utils folder. After installing the [aws command line tools](http://aws.amazon.com/cli/), run: 12 | 13 | ```bash 14 | ./utils/create_site.sh subdomain.my-site.com 15 | ``` 16 | 17 | Feel free to leave out the subdomain if you'd like to host it at the root of your domain. 18 | 19 | This will: 20 | 21 | - Create an S3 bucket for this site with the correct security policy and website hosting 22 | - Create a CloudFront distribution pointed at that bucket 23 | - Create a user with the appropriate permissions to upload to that bucket 24 | - Create an access key for that user 25 | 26 | Once that's done, copy the access key, secret key (from the JSON blob the access key request spits out) and bucket (the bucket's name is just the url you provided) it printed to your `deploy.yaml`, or save them to use with the `stout deploy` as arguments. 27 | 28 | The final step is to point your DNS records to the new CloudFront distribution. If you use Route 53 you want to create an alias to the distribution (it will be named the same as the new domain). If you use another DNS service, you'll want to create a CNAME to the CloudFront distribution's hostname. 29 | 30 | Please note that it will take up to twenty minutes for the CloudFront distribution to initialize. Additionally it may take some time for your DNS records to update. 31 | 32 | If you'd like development or staging environments, just run the command again with the URL you'd like them to have, and add the new credentials as before. See the "YAML Config" section of the README for an example of how to configure multiple environments. 33 | 34 | Be very careful to never commit a file to a public repo that contains your AWS credentials. If you are deploying a public repo, either keep the credentials on your local machine you deploy from, or in the build service (like CircleCI) you're using. 35 | 36 | #### Step-by-step Instructions 37 | 38 | 1. Install Amazon's AWS Command-Line Tools (and create an AWS account if you don't have one) 39 | 1. Run the `create_site.sh` tool with the URL of the site you'd like to deploy 40 | 1. Take note of the AWS key and secret in the final JSON blob outputted by the script 41 | 1. Download the executable from this project 42 | 1. Run `stout deploy --bucket subdomain.your-site.com --key YOUR_NEW_AWS_KEY --secret YOUR_NEW_AWS_SECRET` to deploy 43 | 1. Add the `--root` argument if your built files are in a subdirectory. 44 | 1. Visit the cloudfront url of your new distribution to see how your site currently looks, include any new files you may have missed and deploy again 45 | 1. Optionally, Move any configuration options you don't mind being committed to your repository to a deploy.yaml file 46 | 1. Optionally, Run `create_site.sh` again to create staging or development sites, and add their configuration to your deploy.yaml as well 47 | 1. Optionally, Deploy more projects to this same site by running deploy with the `--dest` argument 48 | 1. Optionally, Add the deploy step to your build tool 49 | -------------------------------------------------------------------------------- /docs/images/cf-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudflare/Stout/e50d63a2f52305e9436afdbe0b74188ea543f531/docs/images/cf-screenshot.png -------------------------------------------------------------------------------- /src/cli.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | ) 7 | 8 | func printUsage() { 9 | fmt.Println(`Stout Static Deploy Tool 10 | Supports three commands, create, deploy and rollback. 11 | 12 | Example Usage: 13 | 14 | To create a site which will be hosted at my.awesome.website: 15 | 16 | stout create --bucket my.awesome.website --key AWS_KEY --secret AWS_SECRET 17 | 18 | To deploy the current folder to the root of the my.awesome.website site: 19 | 20 | stout deploy --bucket my.awesome.website --key AWS_KEY --secret AWS_SECRET 21 | 22 | To rollback to a specific deploy: 23 | 24 | stout rollback --bucket my.awesome.website --key AWS_KEY --secret AWS_SECRET c4a22bf94de1 25 | 26 | See the README for more configuration information. 27 | `) 28 | } 29 | 30 | func main() { 31 | flag.Parse() 32 | 33 | command := flag.Arg(0) 34 | 35 | switch command { 36 | case "help": 37 | printUsage() 38 | case "deploy": 39 | deployCmd() 40 | case "rollback": 41 | rollbackCmd() 42 | case "create": 43 | createCmd() 44 | default: 45 | fmt.Println("Command not understood") 46 | fmt.Println("") 47 | printUsage() 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/rollback.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "path/filepath" 7 | "sync" 8 | 9 | "github.com/zackbloom/goamz/s3" 10 | ) 11 | 12 | func Rollback(options Options, version string) { 13 | if s3Session == nil { 14 | s3Session = openS3(options.AWSKey, options.AWSSecret, options.AWSRegion, options.S3Host) 15 | } 16 | 17 | bucket := s3Session.Bucket(options.Bucket) 18 | 19 | // List files with the correct prefix in bucket 20 | // Remove their prefix with a copy. 21 | 22 | prefix := filepath.Join(options.Dest, version) + "/" 23 | 24 | list, err := bucket.List(prefix, "", "", 1000) 25 | panicIf(err) 26 | 27 | if list.IsTruncated { 28 | panic(fmt.Sprintf("More than %d HTML files in version, rollback is not supported. Consider filing a GitHub issue if you need support for this.", list.MaxKeys)) 29 | } 30 | if len(list.Contents) == 0 { 31 | log.Printf("A deploy with the provided id (%s) was not found in the specified bucket", version) 32 | return 33 | } 34 | 35 | wg := sync.WaitGroup{} 36 | 37 | count := 0 38 | for _, file := range list.Contents { 39 | wg.Add(1) 40 | go func(file s3.Key) { 41 | defer wg.Done() 42 | 43 | path := file.Key 44 | if filepath.Ext(path) != ".html" { 45 | log.Printf("Skipping non-html file %s", path) 46 | return 47 | } 48 | 49 | newPath := filepath.Join(options.Dest, path[len(prefix):]) 50 | 51 | log.Printf("Aliasing %s to %s", path, newPath) 52 | 53 | copyFile(bucket, path, newPath, "text/html", LIMITED) 54 | 55 | count++ 56 | }(file) 57 | } 58 | 59 | wg.Wait() 60 | 61 | log.Printf("Reverted %d HTML files to version %s", count, version) 62 | } 63 | 64 | func rollbackCmd() { 65 | options, set := parseOptions() 66 | version := set.Arg(0) 67 | 68 | loadConfigFile(&options) 69 | addAWSConfig(&options) 70 | 71 | if options.Bucket == "" { 72 | panic("You must specify a bucket") 73 | } 74 | if options.AWSKey == "" || options.AWSSecret == "" { 75 | panic("You must specify your AWS credentials") 76 | } 77 | if version == "" { 78 | panic("You must specify a version to rollback to") 79 | } 80 | 81 | Rollback(options, version) 82 | } 83 | -------------------------------------------------------------------------------- /src/utils.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "io/ioutil" 7 | "log" 8 | "os" 9 | "path/filepath" 10 | "regexp" 11 | "strings" 12 | 13 | "github.com/imdario/mergo" 14 | homedir "github.com/mitchellh/go-homedir" 15 | ini "github.com/sspencer/go-ini" 16 | "github.com/zackbloom/goamz/aws" 17 | "github.com/zackbloom/goamz/cloudfront" 18 | "github.com/zackbloom/goamz/iam" 19 | "github.com/zackbloom/goamz/route53" 20 | "github.com/zackbloom/goamz/s3" 21 | "gopkg.in/yaml.v1" 22 | ) 23 | 24 | const ( 25 | LIMITED = 60 26 | FOREVER = 31556926 27 | ) 28 | 29 | var s3Session *s3.S3 30 | var iamSession *iam.IAM 31 | var r53Session *route53.Route53 32 | var cfSession *cloudfront.CloudFront 33 | 34 | func getRegion(region string, s3Host string) aws.Region { 35 | regionS, ok := aws.Regions[region] 36 | if !ok { 37 | panic("Region not found") 38 | } 39 | 40 | log.Println("HOST", s3Host) 41 | if s3Host != "" { 42 | regionS.S3Endpoint = "https://" + s3Host 43 | regionS.S3BucketEndpoint = "https://${bucket}." + s3Host 44 | } 45 | return regionS 46 | } 47 | 48 | func openS3(key, secret, region, s3Host string) *s3.S3 { 49 | regionS := getRegion(region, s3Host) 50 | 51 | auth := aws.Auth{ 52 | AccessKey: key, 53 | SecretKey: secret, 54 | } 55 | return s3.New(auth, regionS) 56 | } 57 | 58 | func openIAM(key, secret, region string) *iam.IAM { 59 | regionS := getRegion(region, "") 60 | 61 | auth := aws.Auth{ 62 | AccessKey: key, 63 | SecretKey: secret, 64 | } 65 | return iam.New(auth, regionS) 66 | } 67 | 68 | func openCloudFront(key, secret string) *cloudfront.CloudFront { 69 | auth := aws.Auth{ 70 | AccessKey: key, 71 | SecretKey: secret, 72 | } 73 | return cloudfront.NewCloudFront(auth) 74 | } 75 | 76 | func openRoute53(key, secret string) *route53.Route53 { 77 | auth := aws.Auth{ 78 | AccessKey: key, 79 | SecretKey: secret, 80 | } 81 | 82 | r53, _ := route53.NewRoute53(auth) 83 | return r53 84 | } 85 | 86 | func panicIf(err error) { 87 | if err != nil { 88 | panic(err) 89 | } 90 | } 91 | func must(val interface{}, err error) interface{} { 92 | if err != nil { 93 | panic(err) 94 | } 95 | 96 | return val 97 | } 98 | func mustString(val string, err error) string { 99 | panicIf(err) 100 | return val 101 | } 102 | func mustInt(val int, err error) int { 103 | panicIf(err) 104 | return val 105 | } 106 | 107 | type Options struct { 108 | Files string `yaml:"files"` 109 | Root string `yaml:"root"` 110 | Dest string `yaml:"dest"` 111 | ConfigFile string `yaml:"-"` 112 | Env string `yaml:"-"` 113 | Bucket string `yaml:"bucket"` 114 | AWSKey string `yaml:"key"` 115 | AWSSecret string `yaml:"secret"` 116 | AWSRegion string `yaml:"region"` 117 | S3Host string `yaml:"s3Host"` 118 | NoUser bool `yaml:"-"` 119 | } 120 | 121 | func parseOptions() (o Options, set *flag.FlagSet) { 122 | set = flag.NewFlagSet(os.Args[1], flag.ExitOnError) 123 | //TODO: Set set.Usage 124 | 125 | set.StringVar(&o.Files, "files", "*", "Comma-seperated glob patterns of files to deploy (within root)") 126 | set.StringVar(&o.Root, "root", "./", "The local directory to deploy") 127 | set.StringVar(&o.Dest, "dest", "./", "The destination directory to write files to in the S3 bucket") 128 | set.StringVar(&o.ConfigFile, "config", "", "A yaml file to read configuration from") 129 | set.StringVar(&o.Env, "env", "", "The env to read from the config file") 130 | set.StringVar(&o.Bucket, "bucket", "", "The bucket to deploy to") 131 | set.StringVar(&o.AWSKey, "key", "", "The AWS key to use") 132 | set.StringVar(&o.AWSSecret, "secret", "", "The AWS secret of the provided key") 133 | set.StringVar(&o.AWSRegion, "region", "us-east-1", "The AWS region the S3 bucket is in") 134 | set.StringVar(&o.S3Host, "s3-host", "s3.amazonaws.com", "The hostname of an S3 implementation, overrides region") 135 | set.BoolVar(&o.NoUser, "no-user", false, "When creating, should we make a user account?") 136 | 137 | set.Parse(os.Args[2:]) 138 | 139 | return 140 | } 141 | 142 | type ConfigFile map[string]Options 143 | 144 | func loadConfigFile(o *Options) { 145 | isDefault := false 146 | configPath := o.ConfigFile 147 | if o.ConfigFile == "" { 148 | isDefault = true 149 | configPath = "./deploy.yaml" 150 | } 151 | 152 | data, err := ioutil.ReadFile(configPath) 153 | if err != nil { 154 | if os.IsNotExist(err) && isDefault { 155 | return 156 | } 157 | 158 | panic(err) 159 | } 160 | 161 | var file ConfigFile 162 | err = yaml.Unmarshal(data, &file) 163 | panicIf(err) 164 | 165 | var envCfg Options 166 | if o.Env != "" { 167 | var ok bool 168 | envCfg, ok = file[o.Env] 169 | if !ok { 170 | panic("Config for specified env not found") 171 | } 172 | } 173 | 174 | defCfg, _ := file["default"] 175 | 176 | panicIf(mergo.MergeWithOverwrite(o, defCfg)) 177 | panicIf(mergo.MergeWithOverwrite(o, envCfg)) 178 | } 179 | 180 | func addAWSConfig(o *Options) { 181 | if o.AWSKey == "" && o.AWSSecret == "" { 182 | o.AWSKey, o.AWSSecret = loadAWSConfig() 183 | } 184 | } 185 | 186 | type AWSConfig struct { 187 | Default struct { 188 | AccessKey string `ini:"aws_access_key_id"` 189 | SecretKey string `ini:"aws_secret_access_key"` 190 | } `ini:"[default]"` 191 | } 192 | 193 | func loadAWSConfig() (access string, secret string) { 194 | cfg := AWSConfig{} 195 | 196 | for _, file := range []string{"~/.aws/config", "~/.aws/credentials"} { 197 | path, err := homedir.Expand(file) 198 | if err != nil { 199 | continue 200 | } 201 | 202 | content, err := ioutil.ReadFile(path) 203 | if err != nil { 204 | continue 205 | } 206 | 207 | ini.Unmarshal(content, &cfg) 208 | 209 | if cfg.Default.AccessKey != "" { 210 | break 211 | } 212 | } 213 | 214 | return cfg.Default.AccessKey, cfg.Default.SecretKey 215 | } 216 | 217 | func copyFile(bucket *s3.Bucket, from string, to string, contentType string, maxAge int) { 218 | copyOpts := s3.CopyOptions{ 219 | MetadataDirective: "REPLACE", 220 | ContentType: contentType, 221 | Options: s3.Options{ 222 | CacheControl: fmt.Sprintf("public, max-age=%d", maxAge), 223 | ContentEncoding: "gzip", 224 | }, 225 | } 226 | 227 | _, err := bucket.PutCopy(to, s3.PublicRead, copyOpts, joinPath(bucket.Name, from)) 228 | if err != nil { 229 | panic(err) 230 | } 231 | } 232 | 233 | var pathRe = regexp.MustCompile("/{2,}") 234 | 235 | func joinPath(parts ...string) string { 236 | // Like filepath.Join, but always uses '/' 237 | out := filepath.Join(parts...) 238 | 239 | if os.PathSeparator != '/' { 240 | out = strings.Replace(out, string(os.PathSeparator), "/", -1) 241 | } 242 | 243 | return out 244 | } 245 | -------------------------------------------------------------------------------- /utils/build.sh: -------------------------------------------------------------------------------- 1 | GOOS=linux GOARCH=amd64 go build -o stout-linux src/* 2 | GOOS=darwin GOARCH=amd64 go build -o stout-osx src/* 3 | GOOS=windows GOARCH=amd64 go build -o stout-windows.exe src/* 4 | -------------------------------------------------------------------------------- /utils/create_site.sh: -------------------------------------------------------------------------------- 1 | #set -e 2 | 3 | export HOST=$1 4 | export DEPLOY_USER=${HOST}_deploy 5 | 6 | aws s3 mb s3://$HOST --region us-east-1 7 | 8 | aws s3 website s3://$HOST --index-document index.html --error-document error.html 9 | 10 | aws s3api put-bucket-policy --bucket $HOST --policy "{ 11 | \"Version\": \"2008-10-17\", 12 | \"Statement\": [ 13 | { 14 | \"Sid\": \"PublicReadForGetBucketObjects\", 15 | \"Effect\": \"Allow\", 16 | \"Principal\": { 17 | \"AWS\": \"*\" 18 | }, 19 | \"Action\": \"s3:GetObject\", 20 | \"Resource\": \"arn:aws:s3:::$HOST/*\" 21 | } 22 | ] 23 | }" 24 | 25 | export CALLER=`date +"%T"` 26 | 27 | aws cloudfront create-distribution --distribution-config " 28 | { 29 | \"CallerReference\": \"$CALLER\", 30 | \"Comment\": null, 31 | \"CacheBehaviors\": { 32 | \"Quantity\": 0 33 | }, 34 | \"Logging\": { 35 | \"Bucket\": null, 36 | \"Prefix\": null, 37 | \"Enabled\": false, 38 | \"IncludeCookies\": false 39 | }, 40 | \"Origins\": { 41 | \"Items\": [ 42 | { 43 | \"S3OriginConfig\": { 44 | \"OriginAccessIdentity\": null 45 | }, 46 | \"Id\": \"S3-$HOST\", 47 | \"DomainName\": \"$HOST.s3.amazonaws.com\" 48 | } 49 | ], 50 | \"Quantity\": 1 51 | }, 52 | \"DefaultRootObject\": \"index.html\", 53 | \"PriceClass\": \"PriceClass_All\", 54 | \"Enabled\": true, 55 | \"DefaultCacheBehavior\": { 56 | \"TrustedSigners\": { 57 | \"Enabled\": false, 58 | \"Quantity\": 0 59 | }, 60 | \"TargetOriginId\": \"S3-$HOST\", 61 | \"ViewerProtocolPolicy\": \"allow-all\", 62 | \"ForwardedValues\": { 63 | \"Cookies\": { 64 | \"Forward\": \"none\" 65 | }, 66 | \"QueryString\": false 67 | }, 68 | \"AllowedMethods\": { 69 | \"Items\": [ 70 | \"GET\", 71 | \"HEAD\" 72 | ], 73 | \"Quantity\": 2 74 | }, 75 | \"MinTTL\": 0 76 | }, 77 | \"ViewerCertificate\": { 78 | \"CloudFrontDefaultCertificate\": true 79 | }, 80 | \"CustomErrorResponses\": { 81 | \"Quantity\": 0 82 | }, 83 | \"Restrictions\": { 84 | \"GeoRestriction\": { 85 | \"RestrictionType\": \"none\", 86 | \"Quantity\": 0 87 | } 88 | }, 89 | \"Aliases\": { 90 | \"Items\": [ 91 | \"$HOST\" 92 | ], 93 | \"Quantity\": 1 94 | } 95 | }" 96 | 97 | aws iam create-user --user-name $DEPLOY_USER 98 | aws iam put-user-policy --user-name $DEPLOY_USER --policy-name $DEPLOY_USER --policy-document "{ 99 | \"Version\": \"2012-10-17\", 100 | \"Statement\": [ 101 | { 102 | \"Effect\": \"Allow\", 103 | \"Action\": [ 104 | \"s3:DeleteObject\", 105 | \"s3:ListBucket\", 106 | \"s3:PutObject\", 107 | \"s3:PutObjectAcl\", 108 | \"s3:GetObject\" 109 | ], 110 | \"Resource\": [ 111 | \"arn:aws:s3:::$HOST\", \"arn:aws:s3:::$HOST/*\" 112 | ] 113 | } 114 | ] 115 | }" 116 | 117 | aws iam create-access-key --user-name $DEPLOY_USER | cat 118 | 119 | echo "Select a SSL Cert in CloudFront if applicable" 120 | 121 | echo "Site set up. You must now manually add the cloudfront distribution to your DNS configuration." 122 | -------------------------------------------------------------------------------- /utils/release.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | # Install jq with brew install jq 4 | 5 | RELEASE=$1 6 | 7 | git tag $RELEASE 8 | git push origin master --tags 9 | 10 | UPLOAD_URL=$(curl -X POST "https://api.github.com/repos/EagerIO/Stout/releases" \ 11 | -H "Accept: application/vnd.github.v3+json" \ 12 | -H "Authorization: token $GITHUB_AUTH" \ 13 | -H "Content-Type: application/json" \ 14 | -d " 15 | { 16 | \"tag_name\": \"$RELEASE\" 17 | }" | jq -r '.upload_url' | cut -d { -f 1) 18 | 19 | mkdir -p debian 20 | 21 | echo " 22 | Package: stout 23 | Source: stout 24 | Version: $RELEASE 25 | Architecture: all 26 | Maintainer: Zack Bloom 27 | Description: The reliable static website deploy tool 28 | " > `dirname $0`/../control 29 | 30 | `dirname $0`/xc.sh 31 | 32 | upload () { 33 | local archive=$1 34 | local filename=$(basename "$archive") 35 | local extension="${filename##*.}" 36 | 37 | if [ "$extension" == "md" ]; then 38 | return 39 | fi 40 | 41 | curl -X POST "$UPLOAD_URL?name=$filename" \ 42 | -H "Content-Type: application/octet-stream" \ 43 | -H "Authorization: token $GITHUB_AUTH" \ 44 | --data-binary @$archive 45 | } 46 | 47 | for f in builds/snapshot/*; do upload "$f" & done 48 | 49 | wait 50 | -------------------------------------------------------------------------------- /utils/xc.sh: -------------------------------------------------------------------------------- 1 | goxc -tasks-=downloads-page -d=./builds 2 | -------------------------------------------------------------------------------- /vendor/github.com/cenk/backoff/.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/cenk/backoff/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.3.3 4 | - tip 5 | before_install: 6 | - go get github.com/mattn/goveralls 7 | - go get golang.org/x/tools/cmd/cover 8 | script: 9 | - $HOME/gopath/bin/goveralls -service=travis-ci 10 | -------------------------------------------------------------------------------- /vendor/github.com/cenk/backoff/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Cenk Altı 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/cenk/backoff/README.md: -------------------------------------------------------------------------------- 1 | # Exponential Backoff [![GoDoc][godoc image]][godoc] [![Build Status][travis image]][travis] [![Coverage Status][coveralls image]][coveralls] 2 | 3 | This is a Go port of the exponential backoff algorithm from [Google's HTTP Client Library for Java][google-http-java-client]. 4 | 5 | [Exponential backoff][exponential backoff wiki] 6 | is an algorithm that uses feedback to multiplicatively decrease the rate of some process, 7 | in order to gradually find an acceptable rate. 8 | The retries exponentially increase and stop increasing when a certain threshold is met. 9 | 10 | ## How To 11 | 12 | We define two functions, `Retry()` and `RetryNotify()`. 13 | They receive an `Operation` to execute, a `BackOff` algorithm, 14 | and an optional `Notify` error handler. 15 | 16 | The operation will be executed, and will be retried on failure with delay 17 | as given by the backoff algorithm. The backoff algorithm can also decide when to stop 18 | retrying. 19 | In addition, the notify error handler will be called after each failed attempt, 20 | except for the last time, whose error should be handled by the caller. 21 | 22 | ```go 23 | // An Operation is executing by Retry() or RetryNotify(). 24 | // The operation will be retried using a backoff policy if it returns an error. 25 | type Operation func() error 26 | 27 | // Notify is a notify-on-error function. It receives an operation error and 28 | // backoff delay if the operation failed (with an error). 29 | // 30 | // NOTE that if the backoff policy stated to stop retrying, 31 | // the notify function isn't called. 32 | type Notify func(error, time.Duration) 33 | 34 | func Retry(Operation, BackOff) error 35 | func RetryNotify(Operation, BackOff, Notify) 36 | ``` 37 | 38 | ## Examples 39 | 40 | ### Retry 41 | 42 | Simple retry helper that uses the default exponential backoff algorithm: 43 | 44 | ```go 45 | operation := func() error { 46 | // An operation that might fail. 47 | return nil // or return errors.New("some error") 48 | } 49 | 50 | err := Retry(operation, NewExponentialBackOff()) 51 | if err != nil { 52 | // Handle error. 53 | return err 54 | } 55 | 56 | // Operation is successful. 57 | return nil 58 | ``` 59 | 60 | ### Ticker 61 | 62 | Ticker is for using backoff algorithms with channels. 63 | 64 | ```go 65 | operation := func() error { 66 | // An operation that might fail 67 | return nil // or return errors.New("some error") 68 | } 69 | 70 | b := NewExponentialBackOff() 71 | ticker := NewTicker(b) 72 | 73 | var err error 74 | 75 | // Ticks will continue to arrive when the previous operation is still running, 76 | // so operations that take a while to fail could run in quick succession. 77 | for range ticker.C { 78 | if err = operation(); err != nil { 79 | log.Println(err, "will retry...") 80 | continue 81 | } 82 | 83 | ticker.Stop() 84 | break 85 | } 86 | 87 | if err != nil { 88 | // Operation has failed. 89 | return err 90 | } 91 | 92 | // Operation is successful. 93 | return nil 94 | ``` 95 | 96 | ## Getting Started 97 | 98 | ```bash 99 | # install 100 | $ go get github.com/cenk/backoff 101 | 102 | # test 103 | $ cd $GOPATH/src/github.com/cenk/backoff 104 | $ go get -t ./... 105 | $ go test -v -cover 106 | ``` 107 | 108 | [godoc]: https://godoc.org/github.com/cenk/backoff 109 | [godoc image]: https://godoc.org/github.com/cenk/backoff?status.png 110 | [travis]: https://travis-ci.org/cenk/backoff 111 | [travis image]: https://travis-ci.org/cenk/backoff.png?branch=master 112 | [coveralls]: https://coveralls.io/github/cenk/backoff?branch=master 113 | [coveralls image]: https://coveralls.io/repos/github/cenk/backoff/badge.svg?branch=master 114 | 115 | [google-http-java-client]: https://github.com/google/google-http-java-client 116 | [exponential backoff wiki]: http://en.wikipedia.org/wiki/Exponential_backoff 117 | 118 | [advanced example]: https://godoc.org/github.com/cenk/backoff#example_ 119 | -------------------------------------------------------------------------------- /vendor/github.com/cenk/backoff/backoff.go: -------------------------------------------------------------------------------- 1 | // Package backoff implements backoff algorithms for retrying operations. 2 | // 3 | // Also has a Retry() helper for retrying operations that may fail. 4 | package backoff 5 | 6 | import "time" 7 | 8 | // BackOff is a backoff policy for retrying an operation. 9 | type BackOff interface { 10 | // NextBackOff returns the duration to wait before retrying the operation, 11 | // or backoff.Stop to indicate that no more retries should be made. 12 | // 13 | // Example usage: 14 | // 15 | // duration := backoff.NextBackOff(); 16 | // if (duration == backoff.Stop) { 17 | // // Do not retry operation. 18 | // } else { 19 | // // Sleep for duration and retry operation. 20 | // } 21 | // 22 | NextBackOff() time.Duration 23 | 24 | // Reset to initial state. 25 | Reset() 26 | } 27 | 28 | // Indicates that no more retries should be made for use in NextBackOff(). 29 | const Stop time.Duration = -1 30 | 31 | // ZeroBackOff is a fixed backoff policy whose backoff time is always zero, 32 | // meaning that the operation is retried immediately without waiting, indefinitely. 33 | type ZeroBackOff struct{} 34 | 35 | func (b *ZeroBackOff) Reset() {} 36 | 37 | func (b *ZeroBackOff) NextBackOff() time.Duration { return 0 } 38 | 39 | // StopBackOff is a fixed backoff policy that always returns backoff.Stop for 40 | // NextBackOff(), meaning that the operation should never be retried. 41 | type StopBackOff struct{} 42 | 43 | func (b *StopBackOff) Reset() {} 44 | 45 | func (b *StopBackOff) NextBackOff() time.Duration { return Stop } 46 | 47 | // ConstantBackOff is a backoff policy that always returns the same backoff delay. 48 | // This is in contrast to an exponential backoff policy, 49 | // which returns a delay that grows longer as you call NextBackOff() over and over again. 50 | type ConstantBackOff struct { 51 | Interval time.Duration 52 | } 53 | 54 | func (b *ConstantBackOff) Reset() {} 55 | func (b *ConstantBackOff) NextBackOff() time.Duration { return b.Interval } 56 | 57 | func NewConstantBackOff(d time.Duration) *ConstantBackOff { 58 | return &ConstantBackOff{Interval: d} 59 | } 60 | -------------------------------------------------------------------------------- /vendor/github.com/cenk/backoff/exponential.go: -------------------------------------------------------------------------------- 1 | package backoff 2 | 3 | import ( 4 | "math/rand" 5 | "time" 6 | ) 7 | 8 | /* 9 | ExponentialBackOff is a backoff implementation that increases the backoff 10 | period for each retry attempt using a randomization function that grows exponentially. 11 | 12 | NextBackOff() is calculated using the following formula: 13 | 14 | randomized interval = 15 | RetryInterval * (random value in range [1 - RandomizationFactor, 1 + RandomizationFactor]) 16 | 17 | In other words NextBackOff() will range between the randomization factor 18 | percentage below and above the retry interval. 19 | 20 | For example, given the following parameters: 21 | 22 | RetryInterval = 2 23 | RandomizationFactor = 0.5 24 | Multiplier = 2 25 | 26 | the actual backoff period used in the next retry attempt will range between 1 and 3 seconds, 27 | multiplied by the exponential, that is, between 2 and 6 seconds. 28 | 29 | Note: MaxInterval caps the RetryInterval and not the randomized interval. 30 | 31 | If the time elapsed since an ExponentialBackOff instance is created goes past the 32 | MaxElapsedTime, then the method NextBackOff() starts returning backoff.Stop. 33 | 34 | The elapsed time can be reset by calling Reset(). 35 | 36 | Example: Given the following default arguments, for 10 tries the sequence will be, 37 | and assuming we go over the MaxElapsedTime on the 10th try: 38 | 39 | Request # RetryInterval (seconds) Randomized Interval (seconds) 40 | 41 | 1 0.5 [0.25, 0.75] 42 | 2 0.75 [0.375, 1.125] 43 | 3 1.125 [0.562, 1.687] 44 | 4 1.687 [0.8435, 2.53] 45 | 5 2.53 [1.265, 3.795] 46 | 6 3.795 [1.897, 5.692] 47 | 7 5.692 [2.846, 8.538] 48 | 8 8.538 [4.269, 12.807] 49 | 9 12.807 [6.403, 19.210] 50 | 10 19.210 backoff.Stop 51 | 52 | Note: Implementation is not thread-safe. 53 | */ 54 | type ExponentialBackOff struct { 55 | InitialInterval time.Duration 56 | RandomizationFactor float64 57 | Multiplier float64 58 | MaxInterval time.Duration 59 | // After MaxElapsedTime the ExponentialBackOff stops. 60 | // It never stops if MaxElapsedTime == 0. 61 | MaxElapsedTime time.Duration 62 | Clock Clock 63 | 64 | currentInterval time.Duration 65 | startTime time.Time 66 | } 67 | 68 | // Clock is an interface that returns current time for BackOff. 69 | type Clock interface { 70 | Now() time.Time 71 | } 72 | 73 | // Default values for ExponentialBackOff. 74 | const ( 75 | DefaultInitialInterval = 500 * time.Millisecond 76 | DefaultRandomizationFactor = 0.5 77 | DefaultMultiplier = 1.5 78 | DefaultMaxInterval = 60 * time.Second 79 | DefaultMaxElapsedTime = 15 * time.Minute 80 | ) 81 | 82 | // NewExponentialBackOff creates an instance of ExponentialBackOff using default values. 83 | func NewExponentialBackOff() *ExponentialBackOff { 84 | b := &ExponentialBackOff{ 85 | InitialInterval: DefaultInitialInterval, 86 | RandomizationFactor: DefaultRandomizationFactor, 87 | Multiplier: DefaultMultiplier, 88 | MaxInterval: DefaultMaxInterval, 89 | MaxElapsedTime: DefaultMaxElapsedTime, 90 | Clock: SystemClock, 91 | } 92 | if b.RandomizationFactor < 0 { 93 | b.RandomizationFactor = 0 94 | } else if b.RandomizationFactor > 1 { 95 | b.RandomizationFactor = 1 96 | } 97 | b.Reset() 98 | return b 99 | } 100 | 101 | type systemClock struct{} 102 | 103 | func (t systemClock) Now() time.Time { 104 | return time.Now() 105 | } 106 | 107 | // SystemClock implements Clock interface that uses time.Now(). 108 | var SystemClock = systemClock{} 109 | 110 | // Reset the interval back to the initial retry interval and restarts the timer. 111 | func (b *ExponentialBackOff) Reset() { 112 | b.currentInterval = b.InitialInterval 113 | b.startTime = b.Clock.Now() 114 | } 115 | 116 | // NextBackOff calculates the next backoff interval using the formula: 117 | // Randomized interval = RetryInterval +/- (RandomizationFactor * RetryInterval) 118 | func (b *ExponentialBackOff) NextBackOff() time.Duration { 119 | // Make sure we have not gone over the maximum elapsed time. 120 | if b.MaxElapsedTime != 0 && b.GetElapsedTime() > b.MaxElapsedTime { 121 | return Stop 122 | } 123 | defer b.incrementCurrentInterval() 124 | return getRandomValueFromInterval(b.RandomizationFactor, rand.Float64(), b.currentInterval) 125 | } 126 | 127 | // GetElapsedTime returns the elapsed time since an ExponentialBackOff instance 128 | // is created and is reset when Reset() is called. 129 | // 130 | // The elapsed time is computed using time.Now().UnixNano(). 131 | func (b *ExponentialBackOff) GetElapsedTime() time.Duration { 132 | return b.Clock.Now().Sub(b.startTime) 133 | } 134 | 135 | // Increments the current interval by multiplying it with the multiplier. 136 | func (b *ExponentialBackOff) incrementCurrentInterval() { 137 | // Check for overflow, if overflow is detected set the current interval to the max interval. 138 | if float64(b.currentInterval) >= float64(b.MaxInterval)/b.Multiplier { 139 | b.currentInterval = b.MaxInterval 140 | } else { 141 | b.currentInterval = time.Duration(float64(b.currentInterval) * b.Multiplier) 142 | } 143 | } 144 | 145 | // Returns a random value from the following interval: 146 | // [randomizationFactor * currentInterval, randomizationFactor * currentInterval]. 147 | func getRandomValueFromInterval(randomizationFactor, random float64, currentInterval time.Duration) time.Duration { 148 | var delta = randomizationFactor * float64(currentInterval) 149 | var minInterval = float64(currentInterval) - delta 150 | var maxInterval = float64(currentInterval) + delta 151 | 152 | // Get a random value from the range [minInterval, maxInterval]. 153 | // The formula used below has a +1 because if the minInterval is 1 and the maxInterval is 3 then 154 | // we want a 33% chance for selecting either 1, 2 or 3. 155 | return time.Duration(minInterval + (random * (maxInterval - minInterval + 1))) 156 | } 157 | -------------------------------------------------------------------------------- /vendor/github.com/cenk/backoff/retry.go: -------------------------------------------------------------------------------- 1 | package backoff 2 | 3 | import "time" 4 | 5 | // An Operation is executing by Retry() or RetryNotify(). 6 | // The operation will be retried using a backoff policy if it returns an error. 7 | type Operation func() error 8 | 9 | // Notify is a notify-on-error function. It receives an operation error and 10 | // backoff delay if the operation failed (with an error). 11 | // 12 | // NOTE that if the backoff policy stated to stop retrying, 13 | // the notify function isn't called. 14 | type Notify func(error, time.Duration) 15 | 16 | // Retry the operation o until it does not return error or BackOff stops. 17 | // o is guaranteed to be run at least once. 18 | // It is the caller's responsibility to reset b after Retry returns. 19 | // 20 | // Retry sleeps the goroutine for the duration returned by BackOff after a 21 | // failed operation returns. 22 | func Retry(o Operation, b BackOff) error { return RetryNotify(o, b, nil) } 23 | 24 | // RetryNotify calls notify function with the error and wait duration 25 | // for each failed attempt before sleep. 26 | func RetryNotify(operation Operation, b BackOff, notify Notify) error { 27 | var err error 28 | var next time.Duration 29 | 30 | b.Reset() 31 | for { 32 | if err = operation(); err == nil { 33 | return nil 34 | } 35 | 36 | if next = b.NextBackOff(); next == Stop { 37 | return err 38 | } 39 | 40 | if notify != nil { 41 | notify(err, next) 42 | } 43 | 44 | time.Sleep(next) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /vendor/github.com/cenk/backoff/ticker.go: -------------------------------------------------------------------------------- 1 | package backoff 2 | 3 | import ( 4 | "runtime" 5 | "sync" 6 | "time" 7 | ) 8 | 9 | // Ticker holds a channel that delivers `ticks' of a clock at times reported by a BackOff. 10 | // 11 | // Ticks will continue to arrive when the previous operation is still running, 12 | // so operations that take a while to fail could run in quick succession. 13 | type Ticker struct { 14 | C <-chan time.Time 15 | c chan time.Time 16 | b BackOff 17 | stop chan struct{} 18 | stopOnce sync.Once 19 | } 20 | 21 | // NewTicker returns a new Ticker containing a channel that will send the time at times 22 | // specified by the BackOff argument. Ticker is guaranteed to tick at least once. 23 | // The channel is closed when Stop method is called or BackOff stops. 24 | func NewTicker(b BackOff) *Ticker { 25 | c := make(chan time.Time) 26 | t := &Ticker{ 27 | C: c, 28 | c: c, 29 | b: b, 30 | stop: make(chan struct{}), 31 | } 32 | go t.run() 33 | runtime.SetFinalizer(t, (*Ticker).Stop) 34 | return t 35 | } 36 | 37 | // Stop turns off a ticker. After Stop, no more ticks will be sent. 38 | func (t *Ticker) Stop() { 39 | t.stopOnce.Do(func() { close(t.stop) }) 40 | } 41 | 42 | func (t *Ticker) run() { 43 | c := t.c 44 | defer close(c) 45 | t.b.Reset() 46 | 47 | // Ticker is guaranteed to tick at least once. 48 | afterC := t.send(time.Now()) 49 | 50 | for { 51 | if afterC == nil { 52 | return 53 | } 54 | 55 | select { 56 | case tick := <-afterC: 57 | afterC = t.send(tick) 58 | case <-t.stop: 59 | t.c = nil // Prevent future ticks from being sent to the channel. 60 | return 61 | } 62 | } 63 | } 64 | 65 | func (t *Ticker) send(tick time.Time) <-chan time.Time { 66 | select { 67 | case t.c <- tick: 68 | case <-t.stop: 69 | return nil 70 | } 71 | 72 | next := t.b.NextBackOff() 73 | if next == Stop { 74 | t.Stop() 75 | return nil 76 | } 77 | 78 | return time.After(next) 79 | } 80 | -------------------------------------------------------------------------------- /vendor/github.com/imdario/mergo/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | install: go get -t 3 | -------------------------------------------------------------------------------- /vendor/github.com/imdario/mergo/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Dario Castañé. All rights reserved. 2 | Copyright (c) 2012 The Go Authors. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above 11 | copyright notice, this list of conditions and the following disclaimer 12 | in the documentation and/or other materials provided with the 13 | distribution. 14 | * Neither the name of Google Inc. nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /vendor/github.com/imdario/mergo/README.md: -------------------------------------------------------------------------------- 1 | # Mergo 2 | 3 | A helper to merge structs and maps in Golang. Useful for configuration default values, avoiding messy if-statements. 4 | 5 | Also a lovely [comune](http://en.wikipedia.org/wiki/Mergo) (municipality) in the Province of Ancona in the Italian region Marche. 6 | 7 | ![Mergo dall'alto](http://www.comune.mergo.an.it/Siti/Mergo/Immagini/Foto/mergo_dall_alto.jpg) 8 | 9 | ## Status 10 | 11 | It is ready for production use. It works fine after extensive use in the wild. 12 | 13 | [![Build Status][1]][2] 14 | [![GoDoc][3]][4] 15 | [![GoCard][5]][6] 16 | 17 | [1]: https://travis-ci.org/imdario/mergo.png 18 | [2]: https://travis-ci.org/imdario/mergo 19 | [3]: https://godoc.org/github.com/imdario/mergo?status.svg 20 | [4]: https://godoc.org/github.com/imdario/mergo 21 | [5]: https://goreportcard.com/badge/imdario/mergo 22 | [6]: https://goreportcard.com/report/github.com/imdario/mergo 23 | 24 | ### Important note 25 | 26 | Mergo is intended to assign **only** zero value fields on destination with source value. Since April 6th it works like this. Before it didn't work properly, causing some random overwrites. After some issues and PRs I found it didn't merge as I designed it. Thanks to [imdario/mergo#8](https://github.com/imdario/mergo/pull/8) overwriting functions were added and the wrong behavior was clearly detected. 27 | 28 | If you were using Mergo **before** April 6th 2015, please check your project works as intended after updating your local copy with ```go get -u github.com/imdario/mergo```. I apologize for any issue caused by its previous behavior and any future bug that Mergo could cause (I hope it won't!) in existing projects after the change (release 0.2.0). 29 | 30 | ### Mergo in the wild 31 | 32 | - [docker/docker](https://github.com/docker/docker/) 33 | - [kubernetes/kubernetes](https://github.com/kubernetes/kubernetes) 34 | - [imdario/zas](https://github.com/imdario/zas) 35 | - [soniah/dnsmadeeasy](https://github.com/soniah/dnsmadeeasy) 36 | - [EagerIO/Stout](https://github.com/EagerIO/Stout) 37 | - [lynndylanhurley/defsynth-api](https://github.com/lynndylanhurley/defsynth-api) 38 | - [russross/canvasassignments](https://github.com/russross/canvasassignments) 39 | - [rdegges/cryptly-api](https://github.com/rdegges/cryptly-api) 40 | - [casualjim/exeggutor](https://github.com/casualjim/exeggutor) 41 | - [divshot/gitling](https://github.com/divshot/gitling) 42 | - [RWJMurphy/gorl](https://github.com/RWJMurphy/gorl) 43 | - [andrerocker/deploy42](https://github.com/andrerocker/deploy42) 44 | - [elwinar/rambler](https://github.com/elwinar/rambler) 45 | - [tmaiaroto/gopartman](https://github.com/tmaiaroto/gopartman) 46 | - [jfbus/impressionist](https://github.com/jfbus/impressionist) 47 | - [Jmeyering/zealot](https://github.com/Jmeyering/zealot) 48 | - [godep-migrator/rigger-host](https://github.com/godep-migrator/rigger-host) 49 | - [Dronevery/MultiwaySwitch-Go](https://github.com/Dronevery/MultiwaySwitch-Go) 50 | - [thoas/picfit](https://github.com/thoas/picfit) 51 | - [mantasmatelis/whooplist-server](https://github.com/mantasmatelis/whooplist-server) 52 | - [jnuthong/item_search](https://github.com/jnuthong/item_search) 53 | - [Iris Web Framework](https://github.com/kataras/iris) 54 | 55 | ## Installation 56 | 57 | go get github.com/imdario/mergo 58 | 59 | // use in your .go code 60 | import ( 61 | "github.com/imdario/mergo" 62 | ) 63 | 64 | ## Usage 65 | 66 | You can only merge same-type structs with exported fields initialized as zero value of their type and same-types maps. Mergo won't merge unexported (private) fields but will do recursively any exported one. Also maps will be merged recursively except for structs inside maps (because they are not addressable using Go reflection). 67 | 68 | if err := mergo.Merge(&dst, src); err != nil { 69 | // ... 70 | } 71 | 72 | Additionally, you can map a map[string]interface{} to a struct (and otherwise, from struct to map), following the same restrictions as in Merge(). Keys are capitalized to find each corresponding exported field. 73 | 74 | if err := mergo.Map(&dst, srcMap); err != nil { 75 | // ... 76 | } 77 | 78 | Warning: if you map a struct to map, it won't do it recursively. Don't expect Mergo to map struct members of your struct as map[string]interface{}. They will be just assigned as values. 79 | 80 | More information and examples in [godoc documentation](http://godoc.org/github.com/imdario/mergo). 81 | 82 | ### Nice example 83 | 84 | ```go 85 | package main 86 | 87 | import ( 88 | "fmt" 89 | "github.com/imdario/mergo" 90 | ) 91 | 92 | type Foo struct { 93 | A string 94 | B int64 95 | } 96 | 97 | func main() { 98 | src := Foo{ 99 | A: "one", 100 | } 101 | 102 | dest := Foo{ 103 | A: "two", 104 | B: 2, 105 | } 106 | 107 | mergo.Merge(&dest, src) 108 | 109 | fmt.Println(dest) 110 | // Will print 111 | // {two 2} 112 | } 113 | ``` 114 | 115 | Note: if test are failing due missing package, please execute: 116 | 117 | go get gopkg.in/yaml.v1 118 | 119 | ## Contact me 120 | 121 | If I can help you, you have an idea or you are using Mergo in your projects, don't hesitate to drop me a line (or a pull request): [@im_dario](https://twitter.com/im_dario) 122 | 123 | ## About 124 | 125 | Written by [Dario Castañé](http://dario.im). 126 | 127 | ## License 128 | 129 | [BSD 3-Clause](http://opensource.org/licenses/BSD-3-Clause) license, as [Go language](http://golang.org/LICENSE). 130 | -------------------------------------------------------------------------------- /vendor/github.com/imdario/mergo/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Dario Castañé. All rights reserved. 2 | // Copyright 2009 The Go Authors. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | /* 7 | Package mergo merges same-type structs and maps by setting default values in zero-value fields. 8 | 9 | Mergo won't merge unexported (private) fields but will do recursively any exported one. It also won't merge structs inside maps (because they are not addressable using Go reflection). 10 | 11 | Usage 12 | 13 | From my own work-in-progress project: 14 | 15 | type networkConfig struct { 16 | Protocol string 17 | Address string 18 | ServerType string `json: "server_type"` 19 | Port uint16 20 | } 21 | 22 | type FssnConfig struct { 23 | Network networkConfig 24 | } 25 | 26 | var fssnDefault = FssnConfig { 27 | networkConfig { 28 | "tcp", 29 | "127.0.0.1", 30 | "http", 31 | 31560, 32 | }, 33 | } 34 | 35 | // Inside a function [...] 36 | 37 | if err := mergo.Merge(&config, fssnDefault); err != nil { 38 | log.Fatal(err) 39 | } 40 | 41 | // More code [...] 42 | 43 | */ 44 | package mergo 45 | -------------------------------------------------------------------------------- /vendor/github.com/imdario/mergo/map.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Dario Castañé. All rights reserved. 2 | // Copyright 2009 The Go Authors. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // Based on src/pkg/reflect/deepequal.go from official 7 | // golang's stdlib. 8 | 9 | package mergo 10 | 11 | import ( 12 | "fmt" 13 | "reflect" 14 | "unicode" 15 | "unicode/utf8" 16 | ) 17 | 18 | func changeInitialCase(s string, mapper func(rune) rune) string { 19 | if s == "" { 20 | return s 21 | } 22 | r, n := utf8.DecodeRuneInString(s) 23 | return string(mapper(r)) + s[n:] 24 | } 25 | 26 | func isExported(field reflect.StructField) bool { 27 | r, _ := utf8.DecodeRuneInString(field.Name) 28 | return r >= 'A' && r <= 'Z' 29 | } 30 | 31 | // Traverses recursively both values, assigning src's fields values to dst. 32 | // The map argument tracks comparisons that have already been seen, which allows 33 | // short circuiting on recursive types. 34 | func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, overwrite bool) (err error) { 35 | if dst.CanAddr() { 36 | addr := dst.UnsafeAddr() 37 | h := 17 * addr 38 | seen := visited[h] 39 | typ := dst.Type() 40 | for p := seen; p != nil; p = p.next { 41 | if p.ptr == addr && p.typ == typ { 42 | return nil 43 | } 44 | } 45 | // Remember, remember... 46 | visited[h] = &visit{addr, typ, seen} 47 | } 48 | zeroValue := reflect.Value{} 49 | switch dst.Kind() { 50 | case reflect.Map: 51 | dstMap := dst.Interface().(map[string]interface{}) 52 | for i, n := 0, src.NumField(); i < n; i++ { 53 | srcType := src.Type() 54 | field := srcType.Field(i) 55 | if !isExported(field) { 56 | continue 57 | } 58 | fieldName := field.Name 59 | fieldName = changeInitialCase(fieldName, unicode.ToLower) 60 | if v, ok := dstMap[fieldName]; !ok || (isEmptyValue(reflect.ValueOf(v)) || overwrite) { 61 | dstMap[fieldName] = src.Field(i).Interface() 62 | } 63 | } 64 | case reflect.Struct: 65 | srcMap := src.Interface().(map[string]interface{}) 66 | for key := range srcMap { 67 | srcValue := srcMap[key] 68 | fieldName := changeInitialCase(key, unicode.ToUpper) 69 | dstElement := dst.FieldByName(fieldName) 70 | if dstElement == zeroValue { 71 | // We discard it because the field doesn't exist. 72 | continue 73 | } 74 | srcElement := reflect.ValueOf(srcValue) 75 | dstKind := dstElement.Kind() 76 | srcKind := srcElement.Kind() 77 | if srcKind == reflect.Ptr && dstKind != reflect.Ptr { 78 | srcElement = srcElement.Elem() 79 | srcKind = reflect.TypeOf(srcElement.Interface()).Kind() 80 | } else if dstKind == reflect.Ptr { 81 | // Can this work? I guess it can't. 82 | if srcKind != reflect.Ptr && srcElement.CanAddr() { 83 | srcPtr := srcElement.Addr() 84 | srcElement = reflect.ValueOf(srcPtr) 85 | srcKind = reflect.Ptr 86 | } 87 | } 88 | if !srcElement.IsValid() { 89 | continue 90 | } 91 | if srcKind == dstKind { 92 | if err = deepMerge(dstElement, srcElement, visited, depth+1, overwrite); err != nil { 93 | return 94 | } 95 | } else { 96 | if srcKind == reflect.Map { 97 | if err = deepMap(dstElement, srcElement, visited, depth+1, overwrite); err != nil { 98 | return 99 | } 100 | } else { 101 | return fmt.Errorf("type mismatch on %s field: found %v, expected %v", fieldName, srcKind, dstKind) 102 | } 103 | } 104 | } 105 | } 106 | return 107 | } 108 | 109 | // Map sets fields' values in dst from src. 110 | // src can be a map with string keys or a struct. dst must be the opposite: 111 | // if src is a map, dst must be a valid pointer to struct. If src is a struct, 112 | // dst must be map[string]interface{}. 113 | // It won't merge unexported (private) fields and will do recursively 114 | // any exported field. 115 | // If dst is a map, keys will be src fields' names in lower camel case. 116 | // Missing key in src that doesn't match a field in dst will be skipped. This 117 | // doesn't apply if dst is a map. 118 | // This is separated method from Merge because it is cleaner and it keeps sane 119 | // semantics: merging equal types, mapping different (restricted) types. 120 | func Map(dst, src interface{}) error { 121 | return _map(dst, src, false) 122 | } 123 | 124 | // MapWithOverwrite will do the same as Map except that non-empty dst attributes will be overriden by 125 | // non-empty src attribute values. 126 | func MapWithOverwrite(dst, src interface{}) error { 127 | return _map(dst, src, true) 128 | } 129 | 130 | func _map(dst, src interface{}, overwrite bool) error { 131 | var ( 132 | vDst, vSrc reflect.Value 133 | err error 134 | ) 135 | if vDst, vSrc, err = resolveValues(dst, src); err != nil { 136 | return err 137 | } 138 | // To be friction-less, we redirect equal-type arguments 139 | // to deepMerge. Only because arguments can be anything. 140 | if vSrc.Kind() == vDst.Kind() { 141 | return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, overwrite) 142 | } 143 | switch vSrc.Kind() { 144 | case reflect.Struct: 145 | if vDst.Kind() != reflect.Map { 146 | return ErrExpectedMapAsDestination 147 | } 148 | case reflect.Map: 149 | if vDst.Kind() != reflect.Struct { 150 | return ErrExpectedStructAsDestination 151 | } 152 | default: 153 | return ErrNotSupported 154 | } 155 | return deepMap(vDst, vSrc, make(map[uintptr]*visit), 0, overwrite) 156 | } 157 | -------------------------------------------------------------------------------- /vendor/github.com/imdario/mergo/merge.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Dario Castañé. All rights reserved. 2 | // Copyright 2009 The Go Authors. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // Based on src/pkg/reflect/deepequal.go from official 7 | // golang's stdlib. 8 | 9 | package mergo 10 | 11 | import ( 12 | "reflect" 13 | ) 14 | 15 | // Traverses recursively both values, assigning src's fields values to dst. 16 | // The map argument tracks comparisons that have already been seen, which allows 17 | // short circuiting on recursive types. 18 | func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, overwrite bool) (err error) { 19 | if !src.IsValid() { 20 | return 21 | } 22 | if dst.CanAddr() { 23 | addr := dst.UnsafeAddr() 24 | h := 17 * addr 25 | seen := visited[h] 26 | typ := dst.Type() 27 | for p := seen; p != nil; p = p.next { 28 | if p.ptr == addr && p.typ == typ { 29 | return nil 30 | } 31 | } 32 | // Remember, remember... 33 | visited[h] = &visit{addr, typ, seen} 34 | } 35 | switch dst.Kind() { 36 | case reflect.Struct: 37 | for i, n := 0, dst.NumField(); i < n; i++ { 38 | if err = deepMerge(dst.Field(i), src.Field(i), visited, depth+1, overwrite); err != nil { 39 | return 40 | } 41 | } 42 | case reflect.Map: 43 | for _, key := range src.MapKeys() { 44 | srcElement := src.MapIndex(key) 45 | if !srcElement.IsValid() { 46 | continue 47 | } 48 | dstElement := dst.MapIndex(key) 49 | switch srcElement.Kind() { 50 | case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Slice: 51 | if srcElement.IsNil() { 52 | continue 53 | } 54 | fallthrough 55 | default: 56 | if !srcElement.CanInterface() { 57 | continue 58 | } 59 | switch reflect.TypeOf(srcElement.Interface()).Kind() { 60 | case reflect.Struct: 61 | fallthrough 62 | case reflect.Ptr: 63 | fallthrough 64 | case reflect.Map: 65 | if err = deepMerge(dstElement, srcElement, visited, depth+1, overwrite); err != nil { 66 | return 67 | } 68 | } 69 | } 70 | if !isEmptyValue(srcElement) && (overwrite || (!dstElement.IsValid() || isEmptyValue(dst))) { 71 | if dst.IsNil() { 72 | dst.Set(reflect.MakeMap(dst.Type())) 73 | } 74 | dst.SetMapIndex(key, srcElement) 75 | } 76 | } 77 | case reflect.Ptr: 78 | fallthrough 79 | case reflect.Interface: 80 | if src.IsNil() { 81 | break 82 | } else if dst.IsNil() || overwrite { 83 | if dst.CanSet() && (overwrite || isEmptyValue(dst)) { 84 | dst.Set(src) 85 | } 86 | } else if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, overwrite); err != nil { 87 | return 88 | } 89 | default: 90 | if dst.CanSet() && !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) { 91 | dst.Set(src) 92 | } 93 | } 94 | return 95 | } 96 | 97 | // Merge will fill any empty for value type attributes on the dst struct using corresponding 98 | // src attributes if they themselves are not empty. dst and src must be valid same-type structs 99 | // and dst must be a pointer to struct. 100 | // It won't merge unexported (private) fields and will do recursively any exported field. 101 | func Merge(dst, src interface{}) error { 102 | return merge(dst, src, false) 103 | } 104 | 105 | // MergeWithOverwrite will do the same as Merge except that non-empty dst attributes will be overriden by 106 | // non-empty src attribute values. 107 | func MergeWithOverwrite(dst, src interface{}) error { 108 | return merge(dst, src, true) 109 | } 110 | 111 | func merge(dst, src interface{}, overwrite bool) error { 112 | var ( 113 | vDst, vSrc reflect.Value 114 | err error 115 | ) 116 | if vDst, vSrc, err = resolveValues(dst, src); err != nil { 117 | return err 118 | } 119 | if vDst.Type() != vSrc.Type() { 120 | return ErrDifferentArgumentsTypes 121 | } 122 | return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, overwrite) 123 | } 124 | -------------------------------------------------------------------------------- /vendor/github.com/imdario/mergo/mergo.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Dario Castañé. All rights reserved. 2 | // Copyright 2009 The Go Authors. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // Based on src/pkg/reflect/deepequal.go from official 7 | // golang's stdlib. 8 | 9 | package mergo 10 | 11 | import ( 12 | "errors" 13 | "reflect" 14 | ) 15 | 16 | // Errors reported by Mergo when it finds invalid arguments. 17 | var ( 18 | ErrNilArguments = errors.New("src and dst must not be nil") 19 | ErrDifferentArgumentsTypes = errors.New("src and dst must be of same type") 20 | ErrNotSupported = errors.New("only structs and maps are supported") 21 | ErrExpectedMapAsDestination = errors.New("dst was expected to be a map") 22 | ErrExpectedStructAsDestination = errors.New("dst was expected to be a struct") 23 | ) 24 | 25 | // During deepMerge, must keep track of checks that are 26 | // in progress. The comparison algorithm assumes that all 27 | // checks in progress are true when it reencounters them. 28 | // Visited are stored in a map indexed by 17 * a1 + a2; 29 | type visit struct { 30 | ptr uintptr 31 | typ reflect.Type 32 | next *visit 33 | } 34 | 35 | // From src/pkg/encoding/json. 36 | func isEmptyValue(v reflect.Value) bool { 37 | switch v.Kind() { 38 | case reflect.Array, reflect.Map, reflect.Slice, reflect.String: 39 | return v.Len() == 0 40 | case reflect.Bool: 41 | return !v.Bool() 42 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 43 | return v.Int() == 0 44 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 45 | return v.Uint() == 0 46 | case reflect.Float32, reflect.Float64: 47 | return v.Float() == 0 48 | case reflect.Interface, reflect.Ptr: 49 | return v.IsNil() 50 | } 51 | return false 52 | } 53 | 54 | func resolveValues(dst, src interface{}) (vDst, vSrc reflect.Value, err error) { 55 | if dst == nil || src == nil { 56 | err = ErrNilArguments 57 | return 58 | } 59 | vDst = reflect.ValueOf(dst).Elem() 60 | if vDst.Kind() != reflect.Struct && vDst.Kind() != reflect.Map { 61 | err = ErrNotSupported 62 | return 63 | } 64 | vSrc = reflect.ValueOf(src) 65 | // We check if vSrc is a pointer to dereference it. 66 | if vSrc.Kind() == reflect.Ptr { 67 | vSrc = vSrc.Elem() 68 | } 69 | return 70 | } 71 | 72 | // Traverses recursively both values, assigning src's fields values to dst. 73 | // The map argument tracks comparisons that have already been seen, which allows 74 | // short circuiting on recursive types. 75 | func deeper(dst, src reflect.Value, visited map[uintptr]*visit, depth int) (err error) { 76 | if dst.CanAddr() { 77 | addr := dst.UnsafeAddr() 78 | h := 17 * addr 79 | seen := visited[h] 80 | typ := dst.Type() 81 | for p := seen; p != nil; p = p.next { 82 | if p.ptr == addr && p.typ == typ { 83 | return nil 84 | } 85 | } 86 | // Remember, remember... 87 | visited[h] = &visit{addr, typ, seen} 88 | } 89 | return // TODO refactor 90 | } 91 | -------------------------------------------------------------------------------- /vendor/github.com/mitchellh/go-homedir/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Mitchell Hashimoto 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/mitchellh/go-homedir/README.md: -------------------------------------------------------------------------------- 1 | # go-homedir 2 | 3 | This is a Go library for detecting the user's home directory without 4 | the use of cgo, so the library can be used in cross-compilation environments. 5 | 6 | Usage is incredibly simple, just call `homedir.Dir()` to get the home directory 7 | for a user, and `homedir.Expand()` to expand the `~` in a path to the home 8 | directory. 9 | 10 | **Why not just use `os/user`?** The built-in `os/user` package requires 11 | cgo on Darwin systems. This means that any Go code that uses that package 12 | cannot cross compile. But 99% of the time the use for `os/user` is just to 13 | retrieve the home directory, which we can do for the current user without 14 | cgo. This library does that, enabling cross-compilation. 15 | -------------------------------------------------------------------------------- /vendor/github.com/mitchellh/go-homedir/homedir.go: -------------------------------------------------------------------------------- 1 | package homedir 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | "os" 7 | "os/exec" 8 | "path/filepath" 9 | "runtime" 10 | "strconv" 11 | "strings" 12 | "sync" 13 | ) 14 | 15 | // DisableCache will disable caching of the home directory. Caching is enabled 16 | // by default. 17 | var DisableCache bool 18 | 19 | var homedirCache string 20 | var cacheLock sync.RWMutex 21 | 22 | // Dir returns the home directory for the executing user. 23 | // 24 | // This uses an OS-specific method for discovering the home directory. 25 | // An error is returned if a home directory cannot be detected. 26 | func Dir() (string, error) { 27 | if !DisableCache { 28 | cacheLock.RLock() 29 | cached := homedirCache 30 | cacheLock.RUnlock() 31 | if cached != "" { 32 | return cached, nil 33 | } 34 | } 35 | 36 | cacheLock.Lock() 37 | defer cacheLock.Unlock() 38 | 39 | var result string 40 | var err error 41 | if runtime.GOOS == "windows" { 42 | result, err = dirWindows() 43 | } else { 44 | // Unix-like system, so just assume Unix 45 | result, err = dirUnix() 46 | } 47 | 48 | if err != nil { 49 | return "", err 50 | } 51 | homedirCache = result 52 | return result, nil 53 | } 54 | 55 | // Expand expands the path to include the home directory if the path 56 | // is prefixed with `~`. If it isn't prefixed with `~`, the path is 57 | // returned as-is. 58 | func Expand(path string) (string, error) { 59 | if len(path) == 0 { 60 | return path, nil 61 | } 62 | 63 | if path[0] != '~' { 64 | return path, nil 65 | } 66 | 67 | if len(path) > 1 && path[1] != '/' && path[1] != '\\' { 68 | return "", errors.New("cannot expand user-specific home dir") 69 | } 70 | 71 | dir, err := Dir() 72 | if err != nil { 73 | return "", err 74 | } 75 | 76 | return filepath.Join(dir, path[1:]), nil 77 | } 78 | 79 | func dirUnix() (string, error) { 80 | // First prefer the HOME environmental variable 81 | if home := os.Getenv("HOME"); home != "" { 82 | return home, nil 83 | } 84 | 85 | // If that fails, try getent 86 | var stdout bytes.Buffer 87 | cmd := exec.Command("getent", "passwd", strconv.Itoa(os.Getuid())) 88 | cmd.Stdout = &stdout 89 | if err := cmd.Run(); err != nil { 90 | // If "getent" is missing, ignore it 91 | if err == exec.ErrNotFound { 92 | return "", err 93 | } 94 | } else { 95 | if passwd := strings.TrimSpace(stdout.String()); passwd != "" { 96 | // username:password:uid:gid:gecos:home:shell 97 | passwdParts := strings.SplitN(passwd, ":", 7) 98 | if len(passwdParts) > 5 { 99 | return passwdParts[5], nil 100 | } 101 | } 102 | } 103 | 104 | // If all else fails, try the shell 105 | stdout.Reset() 106 | cmd = exec.Command("sh", "-c", "cd && pwd") 107 | cmd.Stdout = &stdout 108 | if err := cmd.Run(); err != nil { 109 | return "", err 110 | } 111 | 112 | result := strings.TrimSpace(stdout.String()) 113 | if result == "" { 114 | return "", errors.New("blank output when reading home directory") 115 | } 116 | 117 | return result, nil 118 | } 119 | 120 | func dirWindows() (string, error) { 121 | // First prefer the HOME environmental variable 122 | if home := os.Getenv("HOME"); home != "" { 123 | return home, nil 124 | } 125 | 126 | drive := os.Getenv("HOMEDRIVE") 127 | path := os.Getenv("HOMEPATH") 128 | home := drive + path 129 | if drive == "" || path == "" { 130 | home = os.Getenv("USERPROFILE") 131 | } 132 | if home == "" { 133 | return "", errors.New("HOMEDRIVE, HOMEPATH, and USERPROFILE are blank") 134 | } 135 | 136 | return home, nil 137 | } 138 | -------------------------------------------------------------------------------- /vendor/github.com/wsxiaoys/terminal/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Meng Zhang. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/github.com/wsxiaoys/terminal/color/color.go: -------------------------------------------------------------------------------- 1 | // The colors package provide a simple way to bring colorful characters to terminal interface. 2 | // 3 | // This example will output the text with a Blue foreground and a Black background 4 | // color.Println("@{bK}Example Text") 5 | // 6 | // This one will output the text with a red foreground 7 | // color.Println("@rExample Text") 8 | // 9 | // This one will escape the @ 10 | // color.Println("@@") 11 | // 12 | // Full color syntax code 13 | // @{rgbcmykwRGBCMYKW} foreground/background color 14 | // r/R: Red 15 | // g/G: Green 16 | // b/B: Blue 17 | // c/C: Cyan 18 | // m/M: Magenta 19 | // y/Y: Yellow 20 | // k/K: Black 21 | // w/W: White 22 | // @{|} Reset format style 23 | // @{!./_} Bold / Dim / Italic / Underline 24 | // @{^&} Blink / Fast blink 25 | // @{*} High intensity foreground color 26 | // @{?} Reverse the foreground and background color 27 | // @{-} Hide the text 28 | // Note some of the functions are not widely supported, like "Fast blink" and "Italic". 29 | package color 30 | 31 | import ( 32 | "bytes" 33 | "errors" 34 | "fmt" 35 | "io" 36 | "log" 37 | ) 38 | 39 | const ( 40 | EscapeChar = '@' // Escape character for color syntax 41 | ResetCode = "\033[0m" // Short for reset to default style 42 | ) 43 | 44 | // Mapping from character to concrete escape code. 45 | var codeMap = map[int]int{ 46 | '|': 0, 47 | '!': 1, 48 | '.': 2, 49 | '/': 3, 50 | '_': 4, 51 | '^': 5, 52 | '&': 6, 53 | '?': 7, 54 | '-': 8, 55 | '*': 60, 56 | 57 | 'k': 30, 58 | 'r': 31, 59 | 'g': 32, 60 | 'y': 33, 61 | 'b': 34, 62 | 'm': 35, 63 | 'c': 36, 64 | 'w': 37, 65 | 'd': 39, 66 | 67 | 'K': 40, 68 | 'R': 41, 69 | 'G': 42, 70 | 'Y': 43, 71 | 'B': 44, 72 | 'M': 45, 73 | 'C': 46, 74 | 'W': 47, 75 | 'D': 49, 76 | } 77 | 78 | // Compile color syntax string like "rG" to escape code. 79 | func Colorize(x string) string { 80 | attr := 0 81 | fg := 39 82 | bg := 49 83 | 84 | for _, key := range x { 85 | c, ok := codeMap[int(key)] 86 | switch { 87 | case !ok: 88 | log.Printf("Wrong color syntax: %c", key) 89 | case 0 <= c && c <= 8: 90 | attr = c 91 | case 30 <= c && c <= 37: 92 | fg = c 93 | case 40 <= c && c <= 47: 94 | bg = c 95 | case c == 60: 96 | fg += c 97 | } 98 | } 99 | return fmt.Sprintf("\033[%d;%d;%dm", attr, fg, bg) 100 | } 101 | 102 | // Handle state after meeting one '@' 103 | func compileColorSyntax(input, output *bytes.Buffer) { 104 | i, _, err := input.ReadRune() 105 | if err != nil { 106 | // EOF got 107 | log.Print("Parse failed on color syntax") 108 | return 109 | } 110 | 111 | switch i { 112 | default: 113 | output.WriteString(Colorize(string(i))) 114 | case '{': 115 | color := bytes.NewBufferString("") 116 | for { 117 | i, _, err := input.ReadRune() 118 | if err != nil { 119 | log.Print("Parse failed on color syntax") 120 | break 121 | } 122 | if i == '}' { 123 | break 124 | } 125 | color.WriteRune(i) 126 | } 127 | output.WriteString(Colorize(color.String())) 128 | case EscapeChar: 129 | output.WriteRune(EscapeChar) 130 | } 131 | } 132 | 133 | // Compile the string and replace color syntax with concrete escape code. 134 | func compile(x string) string { 135 | if x == "" { 136 | return "" 137 | } 138 | 139 | input := bytes.NewBufferString(x) 140 | output := bytes.NewBufferString("") 141 | 142 | for { 143 | i, _, err := input.ReadRune() 144 | if err != nil { 145 | break 146 | } 147 | switch i { 148 | default: 149 | output.WriteRune(i) 150 | case EscapeChar: 151 | compileColorSyntax(input, output) 152 | } 153 | } 154 | return output.String() 155 | } 156 | 157 | // Compile multiple values, only do compiling on string type. 158 | func compileValues(a *[]interface{}) { 159 | for i, x := range *a { 160 | if str, ok := x.(string); ok { 161 | (*a)[i] = compile(str) 162 | } 163 | } 164 | } 165 | 166 | // Similar to fmt.Print, will reset the color at the end. 167 | func Print(a ...interface{}) (int, error) { 168 | a = append(a, ResetCode) 169 | compileValues(&a) 170 | return fmt.Print(a...) 171 | } 172 | 173 | // Similar to fmt.Println, will reset the color at the end. 174 | func Println(a ...interface{}) (int, error) { 175 | a = append(a, ResetCode) 176 | compileValues(&a) 177 | return fmt.Println(a...) 178 | } 179 | 180 | // Similar to fmt.Printf, will reset the color at the end. 181 | func Printf(format string, a ...interface{}) (int, error) { 182 | format += ResetCode 183 | format = compile(format) 184 | return fmt.Printf(format, a...) 185 | } 186 | 187 | // Similar to fmt.Fprint, will reset the color at the end. 188 | func Fprint(w io.Writer, a ...interface{}) (int, error) { 189 | a = append(a, ResetCode) 190 | compileValues(&a) 191 | return fmt.Fprint(w, a...) 192 | } 193 | 194 | // Similar to fmt.Fprintln, will reset the color at the end. 195 | func Fprintln(w io.Writer, a ...interface{}) (int, error) { 196 | a = append(a, ResetCode) 197 | compileValues(&a) 198 | return fmt.Fprintln(w, a...) 199 | } 200 | 201 | // Similar to fmt.Fprintf, will reset the color at the end. 202 | func Fprintf(w io.Writer, format string, a ...interface{}) (int, error) { 203 | format += ResetCode 204 | format = compile(format) 205 | return fmt.Fprintf(w, format, a...) 206 | } 207 | 208 | // Similar to fmt.Sprint, will reset the color at the end. 209 | func Sprint(a ...interface{}) string { 210 | a = append(a, ResetCode) 211 | compileValues(&a) 212 | return fmt.Sprint(a...) 213 | } 214 | 215 | // Similar to fmt.Sprintf, will reset the color at the end. 216 | func Sprintf(format string, a ...interface{}) string { 217 | format += ResetCode 218 | format = compile(format) 219 | return fmt.Sprintf(format, a...) 220 | } 221 | 222 | // Similar to fmt.Errorf, will reset the color at the end. 223 | func Errorf(format string, a ...interface{}) error { 224 | return errors.New(Sprintf(format, a...)) 225 | } 226 | -------------------------------------------------------------------------------- /vendor/github.com/zackbloom/go-ini/.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 | *.nope 26 | -------------------------------------------------------------------------------- /vendor/github.com/zackbloom/go-ini/README.md: -------------------------------------------------------------------------------- 1 | go-ini 2 | ====== 3 | 4 | INI file decoder for Go lang. Idea is to have an unmarshaller similar to JSON - specify parts of the file you want coded with structs and tags. 5 | 6 | For example, for an INI file like this: 7 | 8 | [Pod_mysql] 9 | cache_size = 2000 10 | default_socket = /tmp/mysql.sock 11 | 12 | [Mysql] 13 | default_socket = /tmp/mysql.sock 14 | 15 | Decode into a structure like this: 16 | 17 | type MyIni struct { 18 | 19 | PdoMysql struct { 20 | CacheSize int `ini:"cache_size"` 21 | DefaultSocket string `ini:"default_socket"` 22 | } `ini:"[Pdo_myqsl]"` 23 | 24 | Mysql struct { 25 | DefaultSocket string `ini:"default_socket"` 26 | } `ini:"[Myqsl]"` 27 | } 28 | 29 | With code like this: 30 | 31 | var config MyIni 32 | var b []byte // config file stored here 33 | err := ini.Unmarshal(b, &config) 34 | 35 | 36 | Advanced Types 37 | ============== 38 | 39 | Over the years, INI files have grown from simple `name=value` lists of properties to files that support arrays and arrays of structures. For example, to support playlists a music config file may look like this: 40 | 41 | [CREATE SONG] 42 | SongId=21348 43 | Title=Long Way to Go 44 | Artist=The Coach 45 | 46 | [CREATE SONG] 47 | SongId=9855 48 | Title=The Falcon Lead 49 | Artist=It Wasn't Safe 50 | 51 | [CREATE PLAYLIST] 52 | PlaylistId=438432 53 | Title=Acid Jazz 54 | Song=21348 55 | Song=482 56 | Song=9855 57 | 58 | [CREATE PLAYLIST] 59 | PlaylistId=2585 60 | Title=Lounge 61 | Song=7558 62 | Song=25828 63 | 64 | With GO-INI, parsing is as simple as defining the structure and unmarshalling it. 65 | 66 | package main 67 | 68 | import ( 69 | "encoding/json" 70 | "github.com/sspencer/go-ini" 71 | "io/ioutil" 72 | "log" 73 | "os" 74 | ) 75 | 76 | type TunePlayer struct { 77 | Songs []struct { 78 | SongId int 79 | Title string 80 | Artist string 81 | } `ini:"[CREATE SONG]"` 82 | 83 | Playlists []struct { 84 | PlaylistId int 85 | Title string 86 | SongIds []int `ini:"Song"` 87 | } `ini:[CREATE PLAYLIST]` 88 | } 89 | 90 | func main() { 91 | var player TunePlayer 92 | 93 | content, err := ioutil.ReadFile("./tunes.ini") 94 | if err != nil { 95 | log.Fatal(err) 96 | } 97 | 98 | err = ini.Unmarshal(content, &player) 99 | if err != nil { 100 | log.Fatal(err) 101 | } 102 | 103 | // Output same struct as JSON to verify parsing worked 104 | enc := json.NewEncoder(os.Stdout) 105 | if err := enc.Encode(&player); err != nil { 106 | log.Println(err) 107 | } 108 | } 109 | 110 | 111 | 112 | 113 | 114 | Todo 115 | ===== 116 | 117 | Need to parse inner array of structs 118 | 119 | struct { 120 | Playlists []struct { 121 | Id int 122 | Title string 123 | Programs []struct { 124 | Id int 125 | Mix string 126 | Separation int 127 | } `ini:"Play Program"` 128 | } `ini:"[CREATE PLAYLIST]"` 129 | } 130 | 131 | [CREATE PLAYLIST] 132 | ID=6524 133 | Title=Pop 134 | Start Schedule 135 | 136 | Play Program 137 | ID=391 138 | Mix=RAND 139 | 140 | Play Program 141 | ID=3912 142 | Separation=10 143 | End Schedule 144 | -------------------------------------------------------------------------------- /vendor/github.com/zackbloom/go-ini/stack.go: -------------------------------------------------------------------------------- 1 | package ini 2 | 3 | // NewStack returns a new stack. 4 | func NewStack() *Stack { 5 | return &Stack{} 6 | } 7 | 8 | // Stack is a basic LIFO stack that resizes as needed. 9 | type Stack struct { 10 | items []interface{} 11 | count int 12 | } 13 | 14 | // Push adds an iterm to the top of the stack 15 | func (s *Stack) Push(item interface{}) { 16 | s.items = append(s.items[:s.count], item) 17 | s.count++ 18 | } 19 | 20 | // Pop removes the top item (LIFO) from the stack 21 | func (s *Stack) Pop() interface{} { 22 | if s.count == 0 { 23 | return nil 24 | } 25 | 26 | s.count-- 27 | return s.items[s.count] 28 | } 29 | 30 | // Peek returns item at top of stack without removing it 31 | func (s *Stack) Peek() interface{} { 32 | if s.count == 0 { 33 | return nil 34 | } 35 | 36 | return s.items[s.count-1] 37 | } 38 | 39 | // Empty returns true when stack is empty, false otherwise 40 | func (s *Stack) Empty() bool { 41 | return s.count == 0 42 | } 43 | 44 | // Size returns the number of items in the stack 45 | func (s *Stack) Size() int { 46 | return s.count 47 | } 48 | -------------------------------------------------------------------------------- /vendor/github.com/zackbloom/goamz/LICENSE: -------------------------------------------------------------------------------- 1 | This software is licensed under the LGPLv3, included below. 2 | 3 | As a special exception to the GNU Lesser General Public License version 3 4 | ("LGPL3"), the copyright holders of this Library give you permission to 5 | convey to a third party a Combined Work that links statically or dynamically 6 | to this Library without providing any Minimal Corresponding Source or 7 | Minimal Application Code as set out in 4d or providing the installation 8 | information set out in section 4e, provided that you comply with the other 9 | provisions of LGPL3 and provided that you meet, for the Application the 10 | terms and conditions of the license(s) which apply to the Application. 11 | 12 | Except as stated in this special exception, the provisions of LGPL3 will 13 | continue to comply in full to this Library. If you modify this Library, you 14 | may apply this exception to your version of this Library, but you are not 15 | obliged to do so. If you do not wish to do so, delete this exception 16 | statement from your version. This exception does not (and cannot) modify any 17 | license terms which apply to the Application, with which you must still 18 | comply. 19 | 20 | 21 | GNU LESSER GENERAL PUBLIC LICENSE 22 | Version 3, 29 June 2007 23 | 24 | Copyright (C) 2007 Free Software Foundation, Inc. 25 | Everyone is permitted to copy and distribute verbatim copies 26 | of this license document, but changing it is not allowed. 27 | 28 | 29 | This version of the GNU Lesser General Public License incorporates 30 | the terms and conditions of version 3 of the GNU General Public 31 | License, supplemented by the additional permissions listed below. 32 | 33 | 0. Additional Definitions. 34 | 35 | As used herein, "this License" refers to version 3 of the GNU Lesser 36 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 37 | General Public License. 38 | 39 | "The Library" refers to a covered work governed by this License, 40 | other than an Application or a Combined Work as defined below. 41 | 42 | An "Application" is any work that makes use of an interface provided 43 | by the Library, but which is not otherwise based on the Library. 44 | Defining a subclass of a class defined by the Library is deemed a mode 45 | of using an interface provided by the Library. 46 | 47 | A "Combined Work" is a work produced by combining or linking an 48 | Application with the Library. The particular version of the Library 49 | with which the Combined Work was made is also called the "Linked 50 | Version". 51 | 52 | The "Minimal Corresponding Source" for a Combined Work means the 53 | Corresponding Source for the Combined Work, excluding any source code 54 | for portions of the Combined Work that, considered in isolation, are 55 | based on the Application, and not on the Linked Version. 56 | 57 | The "Corresponding Application Code" for a Combined Work means the 58 | object code and/or source code for the Application, including any data 59 | and utility programs needed for reproducing the Combined Work from the 60 | Application, but excluding the System Libraries of the Combined Work. 61 | 62 | 1. Exception to Section 3 of the GNU GPL. 63 | 64 | You may convey a covered work under sections 3 and 4 of this License 65 | without being bound by section 3 of the GNU GPL. 66 | 67 | 2. Conveying Modified Versions. 68 | 69 | If you modify a copy of the Library, and, in your modifications, a 70 | facility refers to a function or data to be supplied by an Application 71 | that uses the facility (other than as an argument passed when the 72 | facility is invoked), then you may convey a copy of the modified 73 | version: 74 | 75 | a) under this License, provided that you make a good faith effort to 76 | ensure that, in the event an Application does not supply the 77 | function or data, the facility still operates, and performs 78 | whatever part of its purpose remains meaningful, or 79 | 80 | b) under the GNU GPL, with none of the additional permissions of 81 | this License applicable to that copy. 82 | 83 | 3. Object Code Incorporating Material from Library Header Files. 84 | 85 | The object code form of an Application may incorporate material from 86 | a header file that is part of the Library. You may convey such object 87 | code under terms of your choice, provided that, if the incorporated 88 | material is not limited to numerical parameters, data structure 89 | layouts and accessors, or small macros, inline functions and templates 90 | (ten or fewer lines in length), you do both of the following: 91 | 92 | a) Give prominent notice with each copy of the object code that the 93 | Library is used in it and that the Library and its use are 94 | covered by this License. 95 | 96 | b) Accompany the object code with a copy of the GNU GPL and this license 97 | document. 98 | 99 | 4. Combined Works. 100 | 101 | You may convey a Combined Work under terms of your choice that, 102 | taken together, effectively do not restrict modification of the 103 | portions of the Library contained in the Combined Work and reverse 104 | engineering for debugging such modifications, if you also do each of 105 | the following: 106 | 107 | a) Give prominent notice with each copy of the Combined Work that 108 | the Library is used in it and that the Library and its use are 109 | covered by this License. 110 | 111 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 112 | document. 113 | 114 | c) For a Combined Work that displays copyright notices during 115 | execution, include the copyright notice for the Library among 116 | these notices, as well as a reference directing the user to the 117 | copies of the GNU GPL and this license document. 118 | 119 | d) Do one of the following: 120 | 121 | 0) Convey the Minimal Corresponding Source under the terms of this 122 | License, and the Corresponding Application Code in a form 123 | suitable for, and under terms that permit, the user to 124 | recombine or relink the Application with a modified version of 125 | the Linked Version to produce a modified Combined Work, in the 126 | manner specified by section 6 of the GNU GPL for conveying 127 | Corresponding Source. 128 | 129 | 1) Use a suitable shared library mechanism for linking with the 130 | Library. A suitable mechanism is one that (a) uses at run time 131 | a copy of the Library already present on the user's computer 132 | system, and (b) will operate properly with a modified version 133 | of the Library that is interface-compatible with the Linked 134 | Version. 135 | 136 | e) Provide Installation Information, but only if you would otherwise 137 | be required to provide such information under section 6 of the 138 | GNU GPL, and only to the extent that such information is 139 | necessary to install and execute a modified version of the 140 | Combined Work produced by recombining or relinking the 141 | Application with a modified version of the Linked Version. (If 142 | you use option 4d0, the Installation Information must accompany 143 | the Minimal Corresponding Source and Corresponding Application 144 | Code. If you use option 4d1, you must provide the Installation 145 | Information in the manner specified by section 6 of the GNU GPL 146 | for conveying Corresponding Source.) 147 | 148 | 5. Combined Libraries. 149 | 150 | You may place library facilities that are a work based on the 151 | Library side by side in a single library together with other library 152 | facilities that are not Applications and are not covered by this 153 | License, and convey such a combined library under terms of your 154 | choice, if you do both of the following: 155 | 156 | a) Accompany the combined library with a copy of the same work based 157 | on the Library, uncombined with any other library facilities, 158 | conveyed under the terms of this License. 159 | 160 | b) Give prominent notice with the combined library that part of it 161 | is a work based on the Library, and explaining where to find the 162 | accompanying uncombined form of the same work. 163 | 164 | 6. Revised Versions of the GNU Lesser General Public License. 165 | 166 | The Free Software Foundation may publish revised and/or new versions 167 | of the GNU Lesser General Public License from time to time. Such new 168 | versions will be similar in spirit to the present version, but may 169 | differ in detail to address new problems or concerns. 170 | 171 | Each version is given a distinguishing version number. If the 172 | Library as you received it specifies that a certain numbered version 173 | of the GNU Lesser General Public License "or any later version" 174 | applies to it, you have the option of following the terms and 175 | conditions either of that published version or of any later version 176 | published by the Free Software Foundation. If the Library as you 177 | received it does not specify a version number of the GNU Lesser 178 | General Public License, you may choose any version of the GNU Lesser 179 | General Public License ever published by the Free Software Foundation. 180 | 181 | If the Library as you received it specifies that a proxy can decide 182 | whether future versions of the GNU Lesser General Public License shall 183 | apply, that proxy's public statement of acceptance of any version is 184 | permanent authorization for you to choose that version for the 185 | Library. 186 | -------------------------------------------------------------------------------- /vendor/github.com/zackbloom/goamz/aws/attempt.go: -------------------------------------------------------------------------------- 1 | package aws 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // AttemptStrategy represents a strategy for waiting for an action 8 | // to complete successfully. This is an internal type used by the 9 | // implementation of other goamz packages. 10 | type AttemptStrategy struct { 11 | Total time.Duration // total duration of attempt. 12 | Delay time.Duration // interval between each try in the burst. 13 | Min int // minimum number of retries; overrides Total 14 | } 15 | 16 | type Attempt struct { 17 | strategy AttemptStrategy 18 | last time.Time 19 | end time.Time 20 | force bool 21 | count int 22 | } 23 | 24 | // Start begins a new sequence of attempts for the given strategy. 25 | func (s AttemptStrategy) Start() *Attempt { 26 | now := time.Now() 27 | return &Attempt{ 28 | strategy: s, 29 | last: now, 30 | end: now.Add(s.Total), 31 | force: true, 32 | } 33 | } 34 | 35 | // Next waits until it is time to perform the next attempt or returns 36 | // false if it is time to stop trying. 37 | func (a *Attempt) Next() bool { 38 | now := time.Now() 39 | sleep := a.nextSleep(now) 40 | if !a.force && !now.Add(sleep).Before(a.end) && a.strategy.Min <= a.count { 41 | return false 42 | } 43 | a.force = false 44 | if sleep > 0 && a.count > 0 { 45 | time.Sleep(sleep) 46 | now = time.Now() 47 | } 48 | a.count++ 49 | a.last = now 50 | return true 51 | } 52 | 53 | func (a *Attempt) nextSleep(now time.Time) time.Duration { 54 | sleep := a.strategy.Delay - now.Sub(a.last) 55 | if sleep < 0 { 56 | return 0 57 | } 58 | return sleep 59 | } 60 | 61 | // HasNext returns whether another attempt will be made if the current 62 | // one fails. If it returns true, the following call to Next is 63 | // guaranteed to return true. 64 | func (a *Attempt) HasNext() bool { 65 | if a.force || a.strategy.Min > a.count { 66 | return true 67 | } 68 | now := time.Now() 69 | if now.Add(a.nextSleep(now)).Before(a.end) { 70 | a.force = true 71 | return true 72 | } 73 | return false 74 | } 75 | -------------------------------------------------------------------------------- /vendor/github.com/zackbloom/goamz/aws/client.go: -------------------------------------------------------------------------------- 1 | package aws 2 | 3 | import ( 4 | "math" 5 | "net" 6 | "net/http" 7 | "time" 8 | ) 9 | 10 | type RetryableFunc func(*http.Request, *http.Response, error) bool 11 | type WaitFunc func(try int) 12 | type DeadlineFunc func() time.Time 13 | 14 | type ResilientTransport struct { 15 | // Timeout is the maximum amount of time a dial will wait for 16 | // a connect to complete. 17 | // 18 | // The default is no timeout. 19 | // 20 | // With or without a timeout, the operating system may impose 21 | // its own earlier timeout. For instance, TCP timeouts are 22 | // often around 3 minutes. 23 | DialTimeout time.Duration 24 | 25 | // MaxTries, if non-zero, specifies the number of times we will retry on 26 | // failure. Retries are only attempted for temporary network errors or known 27 | // safe failures. 28 | MaxTries int 29 | Deadline DeadlineFunc 30 | ShouldRetry RetryableFunc 31 | Wait WaitFunc 32 | transport *http.Transport 33 | } 34 | 35 | // Convenience method for creating an http client 36 | func NewClient(rt *ResilientTransport) *http.Client { 37 | rt.transport = &http.Transport{ 38 | Dial: func(netw, addr string) (net.Conn, error) { 39 | c, err := net.DialTimeout(netw, addr, rt.DialTimeout) 40 | if err != nil { 41 | return nil, err 42 | } 43 | c.SetDeadline(rt.Deadline()) 44 | return c, nil 45 | }, 46 | Proxy: http.ProxyFromEnvironment, 47 | } 48 | // TODO: Would be nice is ResilientTransport allowed clients to initialize 49 | // with http.Transport attributes. 50 | return &http.Client{ 51 | Transport: rt, 52 | } 53 | } 54 | 55 | var retryingTransport = &ResilientTransport{ 56 | Deadline: func() time.Time { 57 | return time.Now().Add(5 * time.Second) 58 | }, 59 | DialTimeout: 10 * time.Second, 60 | MaxTries: 3, 61 | ShouldRetry: awsRetry, 62 | Wait: ExpBackoff, 63 | } 64 | 65 | // Exported default client 66 | var RetryingClient = NewClient(retryingTransport) 67 | 68 | func (t *ResilientTransport) RoundTrip(req *http.Request) (*http.Response, error) { 69 | return t.tries(req) 70 | } 71 | 72 | // Retry a request a maximum of t.MaxTries times. 73 | // We'll only retry if the proper criteria are met. 74 | // If a wait function is specified, wait that amount of time 75 | // In between requests. 76 | func (t *ResilientTransport) tries(req *http.Request) (res *http.Response, err error) { 77 | for try := 0; try < t.MaxTries; try += 1 { 78 | res, err = t.transport.RoundTrip(req) 79 | 80 | if !t.ShouldRetry(req, res, err) { 81 | break 82 | } 83 | if res != nil { 84 | res.Body.Close() 85 | } 86 | if t.Wait != nil { 87 | t.Wait(try) 88 | } 89 | } 90 | 91 | return 92 | } 93 | 94 | func ExpBackoff(try int) { 95 | time.Sleep(100 * time.Millisecond * 96 | time.Duration(math.Exp2(float64(try)))) 97 | } 98 | 99 | func LinearBackoff(try int) { 100 | time.Sleep(time.Duration(try*100) * time.Millisecond) 101 | } 102 | 103 | // Decide if we should retry a request. 104 | // In general, the criteria for retrying a request is described here 105 | // http://docs.aws.amazon.com/general/latest/gr/api-retries.html 106 | func awsRetry(req *http.Request, res *http.Response, err error) bool { 107 | retry := false 108 | 109 | // Retry if there's a temporary network error. 110 | if neterr, ok := err.(net.Error); ok { 111 | if neterr.Temporary() { 112 | retry = true 113 | } 114 | } 115 | 116 | // Retry if we get a 5xx series error. 117 | if res != nil { 118 | if res.StatusCode >= 500 && res.StatusCode < 600 { 119 | retry = true 120 | } 121 | } 122 | 123 | return retry 124 | } 125 | -------------------------------------------------------------------------------- /vendor/github.com/zackbloom/goamz/aws/regions.go: -------------------------------------------------------------------------------- 1 | package aws 2 | 3 | var USGovWest = Region{ 4 | "us-gov-west-1", 5 | "https://ec2.us-gov-west-1.amazonaws.com", 6 | "https://s3-fips-us-gov-west-1.amazonaws.com", 7 | "", 8 | true, 9 | true, 10 | "", 11 | "https://sns.us-gov-west-1.amazonaws.com", 12 | "https://sqs.us-gov-west-1.amazonaws.com", 13 | "", 14 | "https://iam.us-gov.amazonaws.com", 15 | "https://elasticloadbalancing.us-gov-west-1.amazonaws.com", 16 | "https://dynamodb.us-gov-west-1.amazonaws.com", 17 | ServiceInfo{"https://monitoring.us-gov-west-1.amazonaws.com", V2Signature}, 18 | "https://autoscaling.us-gov-west-1.amazonaws.com", 19 | ServiceInfo{"https://rds.us-gov-west-1.amazonaws.com", V2Signature}, 20 | "", 21 | "https://sts.amazonaws.com", 22 | "https://cloudformation.us-gov-west-1.amazonaws.com", 23 | "", 24 | } 25 | 26 | var USEast = Region{ 27 | "us-east-1", 28 | "https://ec2.us-east-1.amazonaws.com", 29 | "https://s3.amazonaws.com", 30 | "", 31 | false, 32 | false, 33 | "https://sdb.amazonaws.com", 34 | "https://sns.us-east-1.amazonaws.com", 35 | "https://sqs.us-east-1.amazonaws.com", 36 | "https://email.us-east-1.amazonaws.com", 37 | "https://iam.amazonaws.com", 38 | "https://elasticloadbalancing.us-east-1.amazonaws.com", 39 | "https://dynamodb.us-east-1.amazonaws.com", 40 | ServiceInfo{"https://monitoring.us-east-1.amazonaws.com", V2Signature}, 41 | "https://autoscaling.us-east-1.amazonaws.com", 42 | ServiceInfo{"https://rds.us-east-1.amazonaws.com", V2Signature}, 43 | "https://kinesis.us-east-1.amazonaws.com", 44 | "https://sts.amazonaws.com", 45 | "https://cloudformation.us-east-1.amazonaws.com", 46 | "https://elasticache.us-east-1.amazonaws.com", 47 | } 48 | 49 | var USWest = Region{ 50 | "us-west-1", 51 | "https://ec2.us-west-1.amazonaws.com", 52 | "https://s3-us-west-1.amazonaws.com", 53 | "", 54 | true, 55 | true, 56 | "https://sdb.us-west-1.amazonaws.com", 57 | "https://sns.us-west-1.amazonaws.com", 58 | "https://sqs.us-west-1.amazonaws.com", 59 | "", 60 | "https://iam.amazonaws.com", 61 | "https://elasticloadbalancing.us-west-1.amazonaws.com", 62 | "https://dynamodb.us-west-1.amazonaws.com", 63 | ServiceInfo{"https://monitoring.us-west-1.amazonaws.com", V2Signature}, 64 | "https://autoscaling.us-west-1.amazonaws.com", 65 | ServiceInfo{"https://rds.us-west-1.amazonaws.com", V2Signature}, 66 | "https://kinesis.us-west-1.amazonaws.com", 67 | "https://sts.amazonaws.com", 68 | "https://cloudformation.us-west-1.amazonaws.com", 69 | "https://elasticache.us-west-1.amazonaws.com", 70 | } 71 | 72 | var USWest2 = Region{ 73 | "us-west-2", 74 | "https://ec2.us-west-2.amazonaws.com", 75 | "https://s3-us-west-2.amazonaws.com", 76 | "", 77 | true, 78 | true, 79 | "https://sdb.us-west-2.amazonaws.com", 80 | "https://sns.us-west-2.amazonaws.com", 81 | "https://sqs.us-west-2.amazonaws.com", 82 | "https://email.us-west-2.amazonaws.com", 83 | "https://iam.amazonaws.com", 84 | "https://elasticloadbalancing.us-west-2.amazonaws.com", 85 | "https://dynamodb.us-west-2.amazonaws.com", 86 | ServiceInfo{"https://monitoring.us-west-2.amazonaws.com", V2Signature}, 87 | "https://autoscaling.us-west-2.amazonaws.com", 88 | ServiceInfo{"https://rds.us-west-2.amazonaws.com", V2Signature}, 89 | "https://kinesis.us-west-2.amazonaws.com", 90 | "https://sts.amazonaws.com", 91 | "https://cloudformation.us-west-2.amazonaws.com", 92 | "https://elasticache.us-west-2.amazonaws.com", 93 | } 94 | 95 | var EUWest = Region{ 96 | "eu-west-1", 97 | "https://ec2.eu-west-1.amazonaws.com", 98 | "https://s3-eu-west-1.amazonaws.com", 99 | "", 100 | true, 101 | true, 102 | "https://sdb.eu-west-1.amazonaws.com", 103 | "https://sns.eu-west-1.amazonaws.com", 104 | "https://sqs.eu-west-1.amazonaws.com", 105 | "https://email.eu-west-1.amazonaws.com", 106 | "https://iam.amazonaws.com", 107 | "https://elasticloadbalancing.eu-west-1.amazonaws.com", 108 | "https://dynamodb.eu-west-1.amazonaws.com", 109 | ServiceInfo{"https://monitoring.eu-west-1.amazonaws.com", V2Signature}, 110 | "https://autoscaling.eu-west-1.amazonaws.com", 111 | ServiceInfo{"https://rds.eu-west-1.amazonaws.com", V2Signature}, 112 | "https://kinesis.eu-west-1.amazonaws.com", 113 | "https://sts.amazonaws.com", 114 | "https://cloudformation.eu-west-1.amazonaws.com", 115 | "https://elasticache.eu-west-1.amazonaws.com", 116 | } 117 | 118 | var EUCentral = Region{ 119 | "eu-central-1", 120 | "https://ec2.eu-central-1.amazonaws.com", 121 | "https://s3-eu-central-1.amazonaws.com", 122 | "", 123 | true, 124 | true, 125 | "https://sdb.eu-central-1.amazonaws.com", 126 | "https://sns.eu-central-1.amazonaws.com", 127 | "https://sqs.eu-central-1.amazonaws.com", 128 | "", 129 | "https://iam.amazonaws.com", 130 | "https://elasticloadbalancing.eu-central-1.amazonaws.com", 131 | "https://dynamodb.eu-central-1.amazonaws.com", 132 | ServiceInfo{"https://monitoring.eu-central-1.amazonaws.com", V2Signature}, 133 | "https://autoscaling.eu-central-1.amazonaws.com", 134 | ServiceInfo{"https://rds.eu-central-1.amazonaws.com", V2Signature}, 135 | "https://kinesis.eu-central-1.amazonaws.com", 136 | "https://sts.amazonaws.com", 137 | "https://cloudformation.eu-central-1.amazonaws.com", 138 | "", 139 | } 140 | 141 | var APSoutheast = Region{ 142 | "ap-southeast-1", 143 | "https://ec2.ap-southeast-1.amazonaws.com", 144 | "https://s3-ap-southeast-1.amazonaws.com", 145 | "", 146 | true, 147 | true, 148 | "https://sdb.ap-southeast-1.amazonaws.com", 149 | "https://sns.ap-southeast-1.amazonaws.com", 150 | "https://sqs.ap-southeast-1.amazonaws.com", 151 | "", 152 | "https://iam.amazonaws.com", 153 | "https://elasticloadbalancing.ap-southeast-1.amazonaws.com", 154 | "https://dynamodb.ap-southeast-1.amazonaws.com", 155 | ServiceInfo{"https://monitoring.ap-southeast-1.amazonaws.com", V2Signature}, 156 | "https://autoscaling.ap-southeast-1.amazonaws.com", 157 | ServiceInfo{"https://rds.ap-southeast-1.amazonaws.com", V2Signature}, 158 | "https://kinesis.ap-southeast-1.amazonaws.com", 159 | "https://sts.amazonaws.com", 160 | "https://cloudformation.ap-southeast-1.amazonaws.com", 161 | "https://elasticache.ap-southeast-1.amazonaws.com", 162 | } 163 | 164 | var APSoutheast2 = Region{ 165 | "ap-southeast-2", 166 | "https://ec2.ap-southeast-2.amazonaws.com", 167 | "https://s3-ap-southeast-2.amazonaws.com", 168 | "", 169 | true, 170 | true, 171 | "https://sdb.ap-southeast-2.amazonaws.com", 172 | "https://sns.ap-southeast-2.amazonaws.com", 173 | "https://sqs.ap-southeast-2.amazonaws.com", 174 | "", 175 | "https://iam.amazonaws.com", 176 | "https://elasticloadbalancing.ap-southeast-2.amazonaws.com", 177 | "https://dynamodb.ap-southeast-2.amazonaws.com", 178 | ServiceInfo{"https://monitoring.ap-southeast-2.amazonaws.com", V2Signature}, 179 | "https://autoscaling.ap-southeast-2.amazonaws.com", 180 | ServiceInfo{"https://rds.ap-southeast-2.amazonaws.com", V2Signature}, 181 | "https://kinesis.ap-southeast-2.amazonaws.com", 182 | "https://sts.amazonaws.com", 183 | "https://cloudformation.ap-southeast-2.amazonaws.com", 184 | "https://elasticache.ap-southeast-2.amazonaws.com", 185 | } 186 | 187 | var APNortheast = Region{ 188 | "ap-northeast-1", 189 | "https://ec2.ap-northeast-1.amazonaws.com", 190 | "https://s3-ap-northeast-1.amazonaws.com", 191 | "", 192 | true, 193 | true, 194 | "https://sdb.ap-northeast-1.amazonaws.com", 195 | "https://sns.ap-northeast-1.amazonaws.com", 196 | "https://sqs.ap-northeast-1.amazonaws.com", 197 | "", 198 | "https://iam.amazonaws.com", 199 | "https://elasticloadbalancing.ap-northeast-1.amazonaws.com", 200 | "https://dynamodb.ap-northeast-1.amazonaws.com", 201 | ServiceInfo{"https://monitoring.ap-northeast-1.amazonaws.com", V2Signature}, 202 | "https://autoscaling.ap-northeast-1.amazonaws.com", 203 | ServiceInfo{"https://rds.ap-northeast-1.amazonaws.com", V2Signature}, 204 | "https://kinesis.ap-northeast-1.amazonaws.com", 205 | "https://sts.amazonaws.com", 206 | "https://cloudformation.ap-northeast-1.amazonaws.com", 207 | "https://elasticache.ap-northeast-1.amazonaws.com", 208 | } 209 | 210 | var SAEast = Region{ 211 | "sa-east-1", 212 | "https://ec2.sa-east-1.amazonaws.com", 213 | "https://s3-sa-east-1.amazonaws.com", 214 | "", 215 | true, 216 | true, 217 | "https://sdb.sa-east-1.amazonaws.com", 218 | "https://sns.sa-east-1.amazonaws.com", 219 | "https://sqs.sa-east-1.amazonaws.com", 220 | "", 221 | "https://iam.amazonaws.com", 222 | "https://elasticloadbalancing.sa-east-1.amazonaws.com", 223 | "https://dynamodb.sa-east-1.amazonaws.com", 224 | ServiceInfo{"https://monitoring.sa-east-1.amazonaws.com", V2Signature}, 225 | "https://autoscaling.sa-east-1.amazonaws.com", 226 | ServiceInfo{"https://rds.sa-east-1.amazonaws.com", V2Signature}, 227 | "", 228 | "https://sts.amazonaws.com", 229 | "https://cloudformation.sa-east-1.amazonaws.com", 230 | "https://elasticache.sa-east-1.amazonaws.com", 231 | } 232 | -------------------------------------------------------------------------------- /vendor/github.com/zackbloom/goamz/aws/retry.go: -------------------------------------------------------------------------------- 1 | package aws 2 | 3 | import ( 4 | "math/rand" 5 | "net" 6 | "net/http" 7 | "time" 8 | ) 9 | 10 | const ( 11 | maxDelay = 20 * time.Second 12 | defaultScale = 300 * time.Millisecond 13 | throttlingScale = 500 * time.Millisecond 14 | throttlingScaleRange = throttlingScale / 4 15 | defaultMaxRetries = 3 16 | dynamoDBScale = 25 * time.Millisecond 17 | dynamoDBMaxRetries = 10 18 | ) 19 | 20 | // A RetryPolicy encapsulates a strategy for implementing client retries. 21 | // 22 | // Default implementations are provided which match the AWS SDKs. 23 | type RetryPolicy interface { 24 | // ShouldRetry returns whether a client should retry a failed request. 25 | ShouldRetry(target string, r *http.Response, err error, numRetries int) bool 26 | 27 | // Delay returns the time a client should wait before issuing a retry. 28 | Delay(target string, r *http.Response, err error, numRetries int) time.Duration 29 | } 30 | 31 | // DefaultRetryPolicy implements the AWS SDK default retry policy. 32 | // 33 | // It will retry up to 3 times, and uses an exponential backoff with a scale 34 | // factor of 300ms (300ms, 600ms, 1200ms). If the retry is because of 35 | // throttling, the delay will also include some randomness. 36 | // 37 | // See https://github.com/aws/aws-sdk-java/blob/master/aws-java-sdk-core/src/main/java/com/amazonaws/retry/PredefinedRetryPolicies.java#L90. 38 | type DefaultRetryPolicy struct { 39 | } 40 | 41 | // ShouldRetry implements the RetryPolicy ShouldRetry method. 42 | func (policy DefaultRetryPolicy) ShouldRetry(target string, r *http.Response, err error, numRetries int) bool { 43 | return shouldRetry(r, err, numRetries, defaultMaxRetries) 44 | } 45 | 46 | // Delay implements the RetryPolicy Delay method. 47 | func (policy DefaultRetryPolicy) Delay(target string, r *http.Response, err error, numRetries int) time.Duration { 48 | scale := defaultScale 49 | if err, ok := err.(*Error); ok && isThrottlingException(err) { 50 | scale = throttlingScale + time.Duration(rand.Int63n(int64(throttlingScaleRange))) 51 | } 52 | return exponentialBackoff(numRetries, scale) 53 | } 54 | 55 | // DynamoDBRetryPolicy implements the AWS SDK DynamoDB retry policy. 56 | // 57 | // It will retry up to 10 times, and uses an exponential backoff with a scale 58 | // factor of 25ms (25ms, 50ms, 100ms, ...). 59 | // 60 | // See https://github.com/aws/aws-sdk-java/blob/master/aws-java-sdk-core/src/main/java/com/amazonaws/retry/PredefinedRetryPolicies.java#L103. 61 | type DynamoDBRetryPolicy struct { 62 | } 63 | 64 | // ShouldRetry implements the RetryPolicy ShouldRetry method. 65 | func (policy DynamoDBRetryPolicy) ShouldRetry(target string, r *http.Response, err error, numRetries int) bool { 66 | return shouldRetry(r, err, numRetries, dynamoDBMaxRetries) 67 | } 68 | 69 | // Delay implements the RetryPolicy Delay method. 70 | func (policy DynamoDBRetryPolicy) Delay(target string, r *http.Response, err error, numRetries int) time.Duration { 71 | return exponentialBackoff(numRetries, dynamoDBScale) 72 | } 73 | 74 | // NeverRetryPolicy never retries requests and returns immediately on failure. 75 | type NeverRetryPolicy struct { 76 | } 77 | 78 | // ShouldRetry implements the RetryPolicy ShouldRetry method. 79 | func (policy NeverRetryPolicy) ShouldRetry(target string, r *http.Response, err error, numRetries int) bool { 80 | return false 81 | } 82 | 83 | // Delay implements the RetryPolicy Delay method. 84 | func (policy NeverRetryPolicy) Delay(target string, r *http.Response, err error, numRetries int) time.Duration { 85 | return time.Duration(0) 86 | } 87 | 88 | // shouldRetry determines if we should retry the request. 89 | // 90 | // See http://docs.aws.amazon.com/general/latest/gr/api-retries.html. 91 | func shouldRetry(r *http.Response, err error, numRetries int, maxRetries int) bool { 92 | // Once we've exceeded the max retry attempts, game over. 93 | if numRetries >= maxRetries { 94 | return false 95 | } 96 | 97 | // Always retry temporary network errors. 98 | if err, ok := err.(net.Error); ok && err.Temporary() { 99 | return true 100 | } 101 | 102 | // Always retry 5xx responses. 103 | if r != nil && r.StatusCode >= 500 { 104 | return true 105 | } 106 | 107 | // Always retry throttling exceptions. 108 | if err, ok := err.(ServiceError); ok && isThrottlingException(err) { 109 | return true 110 | } 111 | 112 | // Other classes of failures indicate a problem with the request. Retrying 113 | // won't help. 114 | return false 115 | } 116 | 117 | func exponentialBackoff(numRetries int, scale time.Duration) time.Duration { 118 | if numRetries < 0 { 119 | return time.Duration(0) 120 | } 121 | 122 | delay := (1 << uint(numRetries)) * scale 123 | if delay > maxDelay { 124 | return maxDelay 125 | } 126 | return delay 127 | } 128 | 129 | func isThrottlingException(err ServiceError) bool { 130 | switch err.ErrorCode() { 131 | case "Throttling", "ThrottlingException", "ProvisionedThroughputExceededException": 132 | return true 133 | default: 134 | return false 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /vendor/github.com/zackbloom/goamz/iam/sign.go: -------------------------------------------------------------------------------- 1 | package iam 2 | 3 | import ( 4 | "crypto/hmac" 5 | "crypto/sha256" 6 | "encoding/base64" 7 | "github.com/zackbloom/goamz/aws" 8 | "sort" 9 | "strings" 10 | ) 11 | 12 | // ---------------------------------------------------------------------------- 13 | // Version 2 signing (http://goo.gl/RSRp5) 14 | 15 | var b64 = base64.StdEncoding 16 | 17 | func sign(auth aws.Auth, method, path string, params map[string]string, host string) { 18 | params["AWSAccessKeyId"] = auth.AccessKey 19 | params["SignatureVersion"] = "2" 20 | params["SignatureMethod"] = "HmacSHA256" 21 | if auth.Token() != "" { 22 | params["SecurityToken"] = auth.Token() 23 | } 24 | 25 | var sarray []string 26 | for k, v := range params { 27 | sarray = append(sarray, aws.Encode(k)+"="+aws.Encode(v)) 28 | } 29 | sort.StringSlice(sarray).Sort() 30 | joined := strings.Join(sarray, "&") 31 | payload := method + "\n" + host + "\n" + path + "\n" + joined 32 | hash := hmac.New(sha256.New, []byte(auth.SecretKey)) 33 | hash.Write([]byte(payload)) 34 | signature := make([]byte, b64.EncodedLen(hash.Size())) 35 | b64.Encode(signature, hash.Sum(nil)) 36 | 37 | params["Signature"] = string(signature) 38 | } 39 | -------------------------------------------------------------------------------- /vendor/github.com/zackbloom/goamz/s3/lifecycle.go: -------------------------------------------------------------------------------- 1 | package s3 2 | 3 | import ( 4 | "crypto/md5" 5 | "encoding/base64" 6 | "encoding/xml" 7 | "net/url" 8 | "strconv" 9 | "time" 10 | ) 11 | 12 | // Implements an interface for s3 bucket lifecycle configuration 13 | // See goo.gl/d0bbDf for details. 14 | 15 | const ( 16 | LifecycleRuleStatusEnabled = "Enabled" 17 | LifecycleRuleStatusDisabled = "Disabled" 18 | LifecycleRuleDateFormat = "2006-01-02" 19 | StorageClassGlacier = "GLACIER" 20 | ) 21 | 22 | type Expiration struct { 23 | Days *uint `xml:"Days,omitempty"` 24 | Date string `xml:"Date,omitempty"` 25 | } 26 | 27 | // Returns Date as a time.Time. 28 | func (r *Expiration) ParseDate() (time.Time, error) { 29 | return time.Parse(LifecycleRuleDateFormat, r.Date) 30 | } 31 | 32 | type Transition struct { 33 | Days *uint `xml:"Days,omitempty"` 34 | Date string `xml:"Date,omitempty"` 35 | StorageClass string `xml:"StorageClass"` 36 | } 37 | 38 | // Returns Date as a time.Time. 39 | func (r *Transition) ParseDate() (time.Time, error) { 40 | return time.Parse(LifecycleRuleDateFormat, r.Date) 41 | } 42 | 43 | type NoncurrentVersionExpiration struct { 44 | Days *uint `xml:"NoncurrentDays,omitempty"` 45 | } 46 | 47 | type NoncurrentVersionTransition struct { 48 | Days *uint `xml:"NoncurrentDays,omitempty"` 49 | StorageClass string `xml:"StorageClass"` 50 | } 51 | 52 | type LifecycleRule struct { 53 | ID string `xml:"ID"` 54 | Prefix string `xml:"Prefix"` 55 | Status string `xml:"Status"` 56 | NoncurrentVersionTransition *NoncurrentVersionTransition `xml:"NoncurrentVersionTransition,omitempty"` 57 | NoncurrentVersionExpiration *NoncurrentVersionExpiration `xml:"NoncurrentVersionExpiration,omitempty"` 58 | Transition *Transition `xml:"Transition,omitempty"` 59 | Expiration *Expiration `xml:"Expiration,omitempty"` 60 | } 61 | 62 | // Create a lifecycle rule with arbitrary identifier id and object name prefix 63 | // for which the rules should apply. 64 | func NewLifecycleRule(id, prefix string) *LifecycleRule { 65 | rule := &LifecycleRule{ 66 | ID: id, 67 | Prefix: prefix, 68 | Status: LifecycleRuleStatusEnabled, 69 | } 70 | return rule 71 | } 72 | 73 | // Adds a transition rule in days. Overwrites any previous transition rule. 74 | func (r *LifecycleRule) SetTransitionDays(days uint) { 75 | r.Transition = &Transition{ 76 | Days: &days, 77 | StorageClass: StorageClassGlacier, 78 | } 79 | } 80 | 81 | // Adds a transition rule as a date. Overwrites any previous transition rule. 82 | func (r *LifecycleRule) SetTransitionDate(date time.Time) { 83 | r.Transition = &Transition{ 84 | Date: date.Format(LifecycleRuleDateFormat), 85 | StorageClass: StorageClassGlacier, 86 | } 87 | } 88 | 89 | // Adds an expiration rule in days. Overwrites any previous expiration rule. 90 | // Days must be > 0. 91 | func (r *LifecycleRule) SetExpirationDays(days uint) { 92 | r.Expiration = &Expiration{ 93 | Days: &days, 94 | } 95 | } 96 | 97 | // Adds an expiration rule as a date. Overwrites any previous expiration rule. 98 | func (r *LifecycleRule) SetExpirationDate(date time.Time) { 99 | r.Expiration = &Expiration{ 100 | Date: date.Format(LifecycleRuleDateFormat), 101 | } 102 | } 103 | 104 | // Adds a noncurrent version transition rule. Overwrites any previous 105 | // noncurrent version transition rule. 106 | func (r *LifecycleRule) SetNoncurrentVersionTransitionDays(days uint) { 107 | r.NoncurrentVersionTransition = &NoncurrentVersionTransition{ 108 | Days: &days, 109 | StorageClass: StorageClassGlacier, 110 | } 111 | } 112 | 113 | // Adds a noncurrent version expiration rule. Days must be > 0. Overwrites 114 | // any previous noncurrent version expiration rule. 115 | func (r *LifecycleRule) SetNoncurrentVersionExpirationDays(days uint) { 116 | r.NoncurrentVersionExpiration = &NoncurrentVersionExpiration{ 117 | Days: &days, 118 | } 119 | } 120 | 121 | // Marks the rule as disabled. 122 | func (r *LifecycleRule) Disable() { 123 | r.Status = LifecycleRuleStatusDisabled 124 | } 125 | 126 | // Marks the rule as enabled (default). 127 | func (r *LifecycleRule) Enable() { 128 | r.Status = LifecycleRuleStatusEnabled 129 | } 130 | 131 | type LifecycleConfiguration struct { 132 | XMLName xml.Name `xml:"LifecycleConfiguration"` 133 | Rules *[]*LifecycleRule `xml:"Rule,omitempty"` 134 | } 135 | 136 | // Adds a LifecycleRule to the configuration. 137 | func (c *LifecycleConfiguration) AddRule(r *LifecycleRule) { 138 | var rules []*LifecycleRule 139 | if c.Rules != nil { 140 | rules = *c.Rules 141 | } 142 | rules = append(rules, r) 143 | c.Rules = &rules 144 | } 145 | 146 | // Sets the bucket's lifecycle configuration. 147 | func (b *Bucket) PutLifecycleConfiguration(c *LifecycleConfiguration) error { 148 | doc, err := xml.Marshal(c) 149 | if err != nil { 150 | return err 151 | } 152 | 153 | buf := makeXmlBuffer(doc) 154 | digest := md5.New() 155 | size, err := digest.Write(buf.Bytes()) 156 | if err != nil { 157 | return err 158 | } 159 | 160 | headers := map[string][]string{ 161 | "Content-Length": {strconv.FormatInt(int64(size), 10)}, 162 | "Content-MD5": {base64.StdEncoding.EncodeToString(digest.Sum(nil))}, 163 | } 164 | 165 | req := &request{ 166 | path: "/", 167 | method: "PUT", 168 | bucket: b.Name, 169 | headers: headers, 170 | payload: buf, 171 | params: url.Values{"lifecycle": {""}}, 172 | } 173 | 174 | return b.S3.queryV4Sign(req, nil) 175 | } 176 | 177 | // Retrieves the lifecycle configuration for the bucket. AWS returns an error 178 | // if no lifecycle found. 179 | func (b *Bucket) GetLifecycleConfiguration() (*LifecycleConfiguration, error) { 180 | req := &request{ 181 | method: "GET", 182 | bucket: b.Name, 183 | path: "/", 184 | params: url.Values{"lifecycle": {""}}, 185 | } 186 | 187 | conf := &LifecycleConfiguration{} 188 | err := b.S3.queryV4Sign(req, conf) 189 | return conf, err 190 | } 191 | 192 | // Delete the bucket's lifecycle configuration. 193 | func (b *Bucket) DeleteLifecycleConfiguration() error { 194 | req := &request{ 195 | method: "DELETE", 196 | bucket: b.Name, 197 | path: "/", 198 | params: url.Values{"lifecycle": {""}}, 199 | } 200 | 201 | return b.S3.queryV4Sign(req, nil) 202 | } 203 | -------------------------------------------------------------------------------- /vendor/github.com/zackbloom/goamz/s3/sign.go: -------------------------------------------------------------------------------- 1 | package s3 2 | 3 | import ( 4 | "crypto/hmac" 5 | "crypto/sha1" 6 | "encoding/base64" 7 | "github.com/zackbloom/goamz/aws" 8 | "log" 9 | "sort" 10 | "strings" 11 | ) 12 | 13 | var b64 = base64.StdEncoding 14 | 15 | // ---------------------------------------------------------------------------- 16 | // S3 signing (http://goo.gl/G1LrK) 17 | 18 | var s3ParamsToSign = map[string]bool{ 19 | "acl": true, 20 | "location": true, 21 | "logging": true, 22 | "notification": true, 23 | "partNumber": true, 24 | "policy": true, 25 | "requestPayment": true, 26 | "torrent": true, 27 | "uploadId": true, 28 | "uploads": true, 29 | "versionId": true, 30 | "versioning": true, 31 | "versions": true, 32 | "response-content-type": true, 33 | "response-content-language": true, 34 | "response-expires": true, 35 | "response-cache-control": true, 36 | "response-content-disposition": true, 37 | "response-content-encoding": true, 38 | "website": true, 39 | "delete": true, 40 | } 41 | 42 | func sign(auth aws.Auth, method, canonicalPath string, params, headers map[string][]string) { 43 | var md5, ctype, date, xamz string 44 | var xamzDate bool 45 | var keys, sarray []string 46 | xheaders := make(map[string]string) 47 | for k, v := range headers { 48 | k = strings.ToLower(k) 49 | switch k { 50 | case "content-md5": 51 | md5 = v[0] 52 | case "content-type": 53 | ctype = v[0] 54 | case "date": 55 | if !xamzDate { 56 | date = v[0] 57 | } 58 | default: 59 | if strings.HasPrefix(k, "x-amz-") { 60 | keys = append(keys, k) 61 | xheaders[k] = strings.Join(v, ",") 62 | if k == "x-amz-date" { 63 | xamzDate = true 64 | date = "" 65 | } 66 | } 67 | } 68 | } 69 | if len(keys) > 0 { 70 | sort.StringSlice(keys).Sort() 71 | for i := range keys { 72 | key := keys[i] 73 | value := xheaders[key] 74 | sarray = append(sarray, key+":"+value) 75 | } 76 | xamz = strings.Join(sarray, "\n") + "\n" 77 | } 78 | 79 | expires := false 80 | if v, ok := params["Expires"]; ok { 81 | // Query string request authentication alternative. 82 | expires = true 83 | date = v[0] 84 | params["AWSAccessKeyId"] = []string{auth.AccessKey} 85 | } 86 | 87 | sarray = sarray[0:0] 88 | for k, v := range params { 89 | if s3ParamsToSign[k] { 90 | for _, vi := range v { 91 | if vi == "" { 92 | sarray = append(sarray, k) 93 | } else { 94 | // "When signing you do not encode these values." 95 | sarray = append(sarray, k+"="+vi) 96 | } 97 | } 98 | } 99 | } 100 | if len(sarray) > 0 { 101 | sort.StringSlice(sarray).Sort() 102 | canonicalPath = canonicalPath + "?" + strings.Join(sarray, "&") 103 | } 104 | 105 | payload := method + "\n" + md5 + "\n" + ctype + "\n" + date + "\n" + xamz + canonicalPath 106 | hash := hmac.New(sha1.New, []byte(auth.SecretKey)) 107 | hash.Write([]byte(payload)) 108 | signature := make([]byte, b64.EncodedLen(hash.Size())) 109 | b64.Encode(signature, hash.Sum(nil)) 110 | 111 | if expires { 112 | params["Signature"] = []string{string(signature)} 113 | } else { 114 | headers["Authorization"] = []string{"AWS " + auth.AccessKey + ":" + string(signature)} 115 | } 116 | if debug { 117 | log.Printf("Signature payload: %q", payload) 118 | log.Printf("Signature: %q", signature) 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/ssh/terminal/util.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build darwin dragonfly freebsd linux,!appengine netbsd openbsd 6 | 7 | // Package terminal provides support functions for dealing with terminals, as 8 | // commonly found on UNIX systems. 9 | // 10 | // Putting a terminal into raw mode is the most common requirement: 11 | // 12 | // oldState, err := terminal.MakeRaw(0) 13 | // if err != nil { 14 | // panic(err) 15 | // } 16 | // defer terminal.Restore(0, oldState) 17 | package terminal 18 | 19 | import ( 20 | "io" 21 | "syscall" 22 | "unsafe" 23 | ) 24 | 25 | // State contains the state of a terminal. 26 | type State struct { 27 | termios syscall.Termios 28 | } 29 | 30 | // IsTerminal returns true if the given file descriptor is a terminal. 31 | func IsTerminal(fd int) bool { 32 | var termios syscall.Termios 33 | _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) 34 | return err == 0 35 | } 36 | 37 | // MakeRaw put the terminal connected to the given file descriptor into raw 38 | // mode and returns the previous state of the terminal so that it can be 39 | // restored. 40 | func MakeRaw(fd int) (*State, error) { 41 | var oldState State 42 | if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 { 43 | return nil, err 44 | } 45 | 46 | newState := oldState.termios 47 | newState.Iflag &^= syscall.ISTRIP | syscall.INLCR | syscall.ICRNL | syscall.IGNCR | syscall.IXON | syscall.IXOFF 48 | newState.Lflag &^= syscall.ECHO | syscall.ICANON | syscall.ISIG 49 | if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 { 50 | return nil, err 51 | } 52 | 53 | return &oldState, nil 54 | } 55 | 56 | // GetState returns the current state of a terminal which may be useful to 57 | // restore the terminal after a signal. 58 | func GetState(fd int) (*State, error) { 59 | var oldState State 60 | if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 { 61 | return nil, err 62 | } 63 | 64 | return &oldState, nil 65 | } 66 | 67 | // Restore restores the terminal connected to the given file descriptor to a 68 | // previous state. 69 | func Restore(fd int, state *State) error { 70 | _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&state.termios)), 0, 0, 0) 71 | return err 72 | } 73 | 74 | // GetSize returns the dimensions of the given terminal. 75 | func GetSize(fd int) (width, height int, err error) { 76 | var dimensions [4]uint16 77 | 78 | if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&dimensions)), 0, 0, 0); err != 0 { 79 | return -1, -1, err 80 | } 81 | return int(dimensions[1]), int(dimensions[0]), nil 82 | } 83 | 84 | // ReadPassword reads a line of input from a terminal without local echo. This 85 | // is commonly used for inputting passwords and other sensitive data. The slice 86 | // returned does not include the \n. 87 | func ReadPassword(fd int) ([]byte, error) { 88 | var oldState syscall.Termios 89 | if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0); err != 0 { 90 | return nil, err 91 | } 92 | 93 | newState := oldState 94 | newState.Lflag &^= syscall.ECHO 95 | newState.Lflag |= syscall.ICANON | syscall.ISIG 96 | newState.Iflag |= syscall.ICRNL 97 | if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 { 98 | return nil, err 99 | } 100 | 101 | defer func() { 102 | syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0) 103 | }() 104 | 105 | var buf [16]byte 106 | var ret []byte 107 | for { 108 | n, err := syscall.Read(fd, buf[:]) 109 | if err != nil { 110 | return nil, err 111 | } 112 | if n == 0 { 113 | if len(ret) == 0 { 114 | return nil, io.EOF 115 | } 116 | break 117 | } 118 | if buf[n-1] == '\n' { 119 | n-- 120 | } 121 | ret = append(ret, buf[:n]...) 122 | if n < len(buf) { 123 | break 124 | } 125 | } 126 | 127 | return ret, nil 128 | } 129 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build darwin dragonfly freebsd netbsd openbsd 6 | 7 | package terminal 8 | 9 | import "syscall" 10 | 11 | const ioctlReadTermios = syscall.TIOCGETA 12 | const ioctlWriteTermios = syscall.TIOCSETA 13 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/ssh/terminal/util_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package terminal 6 | 7 | // These constants are declared here, rather than importing 8 | // them from the syscall package as some syscall packages, even 9 | // on linux, for example gccgo, do not declare them. 10 | const ioctlReadTermios = 0x5401 // syscall.TCGETS 11 | const ioctlWriteTermios = 0x5402 // syscall.TCSETS 12 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package terminal provides support functions for dealing with terminals, as 6 | // commonly found on UNIX systems. 7 | // 8 | // Putting a terminal into raw mode is the most common requirement: 9 | // 10 | // oldState, err := terminal.MakeRaw(0) 11 | // if err != nil { 12 | // panic(err) 13 | // } 14 | // defer terminal.Restore(0, oldState) 15 | package terminal 16 | 17 | import ( 18 | "fmt" 19 | "runtime" 20 | ) 21 | 22 | type State struct{} 23 | 24 | // IsTerminal returns true if the given file descriptor is a terminal. 25 | func IsTerminal(fd int) bool { 26 | return false 27 | } 28 | 29 | // MakeRaw put the terminal connected to the given file descriptor into raw 30 | // mode and returns the previous state of the terminal so that it can be 31 | // restored. 32 | func MakeRaw(fd int) (*State, error) { 33 | return nil, fmt.Errorf("terminal: MakeRaw not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) 34 | } 35 | 36 | // GetState returns the current state of a terminal which may be useful to 37 | // restore the terminal after a signal. 38 | func GetState(fd int) (*State, error) { 39 | return nil, fmt.Errorf("terminal: GetState not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) 40 | } 41 | 42 | // Restore restores the terminal connected to the given file descriptor to a 43 | // previous state. 44 | func Restore(fd int, state *State) error { 45 | return fmt.Errorf("terminal: Restore not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) 46 | } 47 | 48 | // GetSize returns the dimensions of the given terminal. 49 | func GetSize(fd int) (width, height int, err error) { 50 | return 0, 0, fmt.Errorf("terminal: GetSize not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) 51 | } 52 | 53 | // ReadPassword reads a line of input from a terminal without local echo. This 54 | // is commonly used for inputting passwords and other sensitive data. The slice 55 | // returned does not include the \n. 56 | func ReadPassword(fd int) ([]byte, error) { 57 | return nil, fmt.Errorf("terminal: ReadPassword not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) 58 | } 59 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/ssh/terminal/util_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build windows 6 | 7 | // Package terminal provides support functions for dealing with terminals, as 8 | // commonly found on UNIX systems. 9 | // 10 | // Putting a terminal into raw mode is the most common requirement: 11 | // 12 | // oldState, err := terminal.MakeRaw(0) 13 | // if err != nil { 14 | // panic(err) 15 | // } 16 | // defer terminal.Restore(0, oldState) 17 | package terminal 18 | 19 | import ( 20 | "io" 21 | "syscall" 22 | "unsafe" 23 | ) 24 | 25 | const ( 26 | enableLineInput = 2 27 | enableEchoInput = 4 28 | enableProcessedInput = 1 29 | enableWindowInput = 8 30 | enableMouseInput = 16 31 | enableInsertMode = 32 32 | enableQuickEditMode = 64 33 | enableExtendedFlags = 128 34 | enableAutoPosition = 256 35 | enableProcessedOutput = 1 36 | enableWrapAtEolOutput = 2 37 | ) 38 | 39 | var kernel32 = syscall.NewLazyDLL("kernel32.dll") 40 | 41 | var ( 42 | procGetConsoleMode = kernel32.NewProc("GetConsoleMode") 43 | procSetConsoleMode = kernel32.NewProc("SetConsoleMode") 44 | procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo") 45 | ) 46 | 47 | type ( 48 | short int16 49 | word uint16 50 | 51 | coord struct { 52 | x short 53 | y short 54 | } 55 | smallRect struct { 56 | left short 57 | top short 58 | right short 59 | bottom short 60 | } 61 | consoleScreenBufferInfo struct { 62 | size coord 63 | cursorPosition coord 64 | attributes word 65 | window smallRect 66 | maximumWindowSize coord 67 | } 68 | ) 69 | 70 | type State struct { 71 | mode uint32 72 | } 73 | 74 | // IsTerminal returns true if the given file descriptor is a terminal. 75 | func IsTerminal(fd int) bool { 76 | var st uint32 77 | r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) 78 | return r != 0 && e == 0 79 | } 80 | 81 | // MakeRaw put the terminal connected to the given file descriptor into raw 82 | // mode and returns the previous state of the terminal so that it can be 83 | // restored. 84 | func MakeRaw(fd int) (*State, error) { 85 | var st uint32 86 | _, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) 87 | if e != 0 { 88 | return nil, error(e) 89 | } 90 | raw := st &^ (enableEchoInput | enableProcessedInput | enableLineInput | enableProcessedOutput) 91 | _, _, e = syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(raw), 0) 92 | if e != 0 { 93 | return nil, error(e) 94 | } 95 | return &State{st}, nil 96 | } 97 | 98 | // GetState returns the current state of a terminal which may be useful to 99 | // restore the terminal after a signal. 100 | func GetState(fd int) (*State, error) { 101 | var st uint32 102 | _, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) 103 | if e != 0 { 104 | return nil, error(e) 105 | } 106 | return &State{st}, nil 107 | } 108 | 109 | // Restore restores the terminal connected to the given file descriptor to a 110 | // previous state. 111 | func Restore(fd int, state *State) error { 112 | _, _, err := syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(state.mode), 0) 113 | return err 114 | } 115 | 116 | // GetSize returns the dimensions of the given terminal. 117 | func GetSize(fd int) (width, height int, err error) { 118 | var info consoleScreenBufferInfo 119 | _, _, e := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&info)), 0) 120 | if e != 0 { 121 | return 0, 0, error(e) 122 | } 123 | return int(info.size.x), int(info.size.y), nil 124 | } 125 | 126 | // ReadPassword reads a line of input from a terminal without local echo. This 127 | // is commonly used for inputting passwords and other sensitive data. The slice 128 | // returned does not include the \n. 129 | func ReadPassword(fd int) ([]byte, error) { 130 | var st uint32 131 | _, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) 132 | if e != 0 { 133 | return nil, error(e) 134 | } 135 | old := st 136 | 137 | st &^= (enableEchoInput) 138 | st |= (enableProcessedInput | enableLineInput | enableProcessedOutput) 139 | _, _, e = syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(st), 0) 140 | if e != 0 { 141 | return nil, error(e) 142 | } 143 | 144 | defer func() { 145 | syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(old), 0) 146 | }() 147 | 148 | var buf [16]byte 149 | var ret []byte 150 | for { 151 | n, err := syscall.Read(syscall.Handle(fd), buf[:]) 152 | if err != nil { 153 | return nil, err 154 | } 155 | if n == 0 { 156 | if len(ret) == 0 { 157 | return nil, io.EOF 158 | } 159 | break 160 | } 161 | if buf[n-1] == '\n' { 162 | n-- 163 | } 164 | if n > 0 && buf[n-1] == '\r' { 165 | n-- 166 | } 167 | ret = append(ret, buf[:n]...) 168 | if n < len(buf) { 169 | break 170 | } 171 | } 172 | 173 | return ret, nil 174 | } 175 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/html/atom/atom.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package atom provides integer codes (also known as atoms) for a fixed set of 6 | // frequently occurring HTML strings: tag names and attribute keys such as "p" 7 | // and "id". 8 | // 9 | // Sharing an atom's name between all elements with the same tag can result in 10 | // fewer string allocations when tokenizing and parsing HTML. Integer 11 | // comparisons are also generally faster than string comparisons. 12 | // 13 | // The value of an atom's particular code is not guaranteed to stay the same 14 | // between versions of this package. Neither is any ordering guaranteed: 15 | // whether atom.H1 < atom.H2 may also change. The codes are not guaranteed to 16 | // be dense. The only guarantees are that e.g. looking up "div" will yield 17 | // atom.Div, calling atom.Div.String will return "div", and atom.Div != 0. 18 | package atom 19 | 20 | // Atom is an integer code for a string. The zero value maps to "". 21 | type Atom uint32 22 | 23 | // String returns the atom's name. 24 | func (a Atom) String() string { 25 | start := uint32(a >> 8) 26 | n := uint32(a & 0xff) 27 | if start+n > uint32(len(atomText)) { 28 | return "" 29 | } 30 | return atomText[start : start+n] 31 | } 32 | 33 | func (a Atom) string() string { 34 | return atomText[a>>8 : a>>8+a&0xff] 35 | } 36 | 37 | // fnv computes the FNV hash with an arbitrary starting value h. 38 | func fnv(h uint32, s []byte) uint32 { 39 | for i := range s { 40 | h ^= uint32(s[i]) 41 | h *= 16777619 42 | } 43 | return h 44 | } 45 | 46 | func match(s string, t []byte) bool { 47 | for i, c := range t { 48 | if s[i] != c { 49 | return false 50 | } 51 | } 52 | return true 53 | } 54 | 55 | // Lookup returns the atom whose name is s. It returns zero if there is no 56 | // such atom. The lookup is case sensitive. 57 | func Lookup(s []byte) Atom { 58 | if len(s) == 0 || len(s) > maxAtomLen { 59 | return 0 60 | } 61 | h := fnv(hash0, s) 62 | if a := table[h&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) { 63 | return a 64 | } 65 | if a := table[(h>>16)&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) { 66 | return a 67 | } 68 | return 0 69 | } 70 | 71 | // String returns a string whose contents are equal to s. In that sense, it is 72 | // equivalent to string(s) but may be more efficient. 73 | func String(s []byte) string { 74 | if a := Lookup(s); a != 0 { 75 | return a.String() 76 | } 77 | return string(s) 78 | } 79 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/html/const.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package html 6 | 7 | // Section 12.2.3.2 of the HTML5 specification says "The following elements 8 | // have varying levels of special parsing rules". 9 | // https://html.spec.whatwg.org/multipage/syntax.html#the-stack-of-open-elements 10 | var isSpecialElementMap = map[string]bool{ 11 | "address": true, 12 | "applet": true, 13 | "area": true, 14 | "article": true, 15 | "aside": true, 16 | "base": true, 17 | "basefont": true, 18 | "bgsound": true, 19 | "blockquote": true, 20 | "body": true, 21 | "br": true, 22 | "button": true, 23 | "caption": true, 24 | "center": true, 25 | "col": true, 26 | "colgroup": true, 27 | "dd": true, 28 | "details": true, 29 | "dir": true, 30 | "div": true, 31 | "dl": true, 32 | "dt": true, 33 | "embed": true, 34 | "fieldset": true, 35 | "figcaption": true, 36 | "figure": true, 37 | "footer": true, 38 | "form": true, 39 | "frame": true, 40 | "frameset": true, 41 | "h1": true, 42 | "h2": true, 43 | "h3": true, 44 | "h4": true, 45 | "h5": true, 46 | "h6": true, 47 | "head": true, 48 | "header": true, 49 | "hgroup": true, 50 | "hr": true, 51 | "html": true, 52 | "iframe": true, 53 | "img": true, 54 | "input": true, 55 | "isindex": true, 56 | "li": true, 57 | "link": true, 58 | "listing": true, 59 | "marquee": true, 60 | "menu": true, 61 | "meta": true, 62 | "nav": true, 63 | "noembed": true, 64 | "noframes": true, 65 | "noscript": true, 66 | "object": true, 67 | "ol": true, 68 | "p": true, 69 | "param": true, 70 | "plaintext": true, 71 | "pre": true, 72 | "script": true, 73 | "section": true, 74 | "select": true, 75 | "source": true, 76 | "style": true, 77 | "summary": true, 78 | "table": true, 79 | "tbody": true, 80 | "td": true, 81 | "template": true, 82 | "textarea": true, 83 | "tfoot": true, 84 | "th": true, 85 | "thead": true, 86 | "title": true, 87 | "tr": true, 88 | "track": true, 89 | "ul": true, 90 | "wbr": true, 91 | "xmp": true, 92 | } 93 | 94 | func isSpecialElement(element *Node) bool { 95 | switch element.Namespace { 96 | case "", "html": 97 | return isSpecialElementMap[element.Data] 98 | case "svg": 99 | return element.Data == "foreignObject" 100 | } 101 | return false 102 | } 103 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/html/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | /* 6 | Package html implements an HTML5-compliant tokenizer and parser. 7 | 8 | Tokenization is done by creating a Tokenizer for an io.Reader r. It is the 9 | caller's responsibility to ensure that r provides UTF-8 encoded HTML. 10 | 11 | z := html.NewTokenizer(r) 12 | 13 | Given a Tokenizer z, the HTML is tokenized by repeatedly calling z.Next(), 14 | which parses the next token and returns its type, or an error: 15 | 16 | for { 17 | tt := z.Next() 18 | if tt == html.ErrorToken { 19 | // ... 20 | return ... 21 | } 22 | // Process the current token. 23 | } 24 | 25 | There are two APIs for retrieving the current token. The high-level API is to 26 | call Token; the low-level API is to call Text or TagName / TagAttr. Both APIs 27 | allow optionally calling Raw after Next but before Token, Text, TagName, or 28 | TagAttr. In EBNF notation, the valid call sequence per token is: 29 | 30 | Next {Raw} [ Token | Text | TagName {TagAttr} ] 31 | 32 | Token returns an independent data structure that completely describes a token. 33 | Entities (such as "<") are unescaped, tag names and attribute keys are 34 | lower-cased, and attributes are collected into a []Attribute. For example: 35 | 36 | for { 37 | if z.Next() == html.ErrorToken { 38 | // Returning io.EOF indicates success. 39 | return z.Err() 40 | } 41 | emitToken(z.Token()) 42 | } 43 | 44 | The low-level API performs fewer allocations and copies, but the contents of 45 | the []byte values returned by Text, TagName and TagAttr may change on the next 46 | call to Next. For example, to extract an HTML page's anchor text: 47 | 48 | depth := 0 49 | for { 50 | tt := z.Next() 51 | switch tt { 52 | case ErrorToken: 53 | return z.Err() 54 | case TextToken: 55 | if depth > 0 { 56 | // emitBytes should copy the []byte it receives, 57 | // if it doesn't process it immediately. 58 | emitBytes(z.Text()) 59 | } 60 | case StartTagToken, EndTagToken: 61 | tn, _ := z.TagName() 62 | if len(tn) == 1 && tn[0] == 'a' { 63 | if tt == StartTagToken { 64 | depth++ 65 | } else { 66 | depth-- 67 | } 68 | } 69 | } 70 | } 71 | 72 | Parsing is done by calling Parse with an io.Reader, which returns the root of 73 | the parse tree (the document element) as a *Node. It is the caller's 74 | responsibility to ensure that the Reader provides UTF-8 encoded HTML. For 75 | example, to process each anchor node in depth-first order: 76 | 77 | doc, err := html.Parse(r) 78 | if err != nil { 79 | // ... 80 | } 81 | var f func(*html.Node) 82 | f = func(n *html.Node) { 83 | if n.Type == html.ElementNode && n.Data == "a" { 84 | // Do something with n... 85 | } 86 | for c := n.FirstChild; c != nil; c = c.NextSibling { 87 | f(c) 88 | } 89 | } 90 | f(doc) 91 | 92 | The relevant specifications include: 93 | https://html.spec.whatwg.org/multipage/syntax.html and 94 | https://html.spec.whatwg.org/multipage/syntax.html#tokenization 95 | */ 96 | package html 97 | 98 | // The tokenization algorithm implemented by this package is not a line-by-line 99 | // transliteration of the relatively verbose state-machine in the WHATWG 100 | // specification. A more direct approach is used instead, where the program 101 | // counter implies the state, such as whether it is tokenizing a tag or a text 102 | // node. Specification compliance is verified by checking expected and actual 103 | // outputs over a test suite rather than aiming for algorithmic fidelity. 104 | 105 | // TODO(nigeltao): Does a DOM API belong in this package or a separate one? 106 | // TODO(nigeltao): How does parsing interact with a JavaScript engine? 107 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/html/doctype.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package html 6 | 7 | import ( 8 | "strings" 9 | ) 10 | 11 | // parseDoctype parses the data from a DoctypeToken into a name, 12 | // public identifier, and system identifier. It returns a Node whose Type 13 | // is DoctypeNode, whose Data is the name, and which has attributes 14 | // named "system" and "public" for the two identifiers if they were present. 15 | // quirks is whether the document should be parsed in "quirks mode". 16 | func parseDoctype(s string) (n *Node, quirks bool) { 17 | n = &Node{Type: DoctypeNode} 18 | 19 | // Find the name. 20 | space := strings.IndexAny(s, whitespace) 21 | if space == -1 { 22 | space = len(s) 23 | } 24 | n.Data = s[:space] 25 | // The comparison to "html" is case-sensitive. 26 | if n.Data != "html" { 27 | quirks = true 28 | } 29 | n.Data = strings.ToLower(n.Data) 30 | s = strings.TrimLeft(s[space:], whitespace) 31 | 32 | if len(s) < 6 { 33 | // It can't start with "PUBLIC" or "SYSTEM". 34 | // Ignore the rest of the string. 35 | return n, quirks || s != "" 36 | } 37 | 38 | key := strings.ToLower(s[:6]) 39 | s = s[6:] 40 | for key == "public" || key == "system" { 41 | s = strings.TrimLeft(s, whitespace) 42 | if s == "" { 43 | break 44 | } 45 | quote := s[0] 46 | if quote != '"' && quote != '\'' { 47 | break 48 | } 49 | s = s[1:] 50 | q := strings.IndexRune(s, rune(quote)) 51 | var id string 52 | if q == -1 { 53 | id = s 54 | s = "" 55 | } else { 56 | id = s[:q] 57 | s = s[q+1:] 58 | } 59 | n.Attr = append(n.Attr, Attribute{Key: key, Val: id}) 60 | if key == "public" { 61 | key = "system" 62 | } else { 63 | key = "" 64 | } 65 | } 66 | 67 | if key != "" || s != "" { 68 | quirks = true 69 | } else if len(n.Attr) > 0 { 70 | if n.Attr[0].Key == "public" { 71 | public := strings.ToLower(n.Attr[0].Val) 72 | switch public { 73 | case "-//w3o//dtd w3 html strict 3.0//en//", "-/w3d/dtd html 4.0 transitional/en", "html": 74 | quirks = true 75 | default: 76 | for _, q := range quirkyIDs { 77 | if strings.HasPrefix(public, q) { 78 | quirks = true 79 | break 80 | } 81 | } 82 | } 83 | // The following two public IDs only cause quirks mode if there is no system ID. 84 | if len(n.Attr) == 1 && (strings.HasPrefix(public, "-//w3c//dtd html 4.01 frameset//") || 85 | strings.HasPrefix(public, "-//w3c//dtd html 4.01 transitional//")) { 86 | quirks = true 87 | } 88 | } 89 | if lastAttr := n.Attr[len(n.Attr)-1]; lastAttr.Key == "system" && 90 | strings.ToLower(lastAttr.Val) == "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd" { 91 | quirks = true 92 | } 93 | } 94 | 95 | return n, quirks 96 | } 97 | 98 | // quirkyIDs is a list of public doctype identifiers that cause a document 99 | // to be interpreted in quirks mode. The identifiers should be in lower case. 100 | var quirkyIDs = []string{ 101 | "+//silmaril//dtd html pro v0r11 19970101//", 102 | "-//advasoft ltd//dtd html 3.0 aswedit + extensions//", 103 | "-//as//dtd html 3.0 aswedit + extensions//", 104 | "-//ietf//dtd html 2.0 level 1//", 105 | "-//ietf//dtd html 2.0 level 2//", 106 | "-//ietf//dtd html 2.0 strict level 1//", 107 | "-//ietf//dtd html 2.0 strict level 2//", 108 | "-//ietf//dtd html 2.0 strict//", 109 | "-//ietf//dtd html 2.0//", 110 | "-//ietf//dtd html 2.1e//", 111 | "-//ietf//dtd html 3.0//", 112 | "-//ietf//dtd html 3.2 final//", 113 | "-//ietf//dtd html 3.2//", 114 | "-//ietf//dtd html 3//", 115 | "-//ietf//dtd html level 0//", 116 | "-//ietf//dtd html level 1//", 117 | "-//ietf//dtd html level 2//", 118 | "-//ietf//dtd html level 3//", 119 | "-//ietf//dtd html strict level 0//", 120 | "-//ietf//dtd html strict level 1//", 121 | "-//ietf//dtd html strict level 2//", 122 | "-//ietf//dtd html strict level 3//", 123 | "-//ietf//dtd html strict//", 124 | "-//ietf//dtd html//", 125 | "-//metrius//dtd metrius presentational//", 126 | "-//microsoft//dtd internet explorer 2.0 html strict//", 127 | "-//microsoft//dtd internet explorer 2.0 html//", 128 | "-//microsoft//dtd internet explorer 2.0 tables//", 129 | "-//microsoft//dtd internet explorer 3.0 html strict//", 130 | "-//microsoft//dtd internet explorer 3.0 html//", 131 | "-//microsoft//dtd internet explorer 3.0 tables//", 132 | "-//netscape comm. corp.//dtd html//", 133 | "-//netscape comm. corp.//dtd strict html//", 134 | "-//o'reilly and associates//dtd html 2.0//", 135 | "-//o'reilly and associates//dtd html extended 1.0//", 136 | "-//o'reilly and associates//dtd html extended relaxed 1.0//", 137 | "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//", 138 | "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//", 139 | "-//spyglass//dtd html 2.0 extended//", 140 | "-//sq//dtd html 2.0 hotmetal + extensions//", 141 | "-//sun microsystems corp.//dtd hotjava html//", 142 | "-//sun microsystems corp.//dtd hotjava strict html//", 143 | "-//w3c//dtd html 3 1995-03-24//", 144 | "-//w3c//dtd html 3.2 draft//", 145 | "-//w3c//dtd html 3.2 final//", 146 | "-//w3c//dtd html 3.2//", 147 | "-//w3c//dtd html 3.2s draft//", 148 | "-//w3c//dtd html 4.0 frameset//", 149 | "-//w3c//dtd html 4.0 transitional//", 150 | "-//w3c//dtd html experimental 19960712//", 151 | "-//w3c//dtd html experimental 970421//", 152 | "-//w3c//dtd w3 html//", 153 | "-//w3o//dtd w3 html 3.0//", 154 | "-//webtechs//dtd mozilla html 2.0//", 155 | "-//webtechs//dtd mozilla html//", 156 | } 157 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/html/escape.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package html 6 | 7 | import ( 8 | "bytes" 9 | "strings" 10 | "unicode/utf8" 11 | ) 12 | 13 | // These replacements permit compatibility with old numeric entities that 14 | // assumed Windows-1252 encoding. 15 | // https://html.spec.whatwg.org/multipage/syntax.html#consume-a-character-reference 16 | var replacementTable = [...]rune{ 17 | '\u20AC', // First entry is what 0x80 should be replaced with. 18 | '\u0081', 19 | '\u201A', 20 | '\u0192', 21 | '\u201E', 22 | '\u2026', 23 | '\u2020', 24 | '\u2021', 25 | '\u02C6', 26 | '\u2030', 27 | '\u0160', 28 | '\u2039', 29 | '\u0152', 30 | '\u008D', 31 | '\u017D', 32 | '\u008F', 33 | '\u0090', 34 | '\u2018', 35 | '\u2019', 36 | '\u201C', 37 | '\u201D', 38 | '\u2022', 39 | '\u2013', 40 | '\u2014', 41 | '\u02DC', 42 | '\u2122', 43 | '\u0161', 44 | '\u203A', 45 | '\u0153', 46 | '\u009D', 47 | '\u017E', 48 | '\u0178', // Last entry is 0x9F. 49 | // 0x00->'\uFFFD' is handled programmatically. 50 | // 0x0D->'\u000D' is a no-op. 51 | } 52 | 53 | // unescapeEntity reads an entity like "<" from b[src:] and writes the 54 | // corresponding "<" to b[dst:], returning the incremented dst and src cursors. 55 | // Precondition: b[src] == '&' && dst <= src. 56 | // attribute should be true if parsing an attribute value. 57 | func unescapeEntity(b []byte, dst, src int, attribute bool) (dst1, src1 int) { 58 | // https://html.spec.whatwg.org/multipage/syntax.html#consume-a-character-reference 59 | 60 | // i starts at 1 because we already know that s[0] == '&'. 61 | i, s := 1, b[src:] 62 | 63 | if len(s) <= 1 { 64 | b[dst] = b[src] 65 | return dst + 1, src + 1 66 | } 67 | 68 | if s[i] == '#' { 69 | if len(s) <= 3 { // We need to have at least "&#.". 70 | b[dst] = b[src] 71 | return dst + 1, src + 1 72 | } 73 | i++ 74 | c := s[i] 75 | hex := false 76 | if c == 'x' || c == 'X' { 77 | hex = true 78 | i++ 79 | } 80 | 81 | x := '\x00' 82 | for i < len(s) { 83 | c = s[i] 84 | i++ 85 | if hex { 86 | if '0' <= c && c <= '9' { 87 | x = 16*x + rune(c) - '0' 88 | continue 89 | } else if 'a' <= c && c <= 'f' { 90 | x = 16*x + rune(c) - 'a' + 10 91 | continue 92 | } else if 'A' <= c && c <= 'F' { 93 | x = 16*x + rune(c) - 'A' + 10 94 | continue 95 | } 96 | } else if '0' <= c && c <= '9' { 97 | x = 10*x + rune(c) - '0' 98 | continue 99 | } 100 | if c != ';' { 101 | i-- 102 | } 103 | break 104 | } 105 | 106 | if i <= 3 { // No characters matched. 107 | b[dst] = b[src] 108 | return dst + 1, src + 1 109 | } 110 | 111 | if 0x80 <= x && x <= 0x9F { 112 | // Replace characters from Windows-1252 with UTF-8 equivalents. 113 | x = replacementTable[x-0x80] 114 | } else if x == 0 || (0xD800 <= x && x <= 0xDFFF) || x > 0x10FFFF { 115 | // Replace invalid characters with the replacement character. 116 | x = '\uFFFD' 117 | } 118 | 119 | return dst + utf8.EncodeRune(b[dst:], x), src + i 120 | } 121 | 122 | // Consume the maximum number of characters possible, with the 123 | // consumed characters matching one of the named references. 124 | 125 | for i < len(s) { 126 | c := s[i] 127 | i++ 128 | // Lower-cased characters are more common in entities, so we check for them first. 129 | if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' { 130 | continue 131 | } 132 | if c != ';' { 133 | i-- 134 | } 135 | break 136 | } 137 | 138 | entityName := string(s[1:i]) 139 | if entityName == "" { 140 | // No-op. 141 | } else if attribute && entityName[len(entityName)-1] != ';' && len(s) > i && s[i] == '=' { 142 | // No-op. 143 | } else if x := entity[entityName]; x != 0 { 144 | return dst + utf8.EncodeRune(b[dst:], x), src + i 145 | } else if x := entity2[entityName]; x[0] != 0 { 146 | dst1 := dst + utf8.EncodeRune(b[dst:], x[0]) 147 | return dst1 + utf8.EncodeRune(b[dst1:], x[1]), src + i 148 | } else if !attribute { 149 | maxLen := len(entityName) - 1 150 | if maxLen > longestEntityWithoutSemicolon { 151 | maxLen = longestEntityWithoutSemicolon 152 | } 153 | for j := maxLen; j > 1; j-- { 154 | if x := entity[entityName[:j]]; x != 0 { 155 | return dst + utf8.EncodeRune(b[dst:], x), src + j + 1 156 | } 157 | } 158 | } 159 | 160 | dst1, src1 = dst+i, src+i 161 | copy(b[dst:dst1], b[src:src1]) 162 | return dst1, src1 163 | } 164 | 165 | // unescape unescapes b's entities in-place, so that "a<b" becomes "a': 214 | esc = ">" 215 | case '"': 216 | // """ is shorter than """. 217 | esc = """ 218 | case '\r': 219 | esc = " " 220 | default: 221 | panic("unrecognized escape character") 222 | } 223 | s = s[i+1:] 224 | if _, err := w.WriteString(esc); err != nil { 225 | return err 226 | } 227 | i = strings.IndexAny(s, escapedChars) 228 | } 229 | _, err := w.WriteString(s) 230 | return err 231 | } 232 | 233 | // EscapeString escapes special characters like "<" to become "<". It 234 | // escapes only five such characters: <, >, &, ' and ". 235 | // UnescapeString(EscapeString(s)) == s always holds, but the converse isn't 236 | // always true. 237 | func EscapeString(s string) string { 238 | if strings.IndexAny(s, escapedChars) == -1 { 239 | return s 240 | } 241 | var buf bytes.Buffer 242 | escape(&buf, s) 243 | return buf.String() 244 | } 245 | 246 | // UnescapeString unescapes entities like "<" to become "<". It unescapes a 247 | // larger range of entities than EscapeString escapes. For example, "á" 248 | // unescapes to "á", as does "á" and "&xE1;". 249 | // UnescapeString(EscapeString(s)) == s always holds, but the converse isn't 250 | // always true. 251 | func UnescapeString(s string) string { 252 | for _, c := range s { 253 | if c == '&' { 254 | return string(unescape([]byte(s), false)) 255 | } 256 | } 257 | return s 258 | } 259 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/html/foreign.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package html 6 | 7 | import ( 8 | "strings" 9 | ) 10 | 11 | func adjustAttributeNames(aa []Attribute, nameMap map[string]string) { 12 | for i := range aa { 13 | if newName, ok := nameMap[aa[i].Key]; ok { 14 | aa[i].Key = newName 15 | } 16 | } 17 | } 18 | 19 | func adjustForeignAttributes(aa []Attribute) { 20 | for i, a := range aa { 21 | if a.Key == "" || a.Key[0] != 'x' { 22 | continue 23 | } 24 | switch a.Key { 25 | case "xlink:actuate", "xlink:arcrole", "xlink:href", "xlink:role", "xlink:show", 26 | "xlink:title", "xlink:type", "xml:base", "xml:lang", "xml:space", "xmlns:xlink": 27 | j := strings.Index(a.Key, ":") 28 | aa[i].Namespace = a.Key[:j] 29 | aa[i].Key = a.Key[j+1:] 30 | } 31 | } 32 | } 33 | 34 | func htmlIntegrationPoint(n *Node) bool { 35 | if n.Type != ElementNode { 36 | return false 37 | } 38 | switch n.Namespace { 39 | case "math": 40 | if n.Data == "annotation-xml" { 41 | for _, a := range n.Attr { 42 | if a.Key == "encoding" { 43 | val := strings.ToLower(a.Val) 44 | if val == "text/html" || val == "application/xhtml+xml" { 45 | return true 46 | } 47 | } 48 | } 49 | } 50 | case "svg": 51 | switch n.Data { 52 | case "desc", "foreignObject", "title": 53 | return true 54 | } 55 | } 56 | return false 57 | } 58 | 59 | func mathMLTextIntegrationPoint(n *Node) bool { 60 | if n.Namespace != "math" { 61 | return false 62 | } 63 | switch n.Data { 64 | case "mi", "mo", "mn", "ms", "mtext": 65 | return true 66 | } 67 | return false 68 | } 69 | 70 | // Section 12.2.5.5. 71 | var breakout = map[string]bool{ 72 | "b": true, 73 | "big": true, 74 | "blockquote": true, 75 | "body": true, 76 | "br": true, 77 | "center": true, 78 | "code": true, 79 | "dd": true, 80 | "div": true, 81 | "dl": true, 82 | "dt": true, 83 | "em": true, 84 | "embed": true, 85 | "h1": true, 86 | "h2": true, 87 | "h3": true, 88 | "h4": true, 89 | "h5": true, 90 | "h6": true, 91 | "head": true, 92 | "hr": true, 93 | "i": true, 94 | "img": true, 95 | "li": true, 96 | "listing": true, 97 | "menu": true, 98 | "meta": true, 99 | "nobr": true, 100 | "ol": true, 101 | "p": true, 102 | "pre": true, 103 | "ruby": true, 104 | "s": true, 105 | "small": true, 106 | "span": true, 107 | "strong": true, 108 | "strike": true, 109 | "sub": true, 110 | "sup": true, 111 | "table": true, 112 | "tt": true, 113 | "u": true, 114 | "ul": true, 115 | "var": true, 116 | } 117 | 118 | // Section 12.2.5.5. 119 | var svgTagNameAdjustments = map[string]string{ 120 | "altglyph": "altGlyph", 121 | "altglyphdef": "altGlyphDef", 122 | "altglyphitem": "altGlyphItem", 123 | "animatecolor": "animateColor", 124 | "animatemotion": "animateMotion", 125 | "animatetransform": "animateTransform", 126 | "clippath": "clipPath", 127 | "feblend": "feBlend", 128 | "fecolormatrix": "feColorMatrix", 129 | "fecomponenttransfer": "feComponentTransfer", 130 | "fecomposite": "feComposite", 131 | "feconvolvematrix": "feConvolveMatrix", 132 | "fediffuselighting": "feDiffuseLighting", 133 | "fedisplacementmap": "feDisplacementMap", 134 | "fedistantlight": "feDistantLight", 135 | "feflood": "feFlood", 136 | "fefunca": "feFuncA", 137 | "fefuncb": "feFuncB", 138 | "fefuncg": "feFuncG", 139 | "fefuncr": "feFuncR", 140 | "fegaussianblur": "feGaussianBlur", 141 | "feimage": "feImage", 142 | "femerge": "feMerge", 143 | "femergenode": "feMergeNode", 144 | "femorphology": "feMorphology", 145 | "feoffset": "feOffset", 146 | "fepointlight": "fePointLight", 147 | "fespecularlighting": "feSpecularLighting", 148 | "fespotlight": "feSpotLight", 149 | "fetile": "feTile", 150 | "feturbulence": "feTurbulence", 151 | "foreignobject": "foreignObject", 152 | "glyphref": "glyphRef", 153 | "lineargradient": "linearGradient", 154 | "radialgradient": "radialGradient", 155 | "textpath": "textPath", 156 | } 157 | 158 | // Section 12.2.5.1 159 | var mathMLAttributeAdjustments = map[string]string{ 160 | "definitionurl": "definitionURL", 161 | } 162 | 163 | var svgAttributeAdjustments = map[string]string{ 164 | "attributename": "attributeName", 165 | "attributetype": "attributeType", 166 | "basefrequency": "baseFrequency", 167 | "baseprofile": "baseProfile", 168 | "calcmode": "calcMode", 169 | "clippathunits": "clipPathUnits", 170 | "contentscripttype": "contentScriptType", 171 | "contentstyletype": "contentStyleType", 172 | "diffuseconstant": "diffuseConstant", 173 | "edgemode": "edgeMode", 174 | "externalresourcesrequired": "externalResourcesRequired", 175 | "filterres": "filterRes", 176 | "filterunits": "filterUnits", 177 | "glyphref": "glyphRef", 178 | "gradienttransform": "gradientTransform", 179 | "gradientunits": "gradientUnits", 180 | "kernelmatrix": "kernelMatrix", 181 | "kernelunitlength": "kernelUnitLength", 182 | "keypoints": "keyPoints", 183 | "keysplines": "keySplines", 184 | "keytimes": "keyTimes", 185 | "lengthadjust": "lengthAdjust", 186 | "limitingconeangle": "limitingConeAngle", 187 | "markerheight": "markerHeight", 188 | "markerunits": "markerUnits", 189 | "markerwidth": "markerWidth", 190 | "maskcontentunits": "maskContentUnits", 191 | "maskunits": "maskUnits", 192 | "numoctaves": "numOctaves", 193 | "pathlength": "pathLength", 194 | "patterncontentunits": "patternContentUnits", 195 | "patterntransform": "patternTransform", 196 | "patternunits": "patternUnits", 197 | "pointsatx": "pointsAtX", 198 | "pointsaty": "pointsAtY", 199 | "pointsatz": "pointsAtZ", 200 | "preservealpha": "preserveAlpha", 201 | "preserveaspectratio": "preserveAspectRatio", 202 | "primitiveunits": "primitiveUnits", 203 | "refx": "refX", 204 | "refy": "refY", 205 | "repeatcount": "repeatCount", 206 | "repeatdur": "repeatDur", 207 | "requiredextensions": "requiredExtensions", 208 | "requiredfeatures": "requiredFeatures", 209 | "specularconstant": "specularConstant", 210 | "specularexponent": "specularExponent", 211 | "spreadmethod": "spreadMethod", 212 | "startoffset": "startOffset", 213 | "stddeviation": "stdDeviation", 214 | "stitchtiles": "stitchTiles", 215 | "surfacescale": "surfaceScale", 216 | "systemlanguage": "systemLanguage", 217 | "tablevalues": "tableValues", 218 | "targetx": "targetX", 219 | "targety": "targetY", 220 | "textlength": "textLength", 221 | "viewbox": "viewBox", 222 | "viewtarget": "viewTarget", 223 | "xchannelselector": "xChannelSelector", 224 | "ychannelselector": "yChannelSelector", 225 | "zoomandpan": "zoomAndPan", 226 | } 227 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/html/node.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package html 6 | 7 | import ( 8 | "golang.org/x/net/html/atom" 9 | ) 10 | 11 | // A NodeType is the type of a Node. 12 | type NodeType uint32 13 | 14 | const ( 15 | ErrorNode NodeType = iota 16 | TextNode 17 | DocumentNode 18 | ElementNode 19 | CommentNode 20 | DoctypeNode 21 | scopeMarkerNode 22 | ) 23 | 24 | // Section 12.2.3.3 says "scope markers are inserted when entering applet 25 | // elements, buttons, object elements, marquees, table cells, and table 26 | // captions, and are used to prevent formatting from 'leaking'". 27 | var scopeMarker = Node{Type: scopeMarkerNode} 28 | 29 | // A Node consists of a NodeType and some Data (tag name for element nodes, 30 | // content for text) and are part of a tree of Nodes. Element nodes may also 31 | // have a Namespace and contain a slice of Attributes. Data is unescaped, so 32 | // that it looks like "a 0 { 160 | return (*s)[i-1] 161 | } 162 | return nil 163 | } 164 | 165 | // index returns the index of the top-most occurrence of n in the stack, or -1 166 | // if n is not present. 167 | func (s *nodeStack) index(n *Node) int { 168 | for i := len(*s) - 1; i >= 0; i-- { 169 | if (*s)[i] == n { 170 | return i 171 | } 172 | } 173 | return -1 174 | } 175 | 176 | // insert inserts a node at the given index. 177 | func (s *nodeStack) insert(i int, n *Node) { 178 | (*s) = append(*s, nil) 179 | copy((*s)[i+1:], (*s)[i:]) 180 | (*s)[i] = n 181 | } 182 | 183 | // remove removes a node from the stack. It is a no-op if n is not present. 184 | func (s *nodeStack) remove(n *Node) { 185 | i := s.index(n) 186 | if i == -1 { 187 | return 188 | } 189 | copy((*s)[i:], (*s)[i+1:]) 190 | j := len(*s) - 1 191 | (*s)[j] = nil 192 | *s = (*s)[:j] 193 | } 194 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/html/render.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package html 6 | 7 | import ( 8 | "bufio" 9 | "errors" 10 | "fmt" 11 | "io" 12 | "strings" 13 | ) 14 | 15 | type writer interface { 16 | io.Writer 17 | io.ByteWriter 18 | WriteString(string) (int, error) 19 | } 20 | 21 | // Render renders the parse tree n to the given writer. 22 | // 23 | // Rendering is done on a 'best effort' basis: calling Parse on the output of 24 | // Render will always result in something similar to the original tree, but it 25 | // is not necessarily an exact clone unless the original tree was 'well-formed'. 26 | // 'Well-formed' is not easily specified; the HTML5 specification is 27 | // complicated. 28 | // 29 | // Calling Parse on arbitrary input typically results in a 'well-formed' parse 30 | // tree. However, it is possible for Parse to yield a 'badly-formed' parse tree. 31 | // For example, in a 'well-formed' parse tree, no element is a child of 32 | // another element: parsing "" results in two sibling elements. 33 | // Similarly, in a 'well-formed' parse tree, no element is a child of a 34 | // element: parsing "

" results in a

with two sibling 35 | // children; the is reparented to the

's parent. However, calling 36 | // Parse on "
" does not return an error, but the result has an 37 | // element with an child, and is therefore not 'well-formed'. 38 | // 39 | // Programmatically constructed trees are typically also 'well-formed', but it 40 | // is possible to construct a tree that looks innocuous but, when rendered and 41 | // re-parsed, results in a different tree. A simple example is that a solitary 42 | // text node would become a tree containing , and elements. 43 | // Another example is that the programmatic equivalent of "abc" 44 | // becomes "abc". 45 | func Render(w io.Writer, n *Node) error { 46 | if x, ok := w.(writer); ok { 47 | return render(x, n) 48 | } 49 | buf := bufio.NewWriter(w) 50 | if err := render(buf, n); err != nil { 51 | return err 52 | } 53 | return buf.Flush() 54 | } 55 | 56 | // plaintextAbort is returned from render1 when a element 57 | // has been rendered. No more end tags should be rendered after that. 58 | var plaintextAbort = errors.New("html: internal error (plaintext abort)") 59 | 60 | func render(w writer, n *Node) error { 61 | err := render1(w, n) 62 | if err == plaintextAbort { 63 | err = nil 64 | } 65 | return err 66 | } 67 | 68 | func render1(w writer, n *Node) error { 69 | // Render non-element nodes; these are the easy cases. 70 | switch n.Type { 71 | case ErrorNode: 72 | return errors.New("html: cannot render an ErrorNode node") 73 | case TextNode: 74 | return escape(w, n.Data) 75 | case DocumentNode: 76 | for c := n.FirstChild; c != nil; c = c.NextSibling { 77 | if err := render1(w, c); err != nil { 78 | return err 79 | } 80 | } 81 | return nil 82 | case ElementNode: 83 | // No-op. 84 | case CommentNode: 85 | if _, err := w.WriteString("<!--"); err != nil { 86 | return err 87 | } 88 | if _, err := w.WriteString(n.Data); err != nil { 89 | return err 90 | } 91 | if _, err := w.WriteString("-->"); err != nil { 92 | return err 93 | } 94 | return nil 95 | case DoctypeNode: 96 | if _, err := w.WriteString("<!DOCTYPE "); err != nil { 97 | return err 98 | } 99 | if _, err := w.WriteString(n.Data); err != nil { 100 | return err 101 | } 102 | if n.Attr != nil { 103 | var p, s string 104 | for _, a := range n.Attr { 105 | switch a.Key { 106 | case "public": 107 | p = a.Val 108 | case "system": 109 | s = a.Val 110 | } 111 | } 112 | if p != "" { 113 | if _, err := w.WriteString(" PUBLIC "); err != nil { 114 | return err 115 | } 116 | if err := writeQuoted(w, p); err != nil { 117 | return err 118 | } 119 | if s != "" { 120 | if err := w.WriteByte(' '); err != nil { 121 | return err 122 | } 123 | if err := writeQuoted(w, s); err != nil { 124 | return err 125 | } 126 | } 127 | } else if s != "" { 128 | if _, err := w.WriteString(" SYSTEM "); err != nil { 129 | return err 130 | } 131 | if err := writeQuoted(w, s); err != nil { 132 | return err 133 | } 134 | } 135 | } 136 | return w.WriteByte('>') 137 | default: 138 | return errors.New("html: unknown node type") 139 | } 140 | 141 | // Render the <xxx> opening tag. 142 | if err := w.WriteByte('<'); err != nil { 143 | return err 144 | } 145 | if _, err := w.WriteString(n.Data); err != nil { 146 | return err 147 | } 148 | for _, a := range n.Attr { 149 | if err := w.WriteByte(' '); err != nil { 150 | return err 151 | } 152 | if a.Namespace != "" { 153 | if _, err := w.WriteString(a.Namespace); err != nil { 154 | return err 155 | } 156 | if err := w.WriteByte(':'); err != nil { 157 | return err 158 | } 159 | } 160 | if _, err := w.WriteString(a.Key); err != nil { 161 | return err 162 | } 163 | if _, err := w.WriteString(`="`); err != nil { 164 | return err 165 | } 166 | if err := escape(w, a.Val); err != nil { 167 | return err 168 | } 169 | if err := w.WriteByte('"'); err != nil { 170 | return err 171 | } 172 | } 173 | if voidElements[n.Data] { 174 | if n.FirstChild != nil { 175 | return fmt.Errorf("html: void element <%s> has child nodes", n.Data) 176 | } 177 | _, err := w.WriteString("/>") 178 | return err 179 | } 180 | if err := w.WriteByte('>'); err != nil { 181 | return err 182 | } 183 | 184 | // Add initial newline where there is danger of a newline beging ignored. 185 | if c := n.FirstChild; c != nil && c.Type == TextNode && strings.HasPrefix(c.Data, "\n") { 186 | switch n.Data { 187 | case "pre", "listing", "textarea": 188 | if err := w.WriteByte('\n'); err != nil { 189 | return err 190 | } 191 | } 192 | } 193 | 194 | // Render any child nodes. 195 | switch n.Data { 196 | case "iframe", "noembed", "noframes", "noscript", "plaintext", "script", "style", "xmp": 197 | for c := n.FirstChild; c != nil; c = c.NextSibling { 198 | if c.Type == TextNode { 199 | if _, err := w.WriteString(c.Data); err != nil { 200 | return err 201 | } 202 | } else { 203 | if err := render1(w, c); err != nil { 204 | return err 205 | } 206 | } 207 | } 208 | if n.Data == "plaintext" { 209 | // Don't render anything else. <plaintext> must be the 210 | // last element in the file, with no closing tag. 211 | return plaintextAbort 212 | } 213 | default: 214 | for c := n.FirstChild; c != nil; c = c.NextSibling { 215 | if err := render1(w, c); err != nil { 216 | return err 217 | } 218 | } 219 | } 220 | 221 | // Render the </xxx> closing tag. 222 | if _, err := w.WriteString("</"); err != nil { 223 | return err 224 | } 225 | if _, err := w.WriteString(n.Data); err != nil { 226 | return err 227 | } 228 | return w.WriteByte('>') 229 | } 230 | 231 | // writeQuoted writes s to w surrounded by quotes. Normally it will use double 232 | // quotes, but if s contains a double quote, it will use single quotes. 233 | // It is used for writing the identifiers in a doctype declaration. 234 | // In valid HTML, they can't contain both types of quotes. 235 | func writeQuoted(w writer, s string) error { 236 | var q byte = '"' 237 | if strings.Contains(s, `"`) { 238 | q = '\'' 239 | } 240 | if err := w.WriteByte(q); err != nil { 241 | return err 242 | } 243 | if _, err := w.WriteString(s); err != nil { 244 | return err 245 | } 246 | if err := w.WriteByte(q); err != nil { 247 | return err 248 | } 249 | return nil 250 | } 251 | 252 | // Section 12.1.2, "Elements", gives this list of void elements. Void elements 253 | // are those that can't have any contents. 254 | var voidElements = map[string]bool{ 255 | "area": true, 256 | "base": true, 257 | "br": true, 258 | "col": true, 259 | "command": true, 260 | "embed": true, 261 | "hr": true, 262 | "img": true, 263 | "input": true, 264 | "keygen": true, 265 | "link": true, 266 | "meta": true, 267 | "param": true, 268 | "source": true, 269 | "track": true, 270 | "wbr": true, 271 | } 272 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/publicsuffix/list.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package publicsuffix provides a public suffix list based on data from 6 | // http://publicsuffix.org/. A public suffix is one under which Internet users 7 | // can directly register names. 8 | package publicsuffix 9 | 10 | // TODO: specify case sensitivity and leading/trailing dot behavior for 11 | // func PublicSuffix and func EffectiveTLDPlusOne. 12 | 13 | import ( 14 | "fmt" 15 | "net/http/cookiejar" 16 | "strings" 17 | ) 18 | 19 | // List implements the cookiejar.PublicSuffixList interface by calling the 20 | // PublicSuffix function. 21 | var List cookiejar.PublicSuffixList = list{} 22 | 23 | type list struct{} 24 | 25 | func (list) PublicSuffix(domain string) string { 26 | ps, _ := PublicSuffix(domain) 27 | return ps 28 | } 29 | 30 | func (list) String() string { 31 | return version 32 | } 33 | 34 | // PublicSuffix returns the public suffix of the domain using a copy of the 35 | // publicsuffix.org database compiled into the library. 36 | // 37 | // icann is whether the public suffix is managed by the Internet Corporation 38 | // for Assigned Names and Numbers. If not, the public suffix is privately 39 | // managed. For example, foo.org and foo.co.uk are ICANN domains, 40 | // foo.dyndns.org and foo.blogspot.co.uk are private domains. 41 | // 42 | // Use cases for distinguishing ICANN domains like foo.com from private 43 | // domains like foo.appspot.com can be found at 44 | // https://wiki.mozilla.org/Public_Suffix_List/Use_Cases 45 | func PublicSuffix(domain string) (publicSuffix string, icann bool) { 46 | lo, hi := uint32(0), uint32(numTLD) 47 | s, suffix, wildcard := domain, len(domain), false 48 | loop: 49 | for { 50 | dot := strings.LastIndex(s, ".") 51 | if wildcard { 52 | suffix = 1 + dot 53 | } 54 | if lo == hi { 55 | break 56 | } 57 | f := find(s[1+dot:], lo, hi) 58 | if f == notFound { 59 | break 60 | } 61 | 62 | u := nodes[f] >> (nodesBitsTextOffset + nodesBitsTextLength) 63 | icann = u&(1<<nodesBitsICANN-1) != 0 64 | u >>= nodesBitsICANN 65 | u = children[u&(1<<nodesBitsChildren-1)] 66 | lo = u & (1<<childrenBitsLo - 1) 67 | u >>= childrenBitsLo 68 | hi = u & (1<<childrenBitsHi - 1) 69 | u >>= childrenBitsHi 70 | switch u & (1<<childrenBitsNodeType - 1) { 71 | case nodeTypeNormal: 72 | suffix = 1 + dot 73 | case nodeTypeException: 74 | suffix = 1 + len(s) 75 | break loop 76 | } 77 | u >>= childrenBitsNodeType 78 | wildcard = u&(1<<childrenBitsWildcard-1) != 0 79 | 80 | if dot == -1 { 81 | break 82 | } 83 | s = s[:dot] 84 | } 85 | if suffix == len(domain) { 86 | // If no rules match, the prevailing rule is "*". 87 | return domain[1+strings.LastIndex(domain, "."):], icann 88 | } 89 | return domain[suffix:], icann 90 | } 91 | 92 | const notFound uint32 = 1<<32 - 1 93 | 94 | // find returns the index of the node in the range [lo, hi) whose label equals 95 | // label, or notFound if there is no such node. The range is assumed to be in 96 | // strictly increasing node label order. 97 | func find(label string, lo, hi uint32) uint32 { 98 | for lo < hi { 99 | mid := lo + (hi-lo)/2 100 | s := nodeLabel(mid) 101 | if s < label { 102 | lo = mid + 1 103 | } else if s == label { 104 | return mid 105 | } else { 106 | hi = mid 107 | } 108 | } 109 | return notFound 110 | } 111 | 112 | // nodeLabel returns the label for the i'th node. 113 | func nodeLabel(i uint32) string { 114 | x := nodes[i] 115 | length := x & (1<<nodesBitsTextLength - 1) 116 | x >>= nodesBitsTextLength 117 | offset := x & (1<<nodesBitsTextOffset - 1) 118 | return text[offset : offset+length] 119 | } 120 | 121 | // EffectiveTLDPlusOne returns the effective top level domain plus one more 122 | // label. For example, the eTLD+1 for "foo.bar.golang.org" is "golang.org". 123 | func EffectiveTLDPlusOne(domain string) (string, error) { 124 | suffix, _ := PublicSuffix(domain) 125 | if len(domain) <= len(suffix) { 126 | return "", fmt.Errorf("publicsuffix: cannot derive eTLD+1 for domain %q", domain) 127 | } 128 | i := len(domain) - len(suffix) - 1 129 | if domain[i] != '.' { 130 | return "", fmt.Errorf("publicsuffix: invalid public suffix %q for domain %q", suffix, domain) 131 | } 132 | return domain[1+strings.LastIndex(domain[:i], "."):], nil 133 | } 134 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v1/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Copyright (c) 2011-2014 - Canonical Inc. 3 | 4 | This software is licensed under the LGPLv3, included below. 5 | 6 | As a special exception to the GNU Lesser General Public License version 3 7 | ("LGPL3"), the copyright holders of this Library give you permission to 8 | convey to a third party a Combined Work that links statically or dynamically 9 | to this Library without providing any Minimal Corresponding Source or 10 | Minimal Application Code as set out in 4d or providing the installation 11 | information set out in section 4e, provided that you comply with the other 12 | provisions of LGPL3 and provided that you meet, for the Application the 13 | terms and conditions of the license(s) which apply to the Application. 14 | 15 | Except as stated in this special exception, the provisions of LGPL3 will 16 | continue to comply in full to this Library. If you modify this Library, you 17 | may apply this exception to your version of this Library, but you are not 18 | obliged to do so. If you do not wish to do so, delete this exception 19 | statement from your version. This exception does not (and cannot) modify any 20 | license terms which apply to the Application, with which you must still 21 | comply. 22 | 23 | 24 | GNU LESSER GENERAL PUBLIC LICENSE 25 | Version 3, 29 June 2007 26 | 27 | Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> 28 | Everyone is permitted to copy and distribute verbatim copies 29 | of this license document, but changing it is not allowed. 30 | 31 | 32 | This version of the GNU Lesser General Public License incorporates 33 | the terms and conditions of version 3 of the GNU General Public 34 | License, supplemented by the additional permissions listed below. 35 | 36 | 0. Additional Definitions. 37 | 38 | As used herein, "this License" refers to version 3 of the GNU Lesser 39 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 40 | General Public License. 41 | 42 | "The Library" refers to a covered work governed by this License, 43 | other than an Application or a Combined Work as defined below. 44 | 45 | An "Application" is any work that makes use of an interface provided 46 | by the Library, but which is not otherwise based on the Library. 47 | Defining a subclass of a class defined by the Library is deemed a mode 48 | of using an interface provided by the Library. 49 | 50 | A "Combined Work" is a work produced by combining or linking an 51 | Application with the Library. The particular version of the Library 52 | with which the Combined Work was made is also called the "Linked 53 | Version". 54 | 55 | The "Minimal Corresponding Source" for a Combined Work means the 56 | Corresponding Source for the Combined Work, excluding any source code 57 | for portions of the Combined Work that, considered in isolation, are 58 | based on the Application, and not on the Linked Version. 59 | 60 | The "Corresponding Application Code" for a Combined Work means the 61 | object code and/or source code for the Application, including any data 62 | and utility programs needed for reproducing the Combined Work from the 63 | Application, but excluding the System Libraries of the Combined Work. 64 | 65 | 1. Exception to Section 3 of the GNU GPL. 66 | 67 | You may convey a covered work under sections 3 and 4 of this License 68 | without being bound by section 3 of the GNU GPL. 69 | 70 | 2. Conveying Modified Versions. 71 | 72 | If you modify a copy of the Library, and, in your modifications, a 73 | facility refers to a function or data to be supplied by an Application 74 | that uses the facility (other than as an argument passed when the 75 | facility is invoked), then you may convey a copy of the modified 76 | version: 77 | 78 | a) under this License, provided that you make a good faith effort to 79 | ensure that, in the event an Application does not supply the 80 | function or data, the facility still operates, and performs 81 | whatever part of its purpose remains meaningful, or 82 | 83 | b) under the GNU GPL, with none of the additional permissions of 84 | this License applicable to that copy. 85 | 86 | 3. Object Code Incorporating Material from Library Header Files. 87 | 88 | The object code form of an Application may incorporate material from 89 | a header file that is part of the Library. You may convey such object 90 | code under terms of your choice, provided that, if the incorporated 91 | material is not limited to numerical parameters, data structure 92 | layouts and accessors, or small macros, inline functions and templates 93 | (ten or fewer lines in length), you do both of the following: 94 | 95 | a) Give prominent notice with each copy of the object code that the 96 | Library is used in it and that the Library and its use are 97 | covered by this License. 98 | 99 | b) Accompany the object code with a copy of the GNU GPL and this license 100 | document. 101 | 102 | 4. Combined Works. 103 | 104 | You may convey a Combined Work under terms of your choice that, 105 | taken together, effectively do not restrict modification of the 106 | portions of the Library contained in the Combined Work and reverse 107 | engineering for debugging such modifications, if you also do each of 108 | the following: 109 | 110 | a) Give prominent notice with each copy of the Combined Work that 111 | the Library is used in it and that the Library and its use are 112 | covered by this License. 113 | 114 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 115 | document. 116 | 117 | c) For a Combined Work that displays copyright notices during 118 | execution, include the copyright notice for the Library among 119 | these notices, as well as a reference directing the user to the 120 | copies of the GNU GPL and this license document. 121 | 122 | d) Do one of the following: 123 | 124 | 0) Convey the Minimal Corresponding Source under the terms of this 125 | License, and the Corresponding Application Code in a form 126 | suitable for, and under terms that permit, the user to 127 | recombine or relink the Application with a modified version of 128 | the Linked Version to produce a modified Combined Work, in the 129 | manner specified by section 6 of the GNU GPL for conveying 130 | Corresponding Source. 131 | 132 | 1) Use a suitable shared library mechanism for linking with the 133 | Library. A suitable mechanism is one that (a) uses at run time 134 | a copy of the Library already present on the user's computer 135 | system, and (b) will operate properly with a modified version 136 | of the Library that is interface-compatible with the Linked 137 | Version. 138 | 139 | e) Provide Installation Information, but only if you would otherwise 140 | be required to provide such information under section 6 of the 141 | GNU GPL, and only to the extent that such information is 142 | necessary to install and execute a modified version of the 143 | Combined Work produced by recombining or relinking the 144 | Application with a modified version of the Linked Version. (If 145 | you use option 4d0, the Installation Information must accompany 146 | the Minimal Corresponding Source and Corresponding Application 147 | Code. If you use option 4d1, you must provide the Installation 148 | Information in the manner specified by section 6 of the GNU GPL 149 | for conveying Corresponding Source.) 150 | 151 | 5. Combined Libraries. 152 | 153 | You may place library facilities that are a work based on the 154 | Library side by side in a single library together with other library 155 | facilities that are not Applications and are not covered by this 156 | License, and convey such a combined library under terms of your 157 | choice, if you do both of the following: 158 | 159 | a) Accompany the combined library with a copy of the same work based 160 | on the Library, uncombined with any other library facilities, 161 | conveyed under the terms of this License. 162 | 163 | b) Give prominent notice with the combined library that part of it 164 | is a work based on the Library, and explaining where to find the 165 | accompanying uncombined form of the same work. 166 | 167 | 6. Revised Versions of the GNU Lesser General Public License. 168 | 169 | The Free Software Foundation may publish revised and/or new versions 170 | of the GNU Lesser General Public License from time to time. Such new 171 | versions will be similar in spirit to the present version, but may 172 | differ in detail to address new problems or concerns. 173 | 174 | Each version is given a distinguishing version number. If the 175 | Library as you received it specifies that a certain numbered version 176 | of the GNU Lesser General Public License "or any later version" 177 | applies to it, you have the option of following the terms and 178 | conditions either of that published version or of any later version 179 | published by the Free Software Foundation. If the Library as you 180 | received it does not specify a version number of the GNU Lesser 181 | General Public License, you may choose any version of the GNU Lesser 182 | General Public License ever published by the Free Software Foundation. 183 | 184 | If the Library as you received it specifies that a proxy can decide 185 | whether future versions of the GNU Lesser General Public License shall 186 | apply, that proxy's public statement of acceptance of any version is 187 | permanent authorization for you to choose that version for the 188 | Library. 189 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v1/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.v1/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.v1*. 24 | 25 | To install it, run: 26 | 27 | go get gopkg.in/yaml.v1 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.v1](https://gopkg.in/yaml.v1) 35 | 36 | API stability 37 | ------------- 38 | 39 | The package API for yaml v1 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.v1" 59 | ) 60 | 61 | var data = ` 62 | a: Easy! 63 | b: 64 | c: 2 65 | d: [3, 4] 66 | ` 67 | 68 | type T struct { 69 | A string 70 | B struct{C int; D []int ",flow"} 71 | } 72 | 73 | func main() { 74 | t := T{} 75 | 76 | err := yaml.Unmarshal([]byte(data), &t) 77 | if err != nil { 78 | log.Fatalf("error: %v", err) 79 | } 80 | fmt.Printf("--- t:\n%v\n\n", t) 81 | 82 | d, err := yaml.Marshal(&t) 83 | if err != nil { 84 | log.Fatalf("error: %v", err) 85 | } 86 | fmt.Printf("--- t dump:\n%s\n\n", string(d)) 87 | 88 | m := make(map[interface{}]interface{}) 89 | 90 | err = yaml.Unmarshal([]byte(data), &m) 91 | if err != nil { 92 | log.Fatalf("error: %v", err) 93 | } 94 | fmt.Printf("--- m:\n%v\n\n", m) 95 | 96 | d, err = yaml.Marshal(&m) 97 | if err != nil { 98 | log.Fatalf("error: %v", err) 99 | } 100 | fmt.Printf("--- m dump:\n%s\n\n", string(d)) 101 | } 102 | ``` 103 | 104 | This example will generate the following output: 105 | 106 | ``` 107 | --- t: 108 | {Easy! {2 [3 4]}} 109 | 110 | --- t dump: 111 | a: Easy! 112 | b: 113 | c: 2 114 | d: [3, 4] 115 | 116 | 117 | --- m: 118 | map[a:Easy! b:map[c:2 d:[3 4]]] 119 | 120 | --- m dump: 121 | a: Easy! 122 | b: 123 | c: 2 124 | d: 125 | - 3 126 | - 4 127 | ``` 128 | 129 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v1/encode.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "reflect" 5 | "regexp" 6 | "sort" 7 | "strconv" 8 | "strings" 9 | "time" 10 | ) 11 | 12 | type encoder struct { 13 | emitter yaml_emitter_t 14 | event yaml_event_t 15 | out []byte 16 | flow bool 17 | } 18 | 19 | func newEncoder() (e *encoder) { 20 | e = &encoder{} 21 | e.must(yaml_emitter_initialize(&e.emitter)) 22 | yaml_emitter_set_output_string(&e.emitter, &e.out) 23 | e.must(yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING)) 24 | e.emit() 25 | e.must(yaml_document_start_event_initialize(&e.event, nil, nil, true)) 26 | e.emit() 27 | return e 28 | } 29 | 30 | func (e *encoder) finish() { 31 | e.must(yaml_document_end_event_initialize(&e.event, true)) 32 | e.emit() 33 | e.emitter.open_ended = false 34 | e.must(yaml_stream_end_event_initialize(&e.event)) 35 | e.emit() 36 | } 37 | 38 | func (e *encoder) destroy() { 39 | yaml_emitter_delete(&e.emitter) 40 | } 41 | 42 | func (e *encoder) emit() { 43 | // This will internally delete the e.event value. 44 | if !yaml_emitter_emit(&e.emitter, &e.event) && e.event.typ != yaml_DOCUMENT_END_EVENT && e.event.typ != yaml_STREAM_END_EVENT { 45 | e.must(false) 46 | } 47 | } 48 | 49 | func (e *encoder) must(ok bool) { 50 | if !ok { 51 | msg := e.emitter.problem 52 | if msg == "" { 53 | msg = "Unknown problem generating YAML content" 54 | } 55 | fail(msg) 56 | } 57 | } 58 | 59 | func (e *encoder) marshal(tag string, in reflect.Value) { 60 | if !in.IsValid() { 61 | e.nilv() 62 | return 63 | } 64 | var value interface{} 65 | if getter, ok := in.Interface().(Getter); ok { 66 | tag, value = getter.GetYAML() 67 | tag = longTag(tag) 68 | if value == nil { 69 | e.nilv() 70 | return 71 | } 72 | in = reflect.ValueOf(value) 73 | } 74 | switch in.Kind() { 75 | case reflect.Interface: 76 | if in.IsNil() { 77 | e.nilv() 78 | } else { 79 | e.marshal(tag, in.Elem()) 80 | } 81 | case reflect.Map: 82 | e.mapv(tag, in) 83 | case reflect.Ptr: 84 | if in.IsNil() { 85 | e.nilv() 86 | } else { 87 | e.marshal(tag, in.Elem()) 88 | } 89 | case reflect.Struct: 90 | e.structv(tag, in) 91 | case reflect.Slice: 92 | e.slicev(tag, in) 93 | case reflect.String: 94 | e.stringv(tag, in) 95 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 96 | if in.Type() == durationType { 97 | e.stringv(tag, reflect.ValueOf(in.Interface().(time.Duration).String())) 98 | } else { 99 | e.intv(tag, in) 100 | } 101 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 102 | e.uintv(tag, in) 103 | case reflect.Float32, reflect.Float64: 104 | e.floatv(tag, in) 105 | case reflect.Bool: 106 | e.boolv(tag, in) 107 | default: 108 | panic("Can't marshal type: " + in.Type().String()) 109 | } 110 | } 111 | 112 | func (e *encoder) mapv(tag string, in reflect.Value) { 113 | e.mappingv(tag, func() { 114 | keys := keyList(in.MapKeys()) 115 | sort.Sort(keys) 116 | for _, k := range keys { 117 | e.marshal("", k) 118 | e.marshal("", in.MapIndex(k)) 119 | } 120 | }) 121 | } 122 | 123 | func (e *encoder) structv(tag string, in reflect.Value) { 124 | sinfo, err := getStructInfo(in.Type()) 125 | if err != nil { 126 | panic(err) 127 | } 128 | e.mappingv(tag, func() { 129 | for _, info := range sinfo.FieldsList { 130 | var value reflect.Value 131 | if info.Inline == nil { 132 | value = in.Field(info.Num) 133 | } else { 134 | value = in.FieldByIndex(info.Inline) 135 | } 136 | if info.OmitEmpty && isZero(value) { 137 | continue 138 | } 139 | e.marshal("", reflect.ValueOf(info.Key)) 140 | e.flow = info.Flow 141 | e.marshal("", value) 142 | } 143 | }) 144 | } 145 | 146 | func (e *encoder) mappingv(tag string, f func()) { 147 | implicit := tag == "" 148 | style := yaml_BLOCK_MAPPING_STYLE 149 | if e.flow { 150 | e.flow = false 151 | style = yaml_FLOW_MAPPING_STYLE 152 | } 153 | e.must(yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)) 154 | e.emit() 155 | f() 156 | e.must(yaml_mapping_end_event_initialize(&e.event)) 157 | e.emit() 158 | } 159 | 160 | func (e *encoder) slicev(tag string, in reflect.Value) { 161 | implicit := tag == "" 162 | style := yaml_BLOCK_SEQUENCE_STYLE 163 | if e.flow { 164 | e.flow = false 165 | style = yaml_FLOW_SEQUENCE_STYLE 166 | } 167 | e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)) 168 | e.emit() 169 | n := in.Len() 170 | for i := 0; i < n; i++ { 171 | e.marshal("", in.Index(i)) 172 | } 173 | e.must(yaml_sequence_end_event_initialize(&e.event)) 174 | e.emit() 175 | } 176 | 177 | // isBase60 returns whether s is in base 60 notation as defined in YAML 1.1. 178 | // 179 | // The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported 180 | // in YAML 1.2 and by this package, but these should be marshalled quoted for 181 | // the time being for compatibility with other parsers. 182 | func isBase60Float(s string) (result bool) { 183 | // Fast path. 184 | if s == "" { 185 | return false 186 | } 187 | c := s[0] 188 | if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 { 189 | return false 190 | } 191 | // Do the full match. 192 | return base60float.MatchString(s) 193 | } 194 | 195 | // From http://yaml.org/type/float.html, except the regular expression there 196 | // is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix. 197 | var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`) 198 | 199 | func (e *encoder) stringv(tag string, in reflect.Value) { 200 | var style yaml_scalar_style_t 201 | s := in.String() 202 | rtag, rs := resolve("", s) 203 | if rtag == yaml_BINARY_TAG { 204 | if tag == "" || tag == yaml_STR_TAG { 205 | tag = rtag 206 | s = rs.(string) 207 | } else if tag == yaml_BINARY_TAG { 208 | fail("explicitly tagged !!binary data must be base64-encoded") 209 | } else { 210 | fail("cannot marshal invalid UTF-8 data as " + shortTag(tag)) 211 | } 212 | } 213 | if tag == "" && (rtag != yaml_STR_TAG || isBase60Float(s)) { 214 | style = yaml_DOUBLE_QUOTED_SCALAR_STYLE 215 | } else if strings.Contains(s, "\n") { 216 | style = yaml_LITERAL_SCALAR_STYLE 217 | } else { 218 | style = yaml_PLAIN_SCALAR_STYLE 219 | } 220 | e.emitScalar(s, "", tag, style) 221 | } 222 | 223 | func (e *encoder) boolv(tag string, in reflect.Value) { 224 | var s string 225 | if in.Bool() { 226 | s = "true" 227 | } else { 228 | s = "false" 229 | } 230 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) 231 | } 232 | 233 | func (e *encoder) intv(tag string, in reflect.Value) { 234 | s := strconv.FormatInt(in.Int(), 10) 235 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) 236 | } 237 | 238 | func (e *encoder) uintv(tag string, in reflect.Value) { 239 | s := strconv.FormatUint(in.Uint(), 10) 240 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) 241 | } 242 | 243 | func (e *encoder) floatv(tag string, in reflect.Value) { 244 | // FIXME: Handle 64 bits here. 245 | s := strconv.FormatFloat(float64(in.Float()), 'g', -1, 32) 246 | switch s { 247 | case "+Inf": 248 | s = ".inf" 249 | case "-Inf": 250 | s = "-.inf" 251 | case "NaN": 252 | s = ".nan" 253 | } 254 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) 255 | } 256 | 257 | func (e *encoder) nilv() { 258 | e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE) 259 | } 260 | 261 | func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t) { 262 | implicit := tag == "" 263 | e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style)) 264 | e.emit() 265 | } 266 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v1/resolve.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "encoding/base64" 5 | "fmt" 6 | "math" 7 | "strconv" 8 | "strings" 9 | "unicode/utf8" 10 | ) 11 | 12 | // TODO: merge, timestamps, base 60 floats, omap. 13 | 14 | type resolveMapItem struct { 15 | value interface{} 16 | tag string 17 | } 18 | 19 | var resolveTable = make([]byte, 256) 20 | var resolveMap = make(map[string]resolveMapItem) 21 | 22 | func init() { 23 | t := resolveTable 24 | t[int('+')] = 'S' // Sign 25 | t[int('-')] = 'S' 26 | for _, c := range "0123456789" { 27 | t[int(c)] = 'D' // Digit 28 | } 29 | for _, c := range "yYnNtTfFoO~" { 30 | t[int(c)] = 'M' // In map 31 | } 32 | t[int('.')] = '.' // Float (potentially in map) 33 | 34 | var resolveMapList = []struct { 35 | v interface{} 36 | tag string 37 | l []string 38 | }{ 39 | {true, yaml_BOOL_TAG, []string{"y", "Y", "yes", "Yes", "YES"}}, 40 | {true, yaml_BOOL_TAG, []string{"true", "True", "TRUE"}}, 41 | {true, yaml_BOOL_TAG, []string{"on", "On", "ON"}}, 42 | {false, yaml_BOOL_TAG, []string{"n", "N", "no", "No", "NO"}}, 43 | {false, yaml_BOOL_TAG, []string{"false", "False", "FALSE"}}, 44 | {false, yaml_BOOL_TAG, []string{"off", "Off", "OFF"}}, 45 | {nil, yaml_NULL_TAG, []string{"", "~", "null", "Null", "NULL"}}, 46 | {math.NaN(), yaml_FLOAT_TAG, []string{".nan", ".NaN", ".NAN"}}, 47 | {math.Inf(+1), yaml_FLOAT_TAG, []string{".inf", ".Inf", ".INF"}}, 48 | {math.Inf(+1), yaml_FLOAT_TAG, []string{"+.inf", "+.Inf", "+.INF"}}, 49 | {math.Inf(-1), yaml_FLOAT_TAG, []string{"-.inf", "-.Inf", "-.INF"}}, 50 | {"<<", yaml_MERGE_TAG, []string{"<<"}}, 51 | } 52 | 53 | m := resolveMap 54 | for _, item := range resolveMapList { 55 | for _, s := range item.l { 56 | m[s] = resolveMapItem{item.v, item.tag} 57 | } 58 | } 59 | } 60 | 61 | const longTagPrefix = "tag:yaml.org,2002:" 62 | 63 | func shortTag(tag string) string { 64 | // TODO This can easily be made faster and produce less garbage. 65 | if strings.HasPrefix(tag, longTagPrefix) { 66 | return "!!" + tag[len(longTagPrefix):] 67 | } 68 | return tag 69 | } 70 | 71 | func longTag(tag string) string { 72 | if strings.HasPrefix(tag, "!!") { 73 | return longTagPrefix + tag[2:] 74 | } 75 | return tag 76 | } 77 | 78 | func resolvableTag(tag string) bool { 79 | switch tag { 80 | case "", yaml_STR_TAG, yaml_BOOL_TAG, yaml_INT_TAG, yaml_FLOAT_TAG, yaml_NULL_TAG: 81 | return true 82 | } 83 | return false 84 | } 85 | 86 | func resolve(tag string, in string) (rtag string, out interface{}) { 87 | if !resolvableTag(tag) { 88 | return tag, in 89 | } 90 | 91 | defer func() { 92 | switch tag { 93 | case "", rtag, yaml_STR_TAG, yaml_BINARY_TAG: 94 | return 95 | } 96 | fail(fmt.Sprintf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag))) 97 | }() 98 | 99 | // Any data is accepted as a !!str or !!binary. 100 | // Otherwise, the prefix is enough of a hint about what it might be. 101 | hint := byte('N') 102 | if in != "" { 103 | hint = resolveTable[in[0]] 104 | } 105 | if hint != 0 && tag != yaml_STR_TAG && tag != yaml_BINARY_TAG { 106 | // Handle things we can lookup in a map. 107 | if item, ok := resolveMap[in]; ok { 108 | return item.tag, item.value 109 | } 110 | 111 | // Base 60 floats are a bad idea, were dropped in YAML 1.2, and 112 | // are purposefully unsupported here. They're still quoted on 113 | // the way out for compatibility with other parser, though. 114 | 115 | switch hint { 116 | case 'M': 117 | // We've already checked the map above. 118 | 119 | case '.': 120 | // Not in the map, so maybe a normal float. 121 | floatv, err := strconv.ParseFloat(in, 64) 122 | if err == nil { 123 | return yaml_FLOAT_TAG, floatv 124 | } 125 | 126 | case 'D', 'S': 127 | // Int, float, or timestamp. 128 | plain := strings.Replace(in, "_", "", -1) 129 | intv, err := strconv.ParseInt(plain, 0, 64) 130 | if err == nil { 131 | if intv == int64(int(intv)) { 132 | return yaml_INT_TAG, int(intv) 133 | } else { 134 | return yaml_INT_TAG, intv 135 | } 136 | } 137 | floatv, err := strconv.ParseFloat(plain, 64) 138 | if err == nil { 139 | return yaml_FLOAT_TAG, floatv 140 | } 141 | if strings.HasPrefix(plain, "0b") { 142 | intv, err := strconv.ParseInt(plain[2:], 2, 64) 143 | if err == nil { 144 | return yaml_INT_TAG, int(intv) 145 | } 146 | } else if strings.HasPrefix(plain, "-0b") { 147 | intv, err := strconv.ParseInt(plain[3:], 2, 64) 148 | if err == nil { 149 | return yaml_INT_TAG, -int(intv) 150 | } 151 | } 152 | // XXX Handle timestamps here. 153 | 154 | default: 155 | panic("resolveTable item not yet handled: " + string(rune(hint)) + " (with " + in + ")") 156 | } 157 | } 158 | if tag == yaml_BINARY_TAG { 159 | return yaml_BINARY_TAG, in 160 | } 161 | if utf8.ValidString(in) { 162 | return yaml_STR_TAG, in 163 | } 164 | return yaml_BINARY_TAG, encodeBase64(in) 165 | } 166 | 167 | // encodeBase64 encodes s as base64 that is broken up into multiple lines 168 | // as appropriate for the resulting length. 169 | func encodeBase64(s string) string { 170 | const lineLen = 70 171 | encLen := base64.StdEncoding.EncodedLen(len(s)) 172 | lines := encLen/lineLen + 1 173 | buf := make([]byte, encLen*2+lines) 174 | in := buf[0:encLen] 175 | out := buf[encLen:] 176 | base64.StdEncoding.Encode(in, []byte(s)) 177 | k := 0 178 | for i := 0; i < len(in); i += lineLen { 179 | j := i + lineLen 180 | if j > len(in) { 181 | j = len(in) 182 | } 183 | k += copy(out[k:], in[i:j]) 184 | if lines > 1 { 185 | out[k] = '\n' 186 | k++ 187 | } 188 | } 189 | return string(out[:k]) 190 | } 191 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v1/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.v1/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.v1/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 | --------------------------------------------------------------------------------