Full Code of EagerIO/Stout for AI

master e50d63a2f523 cached
97 files
1.3 MB
498.2k tokens
1617 symbols
1 requests
Download .txt
Showing preview only (1,408K chars total). Download the full file or copy to clipboard to get everything.
Repository: EagerIO/Stout
Branch: master
Commit: e50d63a2f523
Files: 97
Total size: 1.3 MB

Directory structure:
gitextract_dxdit0ui/

├── .github/
│   └── workflows/
│       └── semgrep.yml
├── .gitignore
├── Godeps/
│   ├── Godeps.json
│   └── Readme
├── LICENSE
├── README.md
├── docs/
│   └── getting-started.md
├── 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

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/semgrep.yml
================================================
on:
  pull_request: {}
  workflow_dispatch: {}
  push: 
    branches:
      - main
      - master
  schedule:
    - cron: '0 0 * * *'
name: Semgrep config
jobs:
  semgrep:
    name: semgrep/ci
    runs-on: ubuntu-latest
    env:
      SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}
      SEMGREP_URL: https://cloudflare.semgrep.dev
      SEMGREP_APP_URL: https://cloudflare.semgrep.dev
      SEMGREP_VERSION_CHECK_URL: https://cloudflare.semgrep.dev/api/check-version
    container:
      image: semgrep/semgrep
    steps:
      - uses: actions/checkout@v4
      - run: semgrep ci


================================================
FILE: .gitignore
================================================
.DS_Store
builds/
debian/


================================================
FILE: Godeps/Godeps.json
================================================
{
	"ImportPath": "github.com/eagerio/stout",
	"GoVersion": "go1.6",
	"GodepVersion": "v63",
	"Packages": [
		"./..."
	],
	"Deps": [
		{
			"ImportPath": "github.com/cenk/backoff",
			"Comment": "v1.0.0-7-gcdf48bb",
			"Rev": "cdf48bbc1eb78d1349cbda326a4a037f7ba565c6"
		},
		{
			"ImportPath": "github.com/imdario/mergo",
			"Comment": "0.2.2-6-g50d4dbd",
			"Rev": "50d4dbd4eb0e84778abe37cefef140271d96fade"
		},
		{
			"ImportPath": "github.com/mitchellh/go-homedir",
			"Rev": "1111e456ffea841564ac0fa5f69c26ef44dafec9"
		},
		{
			"ImportPath": "github.com/wsxiaoys/terminal/color",
			"Rev": "0940f3fc43a0ed42d04916b1c04578462c650b09"
		},
		{
			"ImportPath": "github.com/zackbloom/go-ini",
			"Rev": "3db81f263990ac57212cfdc3ce9a65e8af8af966"
		},
		{
			"ImportPath": "github.com/zackbloom/goamz/aws",
			"Rev": "0f589c21f1937992b2952e1f4ce0d31f132b685d"
		},
		{
			"ImportPath": "github.com/zackbloom/goamz/cloudfront",
			"Rev": "0f589c21f1937992b2952e1f4ce0d31f132b685d"
		},
		{
			"ImportPath": "github.com/zackbloom/goamz/iam",
			"Rev": "0f589c21f1937992b2952e1f4ce0d31f132b685d"
		},
		{
			"ImportPath": "github.com/zackbloom/goamz/route53",
			"Rev": "0f589c21f1937992b2952e1f4ce0d31f132b685d"
		},
		{
			"ImportPath": "github.com/zackbloom/goamz/s3",
			"Rev": "0f589c21f1937992b2952e1f4ce0d31f132b685d"
		},
		{
			"ImportPath": "golang.org/x/crypto/ssh/terminal",
			"Rev": "5bcd134fee4dd1475da17714aac19c0aa0142e2f"
		},
		{
			"ImportPath": "golang.org/x/net/html",
			"Rev": "8a52c78636f6b7be1b1e5cb58b01a85f1e082659"
		},
		{
			"ImportPath": "golang.org/x/net/html/atom",
			"Rev": "8a52c78636f6b7be1b1e5cb58b01a85f1e082659"
		},
		{
			"ImportPath": "golang.org/x/net/publicsuffix",
			"Rev": "8a52c78636f6b7be1b1e5cb58b01a85f1e082659"
		},
		{
			"ImportPath": "gopkg.in/yaml.v1",
			"Rev": "9f9df34309c04878acc86042b16630b0f696e1de"
		}
	]
}


================================================
FILE: Godeps/Readme
================================================
This directory tree is generated automatically by godep.

Please do not edit.

See https://github.com/tools/godep for more information.


================================================
FILE: LICENSE
================================================
Copyright (c) 2014 Eager Platform Co.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


================================================
FILE: README.md
================================================
# Stout

#### [View the site →](http://stout.is/)

Stout is a deploy tool for static websites.  It takes a website and uploads it to S3 in a more reliable way than other tools.  It can be an alternative
to paid services like Divshot, to dynamic web servers like Rails, or to manually uploading your site to S3 or an FTP server.

## Why You Need Stout

Traditionally uploading your files to S3 introduces a serious caching issue we ran into in practice at [Eager](https://eager.io).
The cache for the various files your site depends on can expire at different times, meaning your users get an inconsistent (broken) set of files for a
time after every single deploy. Further, traditional static site deployments don't offer any method of rolling back a previous deploy.

We built Stout to fix these issues.

### Features

- Versions script and style files to ensure your pages don't use an inconsistent set of files during or after a deploy
- Supports rollback to any previous version
- Does not depend on any specific build tool or workflow (it is a standalone executable written in Go)
- Does not require a datastore of any kind to maintain state or history
- Can be used by multiple developers simultaneously without locking or a danger of inconsistent state
- Properly handles caching headers
- Supports deploying multiple projects to various subdirectories of the same site without conflicts
- Compresses files for faster delivery

### Limitations

- Stout doesn't currently support rolling back files that aren't HTML, JS or CSS (images, videos, etc.).  See the Versioning section for more information.
- All-or-nothing consistency is only guarenteed on a per-html-file basis, not for the entire deploy.  See the Consistency section for more information.

## Getting Started

[Download](https://github.com/EagerIO/Stout/releases) the `stout` executable for your system from our latest release into a directory on your `$PATH`, like `/usr/local/bin`.

You can use the `create` command to create a new site.  It automatically creates an S3 bucket, a CloudFront distribution, and a user account for deployment.  It therefore requires
credentials for an Amazon AWS account which has permissions to those services along with Route 53.

```sh
stout create --bucket my.website.com --key MY_AWS_KEY --secret MY_AWS_SECRET
```

You can then deploy your project:

```sh
stout deploy --bucket my.website.com --key MY_AWS_KEY --secret MY_AWS_SECRET
```

If your built files are in another directory, add the `--root` option:

```sh
stout deploy --bucket my.website.com --key MY_AWS_KEY --secret MY_AWS_SECRET --root ./build
```

If your bucket located not in the default region, which is us-east-1, add the `--region` option:

```sh
stout deploy --bucket my.website.com --key MY_AWS_KEY --secret MY_AWS_SECRET --region us-west-1
```

If you don't want to deploy all the files in your folder, use the files argument.

```sh
stout deploy --bucket my.website.com --key MY_AWS_KEY --secret MY_AWS_SECRET --root ./build --files "*.html,images/*"
```

Javascript and CSS included in your HTML files will always be included automatically.

The deploy command will give you a deploy id you can use in the future to rollback if you have to:

```sh
stout rollback --bucket my.website.com --key MY_AWS_KEY --secret MY_AWS_SECRET a3b8ff290c33
```

Eventually you'll probably want to move your config to a deploy.yaml file, rather than specifying it in the command every time.

Using the info below you can learn about what the deploy/rollback tools actually do, deploying to subfolders, deploying from your build tool, and rolling back.

## Backstory

We wrote Stout because we couldn't find an open-source way to reliably and efficiently deploy our static sites (including our app and blog).  We used a traditional upload-to-s3 tool, but caching meant a user could get the new html and styles, but the old scripts, for example, causing sporatic and random errors.  It also didn't support reliably rolling back when necessary.  We built Stout to be the reliable, production-ready choice for static deploys.

## Function

Stout is an executable file built from Go code.  The `deploy` command deploys one or more html files and their dependencies to a specified location in S3.  The `rollback` command takes a deploy id and rolls the project back to that version.

### Deploy

The deploy process works by parsing the script and style tags out of one or more html files.  It then hashes those files, uploads them prefixed with their hashes, and updates the location of the original script and link tags with the hashed locations.

It generates a deploy id by hashing all of the files in the deploy, and uploads the html files to a location prefixed by the deploy id.

When the uploads are successful, the prefixed html files are atomically copied to their unprefixed paths, completing the deploy.

### Rollback

A rollback simply copies the html files prefixed with the specified deploy id to the unprefixed paths.

### Deploy Configuration

You can configure the deploy tool with any combination of command line flags or arguments provided in a configuration yaml file.

The options are:

##### `bucket`
  The S3 bucket to deploy to.  In most configurations this bucket should be the origin for the CDN which actually serves your site.  It usually makes sense to make this the url you are going to host your site from (i.e. `"example.com"`)
  	
##### `config` ("./deploy.yaml")
  The location of a yaml file to read any otherwise unspecified configuration from.
   
##### `dest` ("./")
  The destination directory to write files to in the S3 bucket.   For example if you wanted your this project to end up hosted at `yoursite.com/blog`, you would specify `--dest blog`.
  	
##### `root` ("./")
 The local directory where the files to be uploaded lives.  It's common to make this your "./build" directory or the like.
 
##### `files` ("*")
  Comma-seperated glob patterns of the files to be deployed (within the `--root`).  HTML files will be parsed, and the CSS/JS they point to will be included (versioned) automatically.  If you also include those files in your glob pattern they will be uploaded twice, once with a versioning hash in the URL, again without.
  
  Be sure to include any additional files you would like deployed like images, videos, font files, etc.

  You can use relative paths which break out of the `root`.  If you prefix the path with `-/`, it will be interpreted as relative to the project directory, not the `root`.
  	
##### `env`
  The config file can contain configurations for multiple environments (production, staging, etc.).  This specifies which is used.  See the "YAML Config" section for more information.

##### `key`
  The AWS key to use.  The create command will create an IAM user for each project with access only to the relevant bucket.  See the Permissions section for more information.
  
##### `secret`
  The AWS secret of the provided key.

##### `region` ("us-east-1")
  The AWS region the S3 bucket is located in. 
  
  If you are getting a `The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint.` error, specify your bucket `--region`.
   
### YAML Config

You can provide a yaml file which specifies configuration defaults for the project being deployed.  We include this file in each project which will be deployed.  This file can have multiple configurations for different environments, along with a default section.

For example, the `deploy.yaml` for one of our projects looks like:

```yaml
default:
  root: 'build/'

production:
  key: 'XXX'
  secret: 'XXX'
  bucket: 'eager.io'

development:
  key: 'XXX'
  secret: 'XXX'
  bucket: 'next.eager.io'
```

Replacing the "XXX"s with our actual credentials.

To deploy to development we run (from the directory with the deploy.yaml file in it):

```bash
deploy --env development
```

A rollback of development would be:

```bash
rollback --env development $DEPLOY_ID
```

Where the deploy id is taken from the output of the deploy you wish to rollback to.
 
Our public projects use a similar config, but they specify the Amazon credentials as environment vars from the build system, passed in as flags:
 
 ```bash
deploy --env development --key $AMAZON_KEY_DEV --secret $AMAZON_SECRET_DEV
```

Never commit Amazon credentials to a file in a public repo.  Keep them on your local machine, or in your build system's configuration.

### Clean URLS

It's not specific to Stout, but it's worth mentioning that we recommend you structure your built folder to use a folder with an index.html file for each page.

For example, if you want a root and a page at `/blog`, you would have:

```
index.html
blog/
  index.html
```

That way, assuming S3 and CloudFront are configured properly, you'll be able to use the clean URLs `/` and `/blog/`.

### SSL

Cloudfront has the ability to serve your site using SSL.  The general procedure for setting it up is:

1. Get an SSL certificate for your domain
2. Upload it to Amazon
3. Select that certificate in the configuration for the CloudFront distribution Stout creates for you

You will absolutely need more detailed instructions, which you can find [here](https://bryce.fisher-fleig.org/blog/setting-up-ssl-on-aws-cloudfront-and-s3/).

Selecting a certificate for you is one of the few things the `create` command does not do, as it's not always possible to decide which certificate is appropriate.  If you need SSL support, you will have to remember to select the cert in the Amazon Console or CLI after running the `create` command.

### Permissions

The AWS user which is used for Stout should have the `GetObject`, `PutObject`, `DeleteObject`, and `ListBucket` permissions.  The `create` command will set this up for you if you use it.

This is an example policy config which works:

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:DeleteObject",
        "s3:ListBucket",
        "s3:PutObject",
        "s3:PutObjectAcl",
        "s3:GetObject"
      ],
      "Resource": [
        "arn:aws:s3:::BUCKET", "arn:aws:s3:::BUCKET/*"
      ]
    }
  ]
}
```

Be sure to replace `BUCKET` with your bucket's actual name.

### Deploying with CircleCI
 
 Deploying with CircleCI is simply a matter of installing the deploy tool and running it as you would locally.  Here's an excerpt of a working circle.yml:
 
 ```yaml
dependencies:
  post:
    - go get github.com/tools/godep
    - git clone git@github.com:EagerIO/Stout.git
    - cd Stout; godep go build -o ../stout src/*.go
    
deployment:
  development:
    branch: dev
    commands:
      - ./stout deploy --env development --key $AMAZON_KEY_DEV --secret $AMAZON_SECRET_DEV

  production:
    branch: master
    commands:
      - ./stout deploy --env production --key $AMAZON_KEY_PROD --secret $AMAZON_SECRET_PROD
 ```
 
If you use environment vars for your credentials, make sure to add them to your Circle config.
 
If your repo is private, you can specify your Amazon key and secret in your deploy.yaml file, removing the need to specify them in the commands.
 
### Caching

All versioned files (include a hash of their contents in the path) are configured to cache for one year.  All unversioned files are configured to cache for 60 seconds.  This means it will take up to 60 seconds for users to see changes made to your site.

### Versioning

Only JS and CSS files which are pointed to in HTML files are hashed, as we need to be able to update the HTML to point to our new, versioned, files.

Any other file included in your `--files` argument will be uploaded, but not versioned, meaning a rollback will not effect these files.  This is something we'd like to improve. 
 
### Consistency

As the final step of the deploy is atomic, multiple actors can trigger deploys simultaneously without any danger of inconsistent state.  Whichever process triggers the final 'copy' step for a given file will win, with it's specified dependencies guarenteed to be used in their entirity.  Note that this consistency is only guarenteed on a per-html-file level, you may end up with some html files from one deployer, and others from another, but all files will point to their correct dependencies.

### Deploying Multiple Projects To One Site

You can deploy multiple projects to the same domain simply by specifying the appropriate `dest` for each one.  For example your homepage might have the dest `./`, and your blog `./blog`.  Your homepage will be hosted at `your-site.com`, your blog `your-site.com/blog`.

### Using Client-side Routers

It is possible to use a client-side router (where you have multiple request URLs point to the same HTML file) by configuring your CloudFront distribution to serve your index.html file in response to 403s and 404s.

![CF](https://raw.githubusercontent.com/EagerIO/Stout/master/docs/images/cf-screenshot.png)

### Installing

- Download the release for your system type from our [releases](https://github.com/EagerIO/Stout/releases)
- Copy or symlink the `stout` binary contained in the archive into your path (for example, into `/usr/local/bin`)

### Building

- Install go and godep
- Run `godep restore ./...`
- Run `go build -o ../stout src/*`

#### For a Release (Cross Compiling)

- Run `go get github.com/laher/goxc`
- Run `go get code.google.com/p/go.tools/cmd/vet`
- Run `./utils/xc.sh`

The first run will take significantly longer than future runs.  The built files will be placed in the `./builds` directory.

### Running

To run the commands for development purposes, run: `go run src/*`, followed by any command line args you would normally give to the command.

### Contributing

Please do, we would love for this to become a project of the community.  Feel free to open an issue, submit a PR or contribute to the wiki.


================================================
FILE: docs/getting-started.md
================================================
### Setting Up Your Site

If you don't already have an S3-hosted site, start here.

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:

```
The Deploy Tool -> S3 <- CloudFront's Global CDN <- DNS <- Your Users
```

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:

```bash
./utils/create_site.sh subdomain.my-site.com
```

Feel free to leave out the subdomain if you'd like to host it at the root of your domain.

This will:

- Create an S3 bucket for this site with the correct security policy and website hosting
- Create a CloudFront distribution pointed at that bucket
- Create a user with the appropriate permissions to upload to that bucket
- Create an access key for that user

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.

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.

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.

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.

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.

#### Step-by-step Instructions

1. Install Amazon's AWS Command-Line Tools (and create an AWS account if you don't have one)
1. Run the `create_site.sh` tool with the URL of the site you'd like to deploy
1. Take note of the AWS key and secret in the final JSON blob outputted by the script
1. Download the executable from this project
1. Run `stout deploy --bucket subdomain.your-site.com --key YOUR_NEW_AWS_KEY --secret YOUR_NEW_AWS_SECRET` to deploy
1. Add the `--root` argument if your built files are in a subdirectory.
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
1. Optionally, Move any configuration options you don't mind being committed to your repository to a deploy.yaml file
1. Optionally, Run `create_site.sh` again to create staging or development sites, and add their configuration to your deploy.yaml as well
1. Optionally, Deploy more projects to this same site by running deploy with the `--dest` argument
1. Optionally, Add the deploy step to your build tool


================================================
FILE: src/admin.go
================================================
package main

import (
	"fmt"
	"os"
	"os/exec"
	"strings"

	"github.com/zackbloom/goamz/cloudfront"
	"github.com/zackbloom/goamz/iam"
	"github.com/zackbloom/goamz/route53"
	"github.com/zackbloom/goamz/s3"
	"golang.org/x/crypto/ssh/terminal"
	"golang.org/x/net/publicsuffix"
)

func CreateBucket(options Options) error {
	bucket := s3Session.Bucket(options.Bucket)

	err := bucket.PutBucket("public-read")
	if err != nil {
		return err
	}

	err = bucket.PutBucketWebsite(s3.WebsiteConfiguration{
		IndexDocument: &s3.IndexDocument{"index.html"},
		ErrorDocument: &s3.ErrorDocument{"error.html"},
	})
	if err != nil {
		return err
	}

	err = bucket.PutPolicy([]byte(`{
			"Version": "2008-10-17",
			"Statement": [
				{
					"Sid": "PublicReadForGetBucketObjects",
					"Effect": "Allow",
					"Principal": {
						"AWS": "*"
					},
					"Action": "s3:GetObject",
					"Resource": "arn:aws:s3:::` + options.Bucket + `/*"
				}
			]
		}`,
	))
	if err != nil {
		return err
	}

	return nil
}

func GetDistribution(options Options) (dist cloudfront.DistributionSummary, err error) {
	distP, err := cfSession.FindDistributionByAlias(options.Bucket)
	if err != nil {
		return
	}

	if distP != nil {
		fmt.Println("CloudFront distribution found with the provided bucket name, assuming config matches.")
		fmt.Println("If you run into issues, delete the distribution and rerun this command.")

		dist = *distP
		return
	}

	conf := cloudfront.DistributionConfig{
		Origins: cloudfront.Origins{
			cloudfront.Origin{
				Id:         "S3-" + options.Bucket,
				DomainName: options.Bucket + ".s3-website-" + options.AWSRegion + ".amazonaws.com",
				CustomOriginConfig: &cloudfront.CustomOriginConfig{
					HTTPPort:             80,
					HTTPSPort:            443,
					OriginProtocolPolicy: "http-only",
				},
			},
		},
		DefaultRootObject: "index.html",
		PriceClass:        "PriceClass_All",
		Enabled:           true,
		DefaultCacheBehavior: cloudfront.CacheBehavior{
			TargetOriginId:       "S3-" + options.Bucket,
			ViewerProtocolPolicy: "allow-all",
			AllowedMethods: cloudfront.AllowedMethods{
				Allowed: []string{"GET", "HEAD"},
				Cached:  []string{"GET", "HEAD"},
			},
		},
		ViewerCertificate: &cloudfront.ViewerCertificate{
			CloudFrontDefaultCertificate: true,
			MinimumProtocolVersion:       "TLSv1",
			SSLSupportMethod:             "sni-only",
		},
		CustomErrorResponses: cloudfront.CustomErrorResponses{
			// This adds support for single-page apps
			cloudfront.CustomErrorResponse{
				ErrorCode:          403,
				ResponsePagePath:   "/index.html",
				ResponseCode:       200,
				ErrorCachingMinTTL: 60,
			},
			cloudfront.CustomErrorResponse{
				ErrorCode:          404,
				ResponsePagePath:   "/index.html",
				ResponseCode:       200,
				ErrorCachingMinTTL: 60,
			},
		},
		Aliases: cloudfront.Aliases{
			options.Bucket,
		},
	}

	return cfSession.Create(conf)
}

func CreateUser(options Options) (key iam.AccessKey, err error) {
	name := options.Bucket + "_deploy"

	_, err = iamSession.CreateUser(name, "/")
	if err != nil {
		iamErr, ok := err.(*iam.Error)
		if ok && iamErr.Code == "EntityAlreadyExists" {
			err = nil
		} else {
			return
		}
	}

	_, err = iamSession.PutUserPolicy(name, name, `{
			"Version": "2012-10-17",
			"Statement": [
				{
					"Effect": "Allow",
					"Action": [
						"s3:DeleteObject",
						"s3:ListBucket",
						"s3:PutObject",
						"s3:PutObjectAcl",
						"s3:GetObject"
					],
					"Resource": [
						"arn:aws:s3:::`+options.Bucket+`", "arn:aws:s3:::`+options.Bucket+`/*"
					]
				}
			]
		}`,
	)
	if err != nil {
		return
	}

	keyResp, err := iamSession.CreateAccessKey(name)
	if err != nil {
		return
	}

	return keyResp.AccessKey, nil
}

func UpdateRoute(options Options, dist cloudfront.DistributionSummary) error {
	zoneName, err := publicsuffix.EffectiveTLDPlusOne(options.Bucket)
	if err != nil {
		return err
	}

	zoneName = zoneName + "."

	resp, err := r53Session.ListHostedZonesByName(zoneName, "", 100)
	if err != nil {
		return err
	}

	if resp.IsTruncated {
		panic("More than 100 zones in the account")
	}

	var zone *route53.HostedZone
	for _, z := range resp.HostedZones {
		if z.Name == zoneName {
			zone = &z
			break
		}
	}

	if zone == nil {
		fmt.Printf("A Route 53 hosted zone was not found for %s\n", zoneName)
		if zoneName != options.Bucket {
			fmt.Println("If you would like to use Route 53 to manage your DNS, create a zone for this domain, and update your registrar's configuration to point to the DNS servers Amazon provides and rerun this command.  Note that you must copy any existing DNS configuration you have to Route 53 if you do not wish existing services hosted on this domain to stop working.")
			fmt.Printf("If you would like to continue to use your existing DNS, create a CNAME record pointing %s to %s and the site setup will be finished.\n", options.Bucket, dist.DomainName)
		} else {
			fmt.Println("Since you are hosting the root of your domain, using an alternative DNS host is unfortunately not possible.")
			fmt.Println("If you wish to host your site at the root of your domain, you must switch your sites DNS to Amazon's Route 53 and retry this command.")
		}

		return nil
	}

	fmt.Printf("Adding %s to %s Route 53 zone\n", options.Bucket, zone.Name)
	parts := strings.Split(zone.Id, "/")
	idValue := parts[2]

	_, err = r53Session.ChangeResourceRecordSet(&route53.ChangeResourceRecordSetsRequest{
		Changes: []route53.Change{
			route53.Change{
				Action: "CREATE",
				Name:   options.Bucket,
				Type:   "A",
				AliasTarget: route53.AliasTarget{
					HostedZoneId:         "Z2FDTNDATAQYW2",
					DNSName:              dist.DomainName,
					EvaluateTargetHealth: false,
				},
			},
		},
	}, idValue)

	if err != nil {
		if strings.Contains(err.Error(), "it already exists") {
			fmt.Println("Existing route found, assuming it is correct")
			fmt.Printf("If you run into trouble, you may need to delete the %s route in Route53 and try again\n", options.Bucket)
			return nil
		}
		return err
	}

	return nil
}

func Create(options Options) {
	if s3Session == nil {
		s3Session = openS3(options.AWSKey, options.AWSSecret, options.AWSRegion, options.S3Host)
	}
	if iamSession == nil {
		iamSession = openIAM(options.AWSKey, options.AWSSecret, options.AWSRegion)
	}
	if r53Session == nil {
		r53Session = openRoute53(options.AWSKey, options.AWSSecret)
	}
	if cfSession == nil {
		cfSession = openCloudFront(options.AWSKey, options.AWSSecret)
	}

	_, err := exec.LookPath("aws")
	if err != nil {
		fmt.Println("The aws CLI executable was not found in the PATH")
		fmt.Println("Install it from http://aws.amazon.com/cli/ and try again")
	}

	fmt.Println("Creating Bucket")
	err = CreateBucket(options)

	if err != nil {
		fmt.Println("Error creating S3 bucket")
		fmt.Println(err)
		return
	}

	fmt.Println("Loading/Creating CloudFront Distribution")
	dist, err := GetDistribution(options)

	if err != nil {
		fmt.Println("Error loading/creating CloudFront distribution")
		fmt.Println(err)
		return
	}

	fmt.Println("Adding Route")
	err = UpdateRoute(options, dist)

	if err != nil {
		fmt.Println("Error adding route to Route53 DNS config")
		fmt.Println(err)
		return
	}

	if !options.NoUser {
		key, err := CreateUser(options)

		if err != nil {
			fmt.Println("Error creating user")
			fmt.Println(err)
			return
		}

		fmt.Println("An access key has been created with just the permissions required to deploy / rollback this site")
		fmt.Println("It is strongly recommended you use this limited account to deploy this project in the future\n")
		fmt.Printf("ACCESS_KEY_ID=%s\n", key.Id)
		fmt.Printf("ACCESS_KEY_SECRET=%s\n\n", key.Secret)

		if terminal.IsTerminal(int(os.Stdin.Fd())) {
			fmt.Println(`You can either add these credentials to the deploy.yaml file,
or specify them as arguments to the stout deploy / stout rollback commands.
You MUST NOT add them to the deploy.yaml file if this project is public
(i.e. a public GitHub repo).

If you can't add them to the deploy.yaml file, you can specify them as
arguments on the command line.  If you use a build system like CircleCI, you
can add them as environment variables and pass those variables to the deploy
commands (see the README).

Your first deploy command might be:
	
	stout deploy --bucket ` + options.Bucket + ` --key ` + key.Id + ` --secret '` + key.Secret + `'
`)
		}

	}

	fmt.Println("You can begin deploying now, but it can take up to ten minutes for your site to begin to work")
	fmt.Println("Depending on the configuration of your site, you might need to set the 'root', 'dest' or 'files' options to get your deploys working as you wish.  See the README for details.")
	fmt.Println("It's also a good idea to look into the 'env' option, as in real-world situations it usually makes sense to have a development and/or staging site for each of your production sites.")
}

func createCmd() {
	options, _ := parseOptions()
	loadConfigFile(&options)
	addAWSConfig(&options)

	if options.Bucket == "" {
		panic("You must specify a bucket")
	}

	if options.AWSKey == "" || options.AWSSecret == "" {
		panic("You must specify your AWS credentials")
	}

	Create(options)
}


================================================
FILE: src/cli.go
================================================
package main

import (
	"flag"
	"fmt"
)

func printUsage() {
	fmt.Println(`Stout Static Deploy Tool
Supports three commands, create, deploy and rollback.

Example Usage:

To create a site which will be hosted at my.awesome.website:

stout create --bucket my.awesome.website --key AWS_KEY --secret AWS_SECRET

To deploy the current folder to the root of the my.awesome.website site:

stout deploy --bucket my.awesome.website --key AWS_KEY --secret AWS_SECRET

To rollback to a specific deploy:

stout rollback --bucket my.awesome.website --key AWS_KEY --secret AWS_SECRET c4a22bf94de1

See the README for more configuration information.
`)
}

func main() {
	flag.Parse()

	command := flag.Arg(0)

	switch command {
	case "help":
		printUsage()
	case "deploy":
		deployCmd()
	case "rollback":
		rollbackCmd()
	case "create":
		createCmd()
	default:
		fmt.Println("Command not understood")
		fmt.Println("")
		printUsage()
	}
}


================================================
FILE: src/deploy.go
================================================
package main

import (
	"bytes"
	"compress/gzip"
	"crypto/md5"
	"encoding/base64"
	"fmt"
	"io"
	"math/big"
	"mime"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"sync"
	"time"

	"github.com/cenk/backoff"
	"golang.org/x/net/html"

	"log"

	"github.com/wsxiaoys/terminal/color"
	"github.com/zackbloom/goamz/s3"
)

const (
	SCRIPT = iota
	STYLE
)

const UPLOAD_WORKERS = 20

var NO_GZIP = []string{
	"mp4",
	"webm",
	"ogg",
}

func hashFile(path string) []byte {
	hash := md5.New()
	io.WriteString(hash, path)
	io.WriteString(hash, "\n")

	// TODO: Encode type?

	ref := must(os.Open(path)).(*os.File)
	defer ref.Close()

	must(io.Copy(hash, ref))

	return hash.Sum(nil)
}

func hashBytes(data []byte) []byte {
	hash := md5.New()
	must(io.Copy(hash, bytes.NewReader(data)))
	return hash.Sum(nil)
}

func hashFiles(files []string) string {
	hash := new(big.Int)
	for _, file := range files {
		val := new(big.Int)
		val.SetBytes(hashFile(file))

		hash = hash.Xor(hash, val)
	}

	return fmt.Sprintf("%x", hash)
}

func getRef() string {
	gitPath := mustString(exec.LookPath("git"))

	cmd := exec.Command(gitPath, "rev-parse", "--verify", "HEAD")

	out := bytes.Buffer{}
	cmd.Stdout = &out
	panicIf(cmd.Run())

	return string(out.Bytes())
}

func guessContentType(file string) string {
	return mime.TypeByExtension(filepath.Ext(file))
}

func shouldCompress(file string) bool {
	ext := filepath.Ext(file)
	for _, e := range NO_GZIP {
		if "."+e == ext {
			return false
		}
	}

	return true
}

type UploadFileRequest struct {
	Bucket       *s3.Bucket
	Reader       io.Reader
	Path         string
	Dest         string
	IncludeHash  bool
	CacheSeconds int
}

func uploadFile(req UploadFileRequest) (remotePath string) {
	buffer := bytes.NewBuffer([]byte{})

	compress := shouldCompress(req.Path)

	if compress {
		writer := gzip.NewWriter(buffer)
		must(io.Copy(writer, req.Reader))
		writer.Close()
	} else {
		must(io.Copy(buffer, req.Reader))
	}

	data := buffer.Bytes()

	hash := hashBytes(data)
	hashPrefix := fmt.Sprintf("%x", hash)[:12]
	s3Opts := s3.Options{
		ContentMD5:   base64.StdEncoding.EncodeToString(hash),
		CacheControl: fmt.Sprintf("public, max-age=%d", req.CacheSeconds),
	}

	if compress {
		s3Opts.ContentEncoding = "gzip"
	}

	dest := req.Path
	if req.IncludeHash {
		dest = hashPrefix + "_" + dest
	}
	dest = filepath.Join(req.Dest, dest)

	log.Printf("Uploading to %s in %s (%s) [%d]\n", dest, req.Bucket.Name, hashPrefix, req.CacheSeconds)

	op := func() error {
		// We need to create a new reader each time, as we might be doing this more than once (if it fails)
		return req.Bucket.PutReader(dest, bytes.NewReader(data), int64(len(data)), guessContentType(dest)+"; charset=utf-8", s3.PublicRead, s3Opts)
	}

	back := backoff.NewExponentialBackOff()
	back.MaxElapsedTime = 30 * time.Second

	err := backoff.RetryNotify(op, back, func(err error, next time.Duration) {
		log.Println("Error uploading", err, "retrying in", next)
	})
	panicIf(err)

	return dest
}

type FileRef struct {
	LocalPath    string
	RemotePath   string
	UploadedPath string
}

type FileInst struct {
	File     *FileRef
	InstPath string
}

func writeFiles(options Options, includeHash bool, files chan *FileRef) {
	bucket := s3Session.Bucket(options.Bucket)

	for file := range files {
		handle := must(os.Open(file.LocalPath)).(*os.File)
		defer handle.Close()

		var ttl int
		ttl = FOREVER
		if !includeHash {
			ttl = LIMITED
		}

		remote := file.RemotePath
		if strings.HasPrefix(remote, "/") {
			remote = remote[1:]
		}
		partialPath, err := filepath.Rel(options.Dest, remote)
		if err != nil {
			panic(err)
		}

		(*file).UploadedPath = uploadFile(UploadFileRequest{
			Bucket:       bucket,
			Reader:       handle,
			Path:         partialPath,
			Dest:         options.Dest,
			IncludeHash:  includeHash,
			CacheSeconds: ttl,
		})
	}
}

func deployFiles(options Options, includeHash bool, files []*FileRef) {
	ch := make(chan *FileRef)

	wg := new(sync.WaitGroup)
	for i := 0; i < UPLOAD_WORKERS; i++ {
		wg.Add(1)
		go func() {
			writeFiles(options, includeHash, ch)
			wg.Done()
		}()
	}

	for _, file := range files {
		if !includeHash && strings.HasSuffix(file.RemotePath, ".html") {
			panic(fmt.Sprintf("Cowardly refusing to deploy an html file (%s) without versioning.", file.RemotePath))
		}

		ch <- file
	}

	close(ch)

	wg.Wait()
}

func addFiles(form uint8, parent *html.Node, files []string) {
	for _, file := range files {
		node := html.Node{
			Type: html.ElementNode,
		}
		switch form {
		case SCRIPT:
			node.Data = "script"
			node.Attr = []html.Attribute{
				html.Attribute{
					Key: "src",
					Val: file,
				},
			}

		case STYLE:
			node.Data = "link"
			node.Attr = []html.Attribute{
				html.Attribute{
					Key: "rel",
					Val: "stylesheet",
				},
				html.Attribute{
					Key: "href",
					Val: file,
				},
			}
		default:
			panic("Type not understood")
		}

		parent.AppendChild(&node)
	}
}

func isLocal(href string) bool {
	parsed := must(url.Parse(href)).(*url.URL)
	return parsed.Host == ""
}

func formatHref(path string) string {
	if !strings.HasPrefix(path, "/") {
		path = "/" + path
	}
	return path
}

func renderHTML(options Options, file HTMLFile) string {
	handle := must(os.Open(file.File.LocalPath)).(*os.File)
	defer handle.Close()

	doc := must(html.Parse(handle)).(*html.Node)

	var f func(*html.Node)
	f = func(n *html.Node) {
		for c := n.FirstChild; c != nil; c = c.NextSibling {
			f(c)
		}

		if n.Type == html.ElementNode {
			switch n.Data {
			case "script":
				for i, a := range n.Attr {
					if a.Key == "src" {
						for _, dep := range file.Deps {
							if dep.InstPath == a.Val {
								n.Attr[i].Val = formatHref(dep.File.UploadedPath)
								break
							}
						}
					}
				}
			case "link":
				stylesheet := false
				for _, a := range n.Attr {
					if a.Key == "rel" {
						stylesheet = a.Val == "stylesheet"
						break
					}
				}
				if !stylesheet {
					return
				}

				for i, a := range n.Attr {
					if a.Key == "href" {
						for _, dep := range file.Deps {
							if dep.InstPath == a.Val {
								n.Attr[i].Val = formatHref(dep.File.UploadedPath)
								break
							}
						}
					}
				}
			}
		}
	}
	f(doc)

	buf := bytes.NewBuffer([]byte{})
	panicIf(html.Render(buf, doc))

	return buf.String()
}

func parseHTML(options Options, path string) (files []string, base string) {
	files = make([]string, 0)

	handle := must(os.Open(path)).(*os.File)
	defer handle.Close()

	doc := must(html.Parse(handle)).(*html.Node)

	var f func(*html.Node)
	f = func(n *html.Node) {
		for c := n.FirstChild; c != nil; c = c.NextSibling {
			f(c)
		}

		if n.Type == html.ElementNode {
			switch n.Data {
			case "base":
				for _, a := range n.Attr {
					if a.Key == "href" {
						base = a.Val
					}
				}
			case "script":
				for _, a := range n.Attr {
					if a.Key == "src" {
						if isLocal(a.Val) {
							files = append(files, a.Val)
						}
					}
				}
			case "link":
				local := false
				stylesheet := false
				href := ""
				for _, a := range n.Attr {
					switch a.Key {
					case "href":
						local = isLocal(a.Val)
						href = a.Val
					case "rel":
						stylesheet = a.Val == "stylesheet"
					}
				}
				if local && stylesheet {
					files = append(files, href)
				}
			}
		}
	}
	f(doc)

	return
}

func deployHTML(options Options, id string, file HTMLFile) {
	data := renderHTML(options, file)

	internalPath, err := filepath.Rel(options.Root, file.File.LocalPath)
	if err != nil {
		panic(err)
	}

	permPath := joinPath(options.Dest, id, internalPath)
	curPath := joinPath(options.Dest, internalPath)

	bucket := s3Session.Bucket(options.Bucket)
	uploadFile(UploadFileRequest{
		Bucket:       bucket,
		Reader:       strings.NewReader(data),
		Path:         permPath,
		IncludeHash:  false,
		CacheSeconds: FOREVER,
	})

	log.Println("Copying", permPath, "to", curPath)
	copyFile(bucket, permPath, curPath, "text/html; charset=utf-8", LIMITED)
}

func expandFiles(root string, glob string) []string {
	out := make([]string, 0)
	cases := strings.Split(glob, ",")

	for _, pattern := range cases {
		if strings.HasPrefix(pattern, "-/") {
			pattern = pattern[2:]
		} else {
			pattern = joinPath(root, pattern)
		}

		list := must(filepath.Glob(pattern)).([]string)

		for _, file := range list {
			info := must(os.Stat(file)).(os.FileInfo)

			if info.IsDir() {
				filepath.Walk(file, func(path string, info os.FileInfo, err error) error {
					panicIf(err)

					if !info.IsDir() {
						out = append(out, path)
					}

					return nil
				})
			} else {
				out = append(out, file)
			}
		}
	}
	return out
}

func listFiles(options Options) []*FileRef {
	filePaths := expandFiles(options.Root, options.Files)

	files := make([]*FileRef, len(filePaths))
	for i, path := range filePaths {
		remotePath := joinPath(options.Dest, mustString(filepath.Rel(options.Root, path)))

		for strings.HasPrefix(remotePath, "../") {
			remotePath = remotePath[3:]
		}

		files[i] = &FileRef{
			LocalPath:  path,
			RemotePath: remotePath,
		}
	}

	return files
}

func ignoreFiles(full []*FileRef, rem []*FileRef) []*FileRef {
	out := make([]*FileRef, 0, len(full))

	for _, file := range full {
		ignore := false
		path := filepath.Clean(file.LocalPath)

		for _, remFile := range rem {
			if filepath.Clean(remFile.LocalPath) == path {
				ignore = true
				break
			}
		}

		if !ignore {
			out = append(out, file)
		}
	}

	return out
}

func extractFileList(options Options, pattern string) (files []string) {
	files = make([]string, 0)

	parts := strings.Split(pattern, ",")

	for _, part := range parts {
		matches, err := filepath.Glob(joinPath(options.Root, part))
		if err != nil {
			panic(err)
		}
		if matches == nil {
			panic(fmt.Sprintf("Pattern %s did not match any files", part))
		}

		files = append(files, matches...)
	}

	return files
}

func filesWithExtension(files []*FileRef, ext string) (outFiles []*FileRef) {
	outFiles = make([]*FileRef, 0)
	for _, file := range files {
		if filepath.Ext(file.LocalPath) == ext {
			outFiles = append(outFiles, file)
		}
	}

	return
}

type HTMLFile struct {
	File FileRef
	Deps []FileInst
	Base string
}

func (f HTMLFile) GetLocalPath() string {
	return f.File.LocalPath
}

func Deploy(options Options) {
	if s3Session == nil {
		s3Session = openS3(options.AWSKey, options.AWSSecret, options.AWSRegion, options.S3Host)
	}

	files := listFiles(options)

	htmlFileRefs := filesWithExtension(files, ".html")
	var htmlFiles []HTMLFile
	var id string

	if len(htmlFileRefs) == 0 {
		log.Println("No HTML files found")
	} else {
		inclFiles := make(map[string]*FileRef)
		htmlFiles = make([]HTMLFile, len(htmlFileRefs))
		for i, file := range htmlFileRefs {
			dir := filepath.Dir(file.LocalPath)

			rel, err := filepath.Rel(options.Root, dir)
			if err != nil {
				panic(err)
			}

			paths, base := parseHTML(options, file.LocalPath)

			if strings.HasPrefix(strings.ToLower(base), "http") || strings.HasPrefix(base, "//") {
				panic("Absolute base tags are not supported")
			}

			if strings.HasSuffix(base, "/") {
				base = base[:len(base)-1]
			}

			htmlFiles[i] = HTMLFile{
				File: *file,
				Deps: make([]FileInst, len(paths)),
				Base: base,
			}

			var dest string
			if strings.HasPrefix(base, "/") && strings.HasPrefix(base, "/"+options.Dest) {
				dest = base
			} else {
				dest = joinPath(options.Dest, base)
			}

			var root string
			if strings.HasPrefix(base, "/") && strings.HasSuffix(options.Root, base) {
				root = options.Root
			} else {
				root = joinPath(options.Root, base)
			}

			for j, path := range paths {
				var local, remote string
				if strings.HasPrefix(path, "/") {
					local = joinPath(options.Root, path)
					remote = joinPath(options.Dest, path)
				} else {
					if strings.HasPrefix(base, "/") {
						local = joinPath(root, path)
						remote = joinPath(dest, path)
					} else {
						local = joinPath(options.Root, rel, base, path)
						remote = joinPath(options.Dest, rel, base, path)
					}
				}

				for strings.HasPrefix(remote, "../") {
					remote = remote[3:]
				}

				ref, ok := inclFiles[local]
				if !ok {
					ref = &FileRef{
						LocalPath:  local,
						RemotePath: remote,

						// Filled in after the deploy:
						UploadedPath: "",
					}

					inclFiles[local] = ref
				}

				use := FileInst{
					File:     ref,
					InstPath: path,
				}

				htmlFiles[i].Deps[j] = use
			}
		}

		inclFileList := make([]*FileRef, len(inclFiles))
		i := 0
		for _, ref := range inclFiles {
			inclFileList[i] = ref
			i++
		}

		hashPaths := make([]string, 0)
		for _, item := range inclFileList {
			hashPaths = append(hashPaths, item.LocalPath)
		}
		for _, item := range htmlFiles {
			hashPaths = append(hashPaths, item.File.LocalPath)
		}

		hash := hashFiles(hashPaths)
		id = hash[:12]

		deployFiles(options, true, inclFileList)
	}

	deployFiles(options, false, ignoreFiles(files, htmlFileRefs))

	if len(htmlFileRefs) != 0 {
		// Ensure that the new files exist in s3
		// Time based on "Eventual Consistency: How soon is eventual?"
		time.Sleep(1500 * time.Millisecond)

		wg := sync.WaitGroup{}
		for _, file := range htmlFiles {
			wg.Add(1)

			go func(file HTMLFile) {
				defer wg.Done()
				deployHTML(options, id, file)
			}(file)
		}

		wg.Wait()
	}

	visId := id
	if id == "" {
		visId = "0 HTML Files"
	}

	color.Printf(`
+------------------------------------+
|         @{g}Deploy Successful!@{|}         |
|                                    |
|       Deploy ID: @{?}%s@{|}      |
+------------------------------------+
`, visId)

}

func deployCmd() {
	options, _ := parseOptions()
	loadConfigFile(&options)
	addAWSConfig(&options)

	if options.Bucket == "" {
		panic("You must specify a bucket")
	}

	if options.AWSKey == "" || options.AWSSecret == "" {
		panic("You must specify your AWS credentials")
	}

	Deploy(options)
}


================================================
FILE: src/rollback.go
================================================
package main

import (
	"fmt"
	"log"
	"path/filepath"
	"sync"

	"github.com/zackbloom/goamz/s3"
)

func Rollback(options Options, version string) {
	if s3Session == nil {
		s3Session = openS3(options.AWSKey, options.AWSSecret, options.AWSRegion, options.S3Host)
	}

	bucket := s3Session.Bucket(options.Bucket)

	// List files with the correct prefix in bucket
	// Remove their prefix with a copy.

	prefix := filepath.Join(options.Dest, version) + "/"

	list, err := bucket.List(prefix, "", "", 1000)
	panicIf(err)

	if list.IsTruncated {
		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))
	}
	if len(list.Contents) == 0 {
		log.Printf("A deploy with the provided id (%s) was not found in the specified bucket", version)
		return
	}

	wg := sync.WaitGroup{}

	count := 0
	for _, file := range list.Contents {
		wg.Add(1)
		go func(file s3.Key) {
			defer wg.Done()

			path := file.Key
			if filepath.Ext(path) != ".html" {
				log.Printf("Skipping non-html file %s", path)
				return
			}

			newPath := filepath.Join(options.Dest, path[len(prefix):])

			log.Printf("Aliasing %s to %s", path, newPath)

			copyFile(bucket, path, newPath, "text/html", LIMITED)

			count++
		}(file)
	}

	wg.Wait()

	log.Printf("Reverted %d HTML files to version %s", count, version)
}

func rollbackCmd() {
	options, set := parseOptions()
	version := set.Arg(0)

	loadConfigFile(&options)
	addAWSConfig(&options)

	if options.Bucket == "" {
		panic("You must specify a bucket")
	}
	if options.AWSKey == "" || options.AWSSecret == "" {
		panic("You must specify your AWS credentials")
	}
	if version == "" {
		panic("You must specify a version to rollback to")
	}

	Rollback(options, version)
}


================================================
FILE: src/utils.go
================================================
package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/imdario/mergo"
	homedir "github.com/mitchellh/go-homedir"
	ini "github.com/sspencer/go-ini"
	"github.com/zackbloom/goamz/aws"
	"github.com/zackbloom/goamz/cloudfront"
	"github.com/zackbloom/goamz/iam"
	"github.com/zackbloom/goamz/route53"
	"github.com/zackbloom/goamz/s3"
	"gopkg.in/yaml.v1"
)

const (
	LIMITED = 60
	FOREVER = 31556926
)

var s3Session *s3.S3
var iamSession *iam.IAM
var r53Session *route53.Route53
var cfSession *cloudfront.CloudFront

func getRegion(region string, s3Host string) aws.Region {
	regionS, ok := aws.Regions[region]
	if !ok {
		panic("Region not found")
	}

	log.Println("HOST", s3Host)
	if s3Host != "" {
		regionS.S3Endpoint = "https://" + s3Host
		regionS.S3BucketEndpoint = "https://${bucket}." + s3Host
	}
	return regionS
}

func openS3(key, secret, region, s3Host string) *s3.S3 {
	regionS := getRegion(region, s3Host)

	auth := aws.Auth{
		AccessKey: key,
		SecretKey: secret,
	}
	return s3.New(auth, regionS)
}

func openIAM(key, secret, region string) *iam.IAM {
	regionS := getRegion(region, "")

	auth := aws.Auth{
		AccessKey: key,
		SecretKey: secret,
	}
	return iam.New(auth, regionS)
}

func openCloudFront(key, secret string) *cloudfront.CloudFront {
	auth := aws.Auth{
		AccessKey: key,
		SecretKey: secret,
	}
	return cloudfront.NewCloudFront(auth)
}

func openRoute53(key, secret string) *route53.Route53 {
	auth := aws.Auth{
		AccessKey: key,
		SecretKey: secret,
	}

	r53, _ := route53.NewRoute53(auth)
	return r53
}

func panicIf(err error) {
	if err != nil {
		panic(err)
	}
}
func must(val interface{}, err error) interface{} {
	if err != nil {
		panic(err)
	}

	return val
}
func mustString(val string, err error) string {
	panicIf(err)
	return val
}
func mustInt(val int, err error) int {
	panicIf(err)
	return val
}

type Options struct {
	Files      string `yaml:"files"`
	Root       string `yaml:"root"`
	Dest       string `yaml:"dest"`
	ConfigFile string `yaml:"-"`
	Env        string `yaml:"-"`
	Bucket     string `yaml:"bucket"`
	AWSKey     string `yaml:"key"`
	AWSSecret  string `yaml:"secret"`
	AWSRegion  string `yaml:"region"`
	S3Host     string `yaml:"s3Host"`
	NoUser     bool   `yaml:"-"`
}

func parseOptions() (o Options, set *flag.FlagSet) {
	set = flag.NewFlagSet(os.Args[1], flag.ExitOnError)
	//TODO: Set set.Usage

	set.StringVar(&o.Files, "files", "*", "Comma-seperated glob patterns of files to deploy (within root)")
	set.StringVar(&o.Root, "root", "./", "The local directory to deploy")
	set.StringVar(&o.Dest, "dest", "./", "The destination directory to write files to in the S3 bucket")
	set.StringVar(&o.ConfigFile, "config", "", "A yaml file to read configuration from")
	set.StringVar(&o.Env, "env", "", "The env to read from the config file")
	set.StringVar(&o.Bucket, "bucket", "", "The bucket to deploy to")
	set.StringVar(&o.AWSKey, "key", "", "The AWS key to use")
	set.StringVar(&o.AWSSecret, "secret", "", "The AWS secret of the provided key")
	set.StringVar(&o.AWSRegion, "region", "us-east-1", "The AWS region the S3 bucket is in")
	set.StringVar(&o.S3Host, "s3-host", "s3.amazonaws.com", "The hostname of an S3 implementation, overrides region")
	set.BoolVar(&o.NoUser, "no-user", false, "When creating, should we make a user account?")

	set.Parse(os.Args[2:])

	return
}

type ConfigFile map[string]Options

func loadConfigFile(o *Options) {
	isDefault := false
	configPath := o.ConfigFile
	if o.ConfigFile == "" {
		isDefault = true
		configPath = "./deploy.yaml"
	}

	data, err := ioutil.ReadFile(configPath)
	if err != nil {
		if os.IsNotExist(err) && isDefault {
			return
		}

		panic(err)
	}

	var file ConfigFile
	err = yaml.Unmarshal(data, &file)
	panicIf(err)

	var envCfg Options
	if o.Env != "" {
		var ok bool
		envCfg, ok = file[o.Env]
		if !ok {
			panic("Config for specified env not found")
		}
	}

	defCfg, _ := file["default"]

	panicIf(mergo.MergeWithOverwrite(o, defCfg))
	panicIf(mergo.MergeWithOverwrite(o, envCfg))
}

func addAWSConfig(o *Options) {
	if o.AWSKey == "" && o.AWSSecret == "" {
		o.AWSKey, o.AWSSecret = loadAWSConfig()
	}
}

type AWSConfig struct {
	Default struct {
		AccessKey string `ini:"aws_access_key_id"`
		SecretKey string `ini:"aws_secret_access_key"`
	} `ini:"[default]"`
}

func loadAWSConfig() (access string, secret string) {
	cfg := AWSConfig{}

	for _, file := range []string{"~/.aws/config", "~/.aws/credentials"} {
		path, err := homedir.Expand(file)
		if err != nil {
			continue
		}

		content, err := ioutil.ReadFile(path)
		if err != nil {
			continue
		}

		ini.Unmarshal(content, &cfg)

		if cfg.Default.AccessKey != "" {
			break
		}
	}

	return cfg.Default.AccessKey, cfg.Default.SecretKey
}

func copyFile(bucket *s3.Bucket, from string, to string, contentType string, maxAge int) {
	copyOpts := s3.CopyOptions{
		MetadataDirective: "REPLACE",
		ContentType:       contentType,
		Options: s3.Options{
			CacheControl:    fmt.Sprintf("public, max-age=%d", maxAge),
			ContentEncoding: "gzip",
		},
	}

	_, err := bucket.PutCopy(to, s3.PublicRead, copyOpts, joinPath(bucket.Name, from))
	if err != nil {
		panic(err)
	}
}

var pathRe = regexp.MustCompile("/{2,}")

func joinPath(parts ...string) string {
	// Like filepath.Join, but always uses '/'
	out := filepath.Join(parts...)

	if os.PathSeparator != '/' {
		out = strings.Replace(out, string(os.PathSeparator), "/", -1)
	}

	return out
}


================================================
FILE: utils/build.sh
================================================
GOOS=linux GOARCH=amd64 go build -o stout-linux src/* 
GOOS=darwin GOARCH=amd64 go build -o stout-osx src/* 
GOOS=windows GOARCH=amd64 go build -o stout-windows.exe src/* 


================================================
FILE: utils/create_site.sh
================================================
#set -e

export HOST=$1
export DEPLOY_USER=${HOST}_deploy

aws s3 mb s3://$HOST --region us-east-1

aws s3 website s3://$HOST --index-document index.html --error-document error.html

aws s3api put-bucket-policy --bucket $HOST --policy "{
  \"Version\": \"2008-10-17\",
  \"Statement\": [
    {
      \"Sid\": \"PublicReadForGetBucketObjects\",
      \"Effect\": \"Allow\",
      \"Principal\": {
        \"AWS\": \"*\"
      },
      \"Action\": \"s3:GetObject\",
      \"Resource\": \"arn:aws:s3:::$HOST/*\"
    }
  ]
}"

export CALLER=`date +"%T"`

aws cloudfront create-distribution --distribution-config "
{
    \"CallerReference\": \"$CALLER\",
    \"Comment\": null,
    \"CacheBehaviors\": {
        \"Quantity\": 0
    },
    \"Logging\": {
        \"Bucket\": null,
        \"Prefix\": null,
        \"Enabled\": false,
        \"IncludeCookies\": false
    },
    \"Origins\": {
        \"Items\": [
            {
                \"S3OriginConfig\": {
                    \"OriginAccessIdentity\": null
                },
                \"Id\": \"S3-$HOST\",
                \"DomainName\": \"$HOST.s3.amazonaws.com\"
            }
        ],
        \"Quantity\": 1
    },
    \"DefaultRootObject\": \"index.html\",
    \"PriceClass\": \"PriceClass_All\",
    \"Enabled\": true,
    \"DefaultCacheBehavior\": {
        \"TrustedSigners\": {
            \"Enabled\": false,
            \"Quantity\": 0
        },
        \"TargetOriginId\": \"S3-$HOST\",
        \"ViewerProtocolPolicy\": \"allow-all\",
        \"ForwardedValues\": {
            \"Cookies\": {
                \"Forward\": \"none\"
            },
            \"QueryString\": false
        },
        \"AllowedMethods\": {
            \"Items\": [
                \"GET\",
                \"HEAD\"
            ],
            \"Quantity\": 2
        },
        \"MinTTL\": 0
    },
    \"ViewerCertificate\": {
        \"CloudFrontDefaultCertificate\": true
    },
    \"CustomErrorResponses\": {
        \"Quantity\": 0
    },
    \"Restrictions\": {
        \"GeoRestriction\": {
            \"RestrictionType\": \"none\",
            \"Quantity\": 0
        }
    },
    \"Aliases\": {
        \"Items\": [
            \"$HOST\"
        ],
        \"Quantity\": 1
    }
}"

aws iam create-user --user-name $DEPLOY_USER
aws iam put-user-policy --user-name $DEPLOY_USER --policy-name $DEPLOY_USER --policy-document "{
  \"Version\": \"2012-10-17\",
  \"Statement\": [
    {
      \"Effect\": \"Allow\",
      \"Action\": [
        \"s3:DeleteObject\",
        \"s3:ListBucket\",
        \"s3:PutObject\",
        \"s3:PutObjectAcl\",
        \"s3:GetObject\"
      ],
      \"Resource\": [
        \"arn:aws:s3:::$HOST\", \"arn:aws:s3:::$HOST/*\"
      ]
    }
  ]
}"

aws iam create-access-key --user-name $DEPLOY_USER | cat

echo "Select a SSL Cert in CloudFront if applicable"

echo "Site set up. You must now manually add the cloudfront distribution to your DNS configuration."


================================================
FILE: utils/release.sh
================================================
set -e

# Install jq with brew install jq

RELEASE=$1

git tag $RELEASE
git push origin master --tags

UPLOAD_URL=$(curl -X POST "https://api.github.com/repos/EagerIO/Stout/releases" \
  -H "Accept: application/vnd.github.v3+json" \
  -H "Authorization: token $GITHUB_AUTH" \
  -H "Content-Type: application/json" \
  -d "
{
  \"tag_name\": \"$RELEASE\"
}" | jq -r '.upload_url' | cut -d { -f 1)

mkdir -p debian

echo "
Package: stout
Source: stout
Version: $RELEASE
Architecture: all
Maintainer: Zack Bloom <zack@eager.io>
Description: The reliable static website deploy tool
" > `dirname $0`/../control

`dirname $0`/xc.sh

upload () {
  local archive=$1
  local filename=$(basename "$archive")
  local extension="${filename##*.}"

  if [ "$extension" == "md" ]; then
    return
  fi

  curl -X POST "$UPLOAD_URL?name=$filename" \
    -H "Content-Type: application/octet-stream" \
    -H "Authorization: token $GITHUB_AUTH" \
    --data-binary @$archive
}

for f in builds/snapshot/*; do upload "$f" & done

wait


================================================
FILE: utils/xc.sh
================================================
goxc -tasks-=downloads-page -d=./builds


================================================
FILE: vendor/github.com/cenk/backoff/.gitignore
================================================
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so

# Folders
_obj
_test

# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out

*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*

_testmain.go

*.exe


================================================
FILE: vendor/github.com/cenk/backoff/.travis.yml
================================================
language: go
go:
  - 1.3.3
  - tip
before_install:
  - go get github.com/mattn/goveralls
  - go get golang.org/x/tools/cmd/cover
script:
  - $HOME/gopath/bin/goveralls -service=travis-ci


================================================
FILE: vendor/github.com/cenk/backoff/LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2014 Cenk Altı

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


================================================
FILE: vendor/github.com/cenk/backoff/README.md
================================================
# Exponential Backoff [![GoDoc][godoc image]][godoc] [![Build Status][travis image]][travis] [![Coverage Status][coveralls image]][coveralls]

This is a Go port of the exponential backoff algorithm from [Google's HTTP Client Library for Java][google-http-java-client].

[Exponential backoff][exponential backoff wiki]
is an algorithm that uses feedback to multiplicatively decrease the rate of some process,
in order to gradually find an acceptable rate.
The retries exponentially increase and stop increasing when a certain threshold is met.

## How To

We define two functions, `Retry()` and `RetryNotify()`.
They receive an `Operation` to execute, a `BackOff` algorithm,
and an optional `Notify` error handler.

The operation will be executed, and will be retried on failure with delay
as given by the backoff algorithm. The backoff algorithm can also decide when to stop
retrying.
In addition, the notify error handler will be called after each failed attempt,
except for the last time, whose error should be handled by the caller.

```go
// An Operation is executing by Retry() or RetryNotify().
// The operation will be retried using a backoff policy if it returns an error.
type Operation func() error

// Notify is a notify-on-error function. It receives an operation error and
// backoff delay if the operation failed (with an error).
//
// NOTE that if the backoff policy stated to stop retrying,
// the notify function isn't called.
type Notify func(error, time.Duration)

func Retry(Operation, BackOff) error
func RetryNotify(Operation, BackOff, Notify)
```

## Examples

### Retry

Simple retry helper that uses the default exponential backoff algorithm:

```go
operation := func() error {
    // An operation that might fail.
    return nil // or return errors.New("some error")
}

err := Retry(operation, NewExponentialBackOff())
if err != nil {
    // Handle error.
    return err
}

// Operation is successful.
return nil
```

### Ticker

Ticker is for using backoff algorithms with channels.

```go
operation := func() error {
    // An operation that might fail
    return nil // or return errors.New("some error")
}

b := NewExponentialBackOff()
ticker := NewTicker(b)

var err error

// Ticks will continue to arrive when the previous operation is still running,
// so operations that take a while to fail could run in quick succession.
for range ticker.C {
    if err = operation(); err != nil {
        log.Println(err, "will retry...")
        continue
    }

    ticker.Stop()
    break
}

if err != nil {
    // Operation has failed.
    return err
}

// Operation is successful.
return nil
```

## Getting Started

```bash
# install
$ go get github.com/cenk/backoff

# test
$ cd $GOPATH/src/github.com/cenk/backoff
$ go get -t ./...
$ go test -v -cover
```

[godoc]: https://godoc.org/github.com/cenk/backoff
[godoc image]: https://godoc.org/github.com/cenk/backoff?status.png
[travis]: https://travis-ci.org/cenk/backoff
[travis image]: https://travis-ci.org/cenk/backoff.png?branch=master
[coveralls]: https://coveralls.io/github/cenk/backoff?branch=master
[coveralls image]: https://coveralls.io/repos/github/cenk/backoff/badge.svg?branch=master

[google-http-java-client]: https://github.com/google/google-http-java-client
[exponential backoff wiki]: http://en.wikipedia.org/wiki/Exponential_backoff

[advanced example]: https://godoc.org/github.com/cenk/backoff#example_


================================================
FILE: vendor/github.com/cenk/backoff/backoff.go
================================================
// Package backoff implements backoff algorithms for retrying operations.
//
// Also has a Retry() helper for retrying operations that may fail.
package backoff

import "time"

// BackOff is a backoff policy for retrying an operation.
type BackOff interface {
	// NextBackOff returns the duration to wait before retrying the operation,
	// or backoff.Stop to indicate that no more retries should be made.
	//
	// Example usage:
	//
	// 	duration := backoff.NextBackOff();
	// 	if (duration == backoff.Stop) {
	// 		// Do not retry operation.
	// 	} else {
	// 		// Sleep for duration and retry operation.
	// 	}
	//
	NextBackOff() time.Duration

	// Reset to initial state.
	Reset()
}

// Indicates that no more retries should be made for use in NextBackOff().
const Stop time.Duration = -1

// ZeroBackOff is a fixed backoff policy whose backoff time is always zero,
// meaning that the operation is retried immediately without waiting, indefinitely.
type ZeroBackOff struct{}

func (b *ZeroBackOff) Reset() {}

func (b *ZeroBackOff) NextBackOff() time.Duration { return 0 }

// StopBackOff is a fixed backoff policy that always returns backoff.Stop for
// NextBackOff(), meaning that the operation should never be retried.
type StopBackOff struct{}

func (b *StopBackOff) Reset() {}

func (b *StopBackOff) NextBackOff() time.Duration { return Stop }

// ConstantBackOff is a backoff policy that always returns the same backoff delay.
// This is in contrast to an exponential backoff policy,
// which returns a delay that grows longer as you call NextBackOff() over and over again.
type ConstantBackOff struct {
	Interval time.Duration
}

func (b *ConstantBackOff) Reset()                     {}
func (b *ConstantBackOff) NextBackOff() time.Duration { return b.Interval }

func NewConstantBackOff(d time.Duration) *ConstantBackOff {
	return &ConstantBackOff{Interval: d}
}


================================================
FILE: vendor/github.com/cenk/backoff/exponential.go
================================================
package backoff

import (
	"math/rand"
	"time"
)

/*
ExponentialBackOff is a backoff implementation that increases the backoff
period for each retry attempt using a randomization function that grows exponentially.

NextBackOff() is calculated using the following formula:

 randomized interval =
     RetryInterval * (random value in range [1 - RandomizationFactor, 1 + RandomizationFactor])

In other words NextBackOff() will range between the randomization factor
percentage below and above the retry interval.

For example, given the following parameters:

 RetryInterval = 2
 RandomizationFactor = 0.5
 Multiplier = 2

the actual backoff period used in the next retry attempt will range between 1 and 3 seconds,
multiplied by the exponential, that is, between 2 and 6 seconds.

Note: MaxInterval caps the RetryInterval and not the randomized interval.

If the time elapsed since an ExponentialBackOff instance is created goes past the
MaxElapsedTime, then the method NextBackOff() starts returning backoff.Stop.

The elapsed time can be reset by calling Reset().

Example: Given the following default arguments, for 10 tries the sequence will be,
and assuming we go over the MaxElapsedTime on the 10th try:

 Request #  RetryInterval (seconds)  Randomized Interval (seconds)

  1          0.5                     [0.25,   0.75]
  2          0.75                    [0.375,  1.125]
  3          1.125                   [0.562,  1.687]
  4          1.687                   [0.8435, 2.53]
  5          2.53                    [1.265,  3.795]
  6          3.795                   [1.897,  5.692]
  7          5.692                   [2.846,  8.538]
  8          8.538                   [4.269, 12.807]
  9         12.807                   [6.403, 19.210]
 10         19.210                   backoff.Stop

Note: Implementation is not thread-safe.
*/
type ExponentialBackOff struct {
	InitialInterval     time.Duration
	RandomizationFactor float64
	Multiplier          float64
	MaxInterval         time.Duration
	// After MaxElapsedTime the ExponentialBackOff stops.
	// It never stops if MaxElapsedTime == 0.
	MaxElapsedTime time.Duration
	Clock          Clock

	currentInterval time.Duration
	startTime       time.Time
}

// Clock is an interface that returns current time for BackOff.
type Clock interface {
	Now() time.Time
}

// Default values for ExponentialBackOff.
const (
	DefaultInitialInterval     = 500 * time.Millisecond
	DefaultRandomizationFactor = 0.5
	DefaultMultiplier          = 1.5
	DefaultMaxInterval         = 60 * time.Second
	DefaultMaxElapsedTime      = 15 * time.Minute
)

// NewExponentialBackOff creates an instance of ExponentialBackOff using default values.
func NewExponentialBackOff() *ExponentialBackOff {
	b := &ExponentialBackOff{
		InitialInterval:     DefaultInitialInterval,
		RandomizationFactor: DefaultRandomizationFactor,
		Multiplier:          DefaultMultiplier,
		MaxInterval:         DefaultMaxInterval,
		MaxElapsedTime:      DefaultMaxElapsedTime,
		Clock:               SystemClock,
	}
	if b.RandomizationFactor < 0 {
		b.RandomizationFactor = 0
	} else if b.RandomizationFactor > 1 {
		b.RandomizationFactor = 1
	}
	b.Reset()
	return b
}

type systemClock struct{}

func (t systemClock) Now() time.Time {
	return time.Now()
}

// SystemClock implements Clock interface that uses time.Now().
var SystemClock = systemClock{}

// Reset the interval back to the initial retry interval and restarts the timer.
func (b *ExponentialBackOff) Reset() {
	b.currentInterval = b.InitialInterval
	b.startTime = b.Clock.Now()
}

// NextBackOff calculates the next backoff interval using the formula:
// 	Randomized interval = RetryInterval +/- (RandomizationFactor * RetryInterval)
func (b *ExponentialBackOff) NextBackOff() time.Duration {
	// Make sure we have not gone over the maximum elapsed time.
	if b.MaxElapsedTime != 0 && b.GetElapsedTime() > b.MaxElapsedTime {
		return Stop
	}
	defer b.incrementCurrentInterval()
	return getRandomValueFromInterval(b.RandomizationFactor, rand.Float64(), b.currentInterval)
}

// GetElapsedTime returns the elapsed time since an ExponentialBackOff instance
// is created and is reset when Reset() is called.
//
// The elapsed time is computed using time.Now().UnixNano().
func (b *ExponentialBackOff) GetElapsedTime() time.Duration {
	return b.Clock.Now().Sub(b.startTime)
}

// Increments the current interval by multiplying it with the multiplier.
func (b *ExponentialBackOff) incrementCurrentInterval() {
	// Check for overflow, if overflow is detected set the current interval to the max interval.
	if float64(b.currentInterval) >= float64(b.MaxInterval)/b.Multiplier {
		b.currentInterval = b.MaxInterval
	} else {
		b.currentInterval = time.Duration(float64(b.currentInterval) * b.Multiplier)
	}
}

// Returns a random value from the following interval:
// 	[randomizationFactor * currentInterval, randomizationFactor * currentInterval].
func getRandomValueFromInterval(randomizationFactor, random float64, currentInterval time.Duration) time.Duration {
	var delta = randomizationFactor * float64(currentInterval)
	var minInterval = float64(currentInterval) - delta
	var maxInterval = float64(currentInterval) + delta

	// Get a random value from the range [minInterval, maxInterval].
	// The formula used below has a +1 because if the minInterval is 1 and the maxInterval is 3 then
	// we want a 33% chance for selecting either 1, 2 or 3.
	return time.Duration(minInterval + (random * (maxInterval - minInterval + 1)))
}


================================================
FILE: vendor/github.com/cenk/backoff/retry.go
================================================
package backoff

import "time"

// An Operation is executing by Retry() or RetryNotify().
// The operation will be retried using a backoff policy if it returns an error.
type Operation func() error

// Notify is a notify-on-error function. It receives an operation error and
// backoff delay if the operation failed (with an error).
//
// NOTE that if the backoff policy stated to stop retrying,
// the notify function isn't called.
type Notify func(error, time.Duration)

// Retry the operation o until it does not return error or BackOff stops.
// o is guaranteed to be run at least once.
// It is the caller's responsibility to reset b after Retry returns.
//
// Retry sleeps the goroutine for the duration returned by BackOff after a
// failed operation returns.
func Retry(o Operation, b BackOff) error { return RetryNotify(o, b, nil) }

// RetryNotify calls notify function with the error and wait duration
// for each failed attempt before sleep.
func RetryNotify(operation Operation, b BackOff, notify Notify) error {
	var err error
	var next time.Duration

	b.Reset()
	for {
		if err = operation(); err == nil {
			return nil
		}

		if next = b.NextBackOff(); next == Stop {
			return err
		}

		if notify != nil {
			notify(err, next)
		}

		time.Sleep(next)
	}
}


================================================
FILE: vendor/github.com/cenk/backoff/ticker.go
================================================
package backoff

import (
	"runtime"
	"sync"
	"time"
)

// Ticker holds a channel that delivers `ticks' of a clock at times reported by a BackOff.
//
// Ticks will continue to arrive when the previous operation is still running,
// so operations that take a while to fail could run in quick succession.
type Ticker struct {
	C        <-chan time.Time
	c        chan time.Time
	b        BackOff
	stop     chan struct{}
	stopOnce sync.Once
}

// NewTicker returns a new Ticker containing a channel that will send the time at times
// specified by the BackOff argument. Ticker is guaranteed to tick at least once.
// The channel is closed when Stop method is called or BackOff stops.
func NewTicker(b BackOff) *Ticker {
	c := make(chan time.Time)
	t := &Ticker{
		C:    c,
		c:    c,
		b:    b,
		stop: make(chan struct{}),
	}
	go t.run()
	runtime.SetFinalizer(t, (*Ticker).Stop)
	return t
}

// Stop turns off a ticker. After Stop, no more ticks will be sent.
func (t *Ticker) Stop() {
	t.stopOnce.Do(func() { close(t.stop) })
}

func (t *Ticker) run() {
	c := t.c
	defer close(c)
	t.b.Reset()

	// Ticker is guaranteed to tick at least once.
	afterC := t.send(time.Now())

	for {
		if afterC == nil {
			return
		}

		select {
		case tick := <-afterC:
			afterC = t.send(tick)
		case <-t.stop:
			t.c = nil // Prevent future ticks from being sent to the channel.
			return
		}
	}
}

func (t *Ticker) send(tick time.Time) <-chan time.Time {
	select {
	case t.c <- tick:
	case <-t.stop:
		return nil
	}

	next := t.b.NextBackOff()
	if next == Stop {
		t.Stop()
		return nil
	}

	return time.After(next)
}


================================================
FILE: vendor/github.com/imdario/mergo/.travis.yml
================================================
language: go
install: go get -t


================================================
FILE: vendor/github.com/imdario/mergo/LICENSE
================================================
Copyright (c) 2013 Dario Castañé. All rights reserved.
Copyright (c) 2012 The Go Authors. All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

   * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
   * Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


================================================
FILE: vendor/github.com/imdario/mergo/README.md
================================================
# Mergo

A helper to merge structs and maps in Golang. Useful for configuration default values, avoiding messy if-statements.

Also a lovely [comune](http://en.wikipedia.org/wiki/Mergo) (municipality) in the Province of Ancona in the Italian region Marche.

![Mergo dall'alto](http://www.comune.mergo.an.it/Siti/Mergo/Immagini/Foto/mergo_dall_alto.jpg)

## Status

It is ready for production use. It works fine after extensive use in the wild.

[![Build Status][1]][2]
[![GoDoc][3]][4]
[![GoCard][5]][6]

[1]: https://travis-ci.org/imdario/mergo.png
[2]: https://travis-ci.org/imdario/mergo
[3]: https://godoc.org/github.com/imdario/mergo?status.svg
[4]: https://godoc.org/github.com/imdario/mergo
[5]: https://goreportcard.com/badge/imdario/mergo
[6]: https://goreportcard.com/report/github.com/imdario/mergo

### Important note

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.

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).

### Mergo in the wild

- [docker/docker](https://github.com/docker/docker/)
- [kubernetes/kubernetes](https://github.com/kubernetes/kubernetes)
- [imdario/zas](https://github.com/imdario/zas)
- [soniah/dnsmadeeasy](https://github.com/soniah/dnsmadeeasy)
- [EagerIO/Stout](https://github.com/EagerIO/Stout)
- [lynndylanhurley/defsynth-api](https://github.com/lynndylanhurley/defsynth-api)
- [russross/canvasassignments](https://github.com/russross/canvasassignments)
- [rdegges/cryptly-api](https://github.com/rdegges/cryptly-api)
- [casualjim/exeggutor](https://github.com/casualjim/exeggutor)
- [divshot/gitling](https://github.com/divshot/gitling)
- [RWJMurphy/gorl](https://github.com/RWJMurphy/gorl)
- [andrerocker/deploy42](https://github.com/andrerocker/deploy42)
- [elwinar/rambler](https://github.com/elwinar/rambler)
- [tmaiaroto/gopartman](https://github.com/tmaiaroto/gopartman)
- [jfbus/impressionist](https://github.com/jfbus/impressionist)
- [Jmeyering/zealot](https://github.com/Jmeyering/zealot)
- [godep-migrator/rigger-host](https://github.com/godep-migrator/rigger-host)
- [Dronevery/MultiwaySwitch-Go](https://github.com/Dronevery/MultiwaySwitch-Go)
- [thoas/picfit](https://github.com/thoas/picfit)
- [mantasmatelis/whooplist-server](https://github.com/mantasmatelis/whooplist-server)
- [jnuthong/item_search](https://github.com/jnuthong/item_search)
- [Iris Web Framework](https://github.com/kataras/iris)

## Installation

    go get github.com/imdario/mergo

    // use in your .go code
    import (
        "github.com/imdario/mergo"
    )

## Usage

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).

    if err := mergo.Merge(&dst, src); err != nil {
        // ...
    }

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.

    if err := mergo.Map(&dst, srcMap); err != nil {
        // ...
    }

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.

More information and examples in [godoc documentation](http://godoc.org/github.com/imdario/mergo).

### Nice example

```go
package main

import (
	"fmt"
	"github.com/imdario/mergo"
)

type Foo struct {
	A string
	B int64
}

func main() {
	src := Foo{
		A: "one",
	}

	dest := Foo{
		A: "two",
		B: 2,
	}

	mergo.Merge(&dest, src)

	fmt.Println(dest)
	// Will print
	// {two 2}
}
```

Note: if test are failing due missing package, please execute:

    go get gopkg.in/yaml.v1

## Contact me

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)

## About

Written by [Dario Castañé](http://dario.im).

## License

[BSD 3-Clause](http://opensource.org/licenses/BSD-3-Clause) license, as [Go language](http://golang.org/LICENSE).


================================================
FILE: vendor/github.com/imdario/mergo/doc.go
================================================
// Copyright 2013 Dario Castañé. All rights reserved.
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
Package mergo merges same-type structs and maps by setting default values in zero-value fields.

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).

Usage

From my own work-in-progress project:

	type networkConfig struct {
		Protocol string
		Address string
		ServerType string `json: "server_type"`
		Port uint16
	}

	type FssnConfig struct {
		Network networkConfig
	}

	var fssnDefault = FssnConfig {
		networkConfig {
			"tcp",
			"127.0.0.1",
			"http",
			31560,
		},
	}

	// Inside a function [...]

	if err := mergo.Merge(&config, fssnDefault); err != nil {
		log.Fatal(err)
	}

	// More code [...]

*/
package mergo


================================================
FILE: vendor/github.com/imdario/mergo/map.go
================================================
// Copyright 2014 Dario Castañé. All rights reserved.
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Based on src/pkg/reflect/deepequal.go from official
// golang's stdlib.

package mergo

import (
	"fmt"
	"reflect"
	"unicode"
	"unicode/utf8"
)

func changeInitialCase(s string, mapper func(rune) rune) string {
	if s == "" {
		return s
	}
	r, n := utf8.DecodeRuneInString(s)
	return string(mapper(r)) + s[n:]
}

func isExported(field reflect.StructField) bool {
	r, _ := utf8.DecodeRuneInString(field.Name)
	return r >= 'A' && r <= 'Z'
}

// Traverses recursively both values, assigning src's fields values to dst.
// The map argument tracks comparisons that have already been seen, which allows
// short circuiting on recursive types.
func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, overwrite bool) (err error) {
	if dst.CanAddr() {
		addr := dst.UnsafeAddr()
		h := 17 * addr
		seen := visited[h]
		typ := dst.Type()
		for p := seen; p != nil; p = p.next {
			if p.ptr == addr && p.typ == typ {
				return nil
			}
		}
		// Remember, remember...
		visited[h] = &visit{addr, typ, seen}
	}
	zeroValue := reflect.Value{}
	switch dst.Kind() {
	case reflect.Map:
		dstMap := dst.Interface().(map[string]interface{})
		for i, n := 0, src.NumField(); i < n; i++ {
			srcType := src.Type()
			field := srcType.Field(i)
			if !isExported(field) {
				continue
			}
			fieldName := field.Name
			fieldName = changeInitialCase(fieldName, unicode.ToLower)
			if v, ok := dstMap[fieldName]; !ok || (isEmptyValue(reflect.ValueOf(v)) || overwrite) {
				dstMap[fieldName] = src.Field(i).Interface()
			}
		}
	case reflect.Struct:
		srcMap := src.Interface().(map[string]interface{})
		for key := range srcMap {
			srcValue := srcMap[key]
			fieldName := changeInitialCase(key, unicode.ToUpper)
			dstElement := dst.FieldByName(fieldName)
			if dstElement == zeroValue {
				// We discard it because the field doesn't exist.
				continue
			}
			srcElement := reflect.ValueOf(srcValue)
			dstKind := dstElement.Kind()
			srcKind := srcElement.Kind()
			if srcKind == reflect.Ptr && dstKind != reflect.Ptr {
				srcElement = srcElement.Elem()
				srcKind = reflect.TypeOf(srcElement.Interface()).Kind()
			} else if dstKind == reflect.Ptr {
				// Can this work? I guess it can't.
				if srcKind != reflect.Ptr && srcElement.CanAddr() {
					srcPtr := srcElement.Addr()
					srcElement = reflect.ValueOf(srcPtr)
					srcKind = reflect.Ptr
				}
			}
			if !srcElement.IsValid() {
				continue
			}
			if srcKind == dstKind {
				if err = deepMerge(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
					return
				}
			} else {
				if srcKind == reflect.Map {
					if err = deepMap(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
						return
					}
				} else {
					return fmt.Errorf("type mismatch on %s field: found %v, expected %v", fieldName, srcKind, dstKind)
				}
			}
		}
	}
	return
}

// Map sets fields' values in dst from src.
// src can be a map with string keys or a struct. dst must be the opposite:
// if src is a map, dst must be a valid pointer to struct. If src is a struct,
// dst must be map[string]interface{}.
// It won't merge unexported (private) fields and will do recursively
// any exported field.
// If dst is a map, keys will be src fields' names in lower camel case.
// Missing key in src that doesn't match a field in dst will be skipped. This
// doesn't apply if dst is a map.
// This is separated method from Merge because it is cleaner and it keeps sane
// semantics: merging equal types, mapping different (restricted) types.
func Map(dst, src interface{}) error {
	return _map(dst, src, false)
}

// MapWithOverwrite will do the same as Map except that non-empty dst attributes will be overriden by
// non-empty src attribute values.
func MapWithOverwrite(dst, src interface{}) error {
	return _map(dst, src, true)
}

func _map(dst, src interface{}, overwrite bool) error {
	var (
		vDst, vSrc reflect.Value
		err        error
	)
	if vDst, vSrc, err = resolveValues(dst, src); err != nil {
		return err
	}
	// To be friction-less, we redirect equal-type arguments
	// to deepMerge. Only because arguments can be anything.
	if vSrc.Kind() == vDst.Kind() {
		return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, overwrite)
	}
	switch vSrc.Kind() {
	case reflect.Struct:
		if vDst.Kind() != reflect.Map {
			return ErrExpectedMapAsDestination
		}
	case reflect.Map:
		if vDst.Kind() != reflect.Struct {
			return ErrExpectedStructAsDestination
		}
	default:
		return ErrNotSupported
	}
	return deepMap(vDst, vSrc, make(map[uintptr]*visit), 0, overwrite)
}


================================================
FILE: vendor/github.com/imdario/mergo/merge.go
================================================
// Copyright 2013 Dario Castañé. All rights reserved.
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Based on src/pkg/reflect/deepequal.go from official
// golang's stdlib.

package mergo

import (
	"reflect"
)

// Traverses recursively both values, assigning src's fields values to dst.
// The map argument tracks comparisons that have already been seen, which allows
// short circuiting on recursive types.
func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, overwrite bool) (err error) {
	if !src.IsValid() {
		return
	}
	if dst.CanAddr() {
		addr := dst.UnsafeAddr()
		h := 17 * addr
		seen := visited[h]
		typ := dst.Type()
		for p := seen; p != nil; p = p.next {
			if p.ptr == addr && p.typ == typ {
				return nil
			}
		}
		// Remember, remember...
		visited[h] = &visit{addr, typ, seen}
	}
	switch dst.Kind() {
	case reflect.Struct:
		for i, n := 0, dst.NumField(); i < n; i++ {
			if err = deepMerge(dst.Field(i), src.Field(i), visited, depth+1, overwrite); err != nil {
				return
			}
		}
	case reflect.Map:
		for _, key := range src.MapKeys() {
			srcElement := src.MapIndex(key)
			if !srcElement.IsValid() {
				continue
			}
			dstElement := dst.MapIndex(key)
			switch srcElement.Kind() {
			case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Slice:
				if srcElement.IsNil() {
					continue
				}
				fallthrough
			default:
				if !srcElement.CanInterface() {
					continue
				}
				switch reflect.TypeOf(srcElement.Interface()).Kind() {
				case reflect.Struct:
					fallthrough
				case reflect.Ptr:
					fallthrough
				case reflect.Map:
					if err = deepMerge(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
						return
					}
				}
			}
			if !isEmptyValue(srcElement) && (overwrite || (!dstElement.IsValid() || isEmptyValue(dst))) {
				if dst.IsNil() {
					dst.Set(reflect.MakeMap(dst.Type()))
				}
				dst.SetMapIndex(key, srcElement)
			}
		}
	case reflect.Ptr:
		fallthrough
	case reflect.Interface:
		if src.IsNil() {
			break
		} else if dst.IsNil() || overwrite {
			if dst.CanSet() && (overwrite || isEmptyValue(dst)) {
				dst.Set(src)
			}
		} else if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, overwrite); err != nil {
			return
		}
	default:
		if dst.CanSet() && !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) {
			dst.Set(src)
		}
	}
	return
}

// Merge will fill any empty for value type attributes on the dst struct using corresponding
// src attributes if they themselves are not empty. dst and src must be valid same-type structs
// and dst must be a pointer to struct.
// It won't merge unexported (private) fields and will do recursively any exported field.
func Merge(dst, src interface{}) error {
	return merge(dst, src, false)
}

// MergeWithOverwrite will do the same as Merge except that non-empty dst attributes will be overriden by
// non-empty src attribute values.
func MergeWithOverwrite(dst, src interface{}) error {
	return merge(dst, src, true)
}

func merge(dst, src interface{}, overwrite bool) error {
	var (
		vDst, vSrc reflect.Value
		err        error
	)
	if vDst, vSrc, err = resolveValues(dst, src); err != nil {
		return err
	}
	if vDst.Type() != vSrc.Type() {
		return ErrDifferentArgumentsTypes
	}
	return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, overwrite)
}


================================================
FILE: vendor/github.com/imdario/mergo/mergo.go
================================================
// Copyright 2013 Dario Castañé. All rights reserved.
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Based on src/pkg/reflect/deepequal.go from official
// golang's stdlib.

package mergo

import (
	"errors"
	"reflect"
)

// Errors reported by Mergo when it finds invalid arguments.
var (
	ErrNilArguments                = errors.New("src and dst must not be nil")
	ErrDifferentArgumentsTypes     = errors.New("src and dst must be of same type")
	ErrNotSupported                = errors.New("only structs and maps are supported")
	ErrExpectedMapAsDestination    = errors.New("dst was expected to be a map")
	ErrExpectedStructAsDestination = errors.New("dst was expected to be a struct")
)

// During deepMerge, must keep track of checks that are
// in progress.  The comparison algorithm assumes that all
// checks in progress are true when it reencounters them.
// Visited are stored in a map indexed by 17 * a1 + a2;
type visit struct {
	ptr  uintptr
	typ  reflect.Type
	next *visit
}

// From src/pkg/encoding/json.
func isEmptyValue(v reflect.Value) bool {
	switch v.Kind() {
	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
		return v.Len() == 0
	case reflect.Bool:
		return !v.Bool()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return v.Int() == 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return v.Uint() == 0
	case reflect.Float32, reflect.Float64:
		return v.Float() == 0
	case reflect.Interface, reflect.Ptr:
		return v.IsNil()
	}
	return false
}

func resolveValues(dst, src interface{}) (vDst, vSrc reflect.Value, err error) {
	if dst == nil || src == nil {
		err = ErrNilArguments
		return
	}
	vDst = reflect.ValueOf(dst).Elem()
	if vDst.Kind() != reflect.Struct && vDst.Kind() != reflect.Map {
		err = ErrNotSupported
		return
	}
	vSrc = reflect.ValueOf(src)
	// We check if vSrc is a pointer to dereference it.
	if vSrc.Kind() == reflect.Ptr {
		vSrc = vSrc.Elem()
	}
	return
}

// Traverses recursively both values, assigning src's fields values to dst.
// The map argument tracks comparisons that have already been seen, which allows
// short circuiting on recursive types.
func deeper(dst, src reflect.Value, visited map[uintptr]*visit, depth int) (err error) {
	if dst.CanAddr() {
		addr := dst.UnsafeAddr()
		h := 17 * addr
		seen := visited[h]
		typ := dst.Type()
		for p := seen; p != nil; p = p.next {
			if p.ptr == addr && p.typ == typ {
				return nil
			}
		}
		// Remember, remember...
		visited[h] = &visit{addr, typ, seen}
	}
	return // TODO refactor
}


================================================
FILE: vendor/github.com/mitchellh/go-homedir/LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2013 Mitchell Hashimoto

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.


================================================
FILE: vendor/github.com/mitchellh/go-homedir/README.md
================================================
# go-homedir

This is a Go library for detecting the user's home directory without
the use of cgo, so the library can be used in cross-compilation environments.

Usage is incredibly simple, just call `homedir.Dir()` to get the home directory
for a user, and `homedir.Expand()` to expand the `~` in a path to the home
directory.

**Why not just use `os/user`?** The built-in `os/user` package requires
cgo on Darwin systems. This means that any Go code that uses that package
cannot cross compile. But 99% of the time the use for `os/user` is just to
retrieve the home directory, which we can do for the current user without
cgo. This library does that, enabling cross-compilation.


================================================
FILE: vendor/github.com/mitchellh/go-homedir/homedir.go
================================================
package homedir

import (
	"bytes"
	"errors"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"sync"
)

// DisableCache will disable caching of the home directory. Caching is enabled
// by default.
var DisableCache bool

var homedirCache string
var cacheLock sync.RWMutex

// Dir returns the home directory for the executing user.
//
// This uses an OS-specific method for discovering the home directory.
// An error is returned if a home directory cannot be detected.
func Dir() (string, error) {
	if !DisableCache {
		cacheLock.RLock()
		cached := homedirCache
		cacheLock.RUnlock()
		if cached != "" {
			return cached, nil
		}
	}

	cacheLock.Lock()
	defer cacheLock.Unlock()

	var result string
	var err error
	if runtime.GOOS == "windows" {
		result, err = dirWindows()
	} else {
		// Unix-like system, so just assume Unix
		result, err = dirUnix()
	}

	if err != nil {
		return "", err
	}
	homedirCache = result
	return result, nil
}

// Expand expands the path to include the home directory if the path
// is prefixed with `~`. If it isn't prefixed with `~`, the path is
// returned as-is.
func Expand(path string) (string, error) {
	if len(path) == 0 {
		return path, nil
	}

	if path[0] != '~' {
		return path, nil
	}

	if len(path) > 1 && path[1] != '/' && path[1] != '\\' {
		return "", errors.New("cannot expand user-specific home dir")
	}

	dir, err := Dir()
	if err != nil {
		return "", err
	}

	return filepath.Join(dir, path[1:]), nil
}

func dirUnix() (string, error) {
	// First prefer the HOME environmental variable
	if home := os.Getenv("HOME"); home != "" {
		return home, nil
	}

	// If that fails, try getent
	var stdout bytes.Buffer
	cmd := exec.Command("getent", "passwd", strconv.Itoa(os.Getuid()))
	cmd.Stdout = &stdout
	if err := cmd.Run(); err != nil {
		// If "getent" is missing, ignore it
		if err == exec.ErrNotFound {
			return "", err
		}
	} else {
		if passwd := strings.TrimSpace(stdout.String()); passwd != "" {
			// username:password:uid:gid:gecos:home:shell
			passwdParts := strings.SplitN(passwd, ":", 7)
			if len(passwdParts) > 5 {
				return passwdParts[5], nil
			}
		}
	}

	// If all else fails, try the shell
	stdout.Reset()
	cmd = exec.Command("sh", "-c", "cd && pwd")
	cmd.Stdout = &stdout
	if err := cmd.Run(); err != nil {
		return "", err
	}

	result := strings.TrimSpace(stdout.String())
	if result == "" {
		return "", errors.New("blank output when reading home directory")
	}

	return result, nil
}

func dirWindows() (string, error) {
	// First prefer the HOME environmental variable
	if home := os.Getenv("HOME"); home != "" {
		return home, nil
	}

	drive := os.Getenv("HOMEDRIVE")
	path := os.Getenv("HOMEPATH")
	home := drive + path
	if drive == "" || path == "" {
		home = os.Getenv("USERPROFILE")
	}
	if home == "" {
		return "", errors.New("HOMEDRIVE, HOMEPATH, and USERPROFILE are blank")
	}

	return home, nil
}


================================================
FILE: vendor/github.com/wsxiaoys/terminal/LICENSE
================================================
Copyright (c) 2013 Meng Zhang. All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

   * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
   * Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


================================================
FILE: vendor/github.com/wsxiaoys/terminal/color/color.go
================================================
// The colors package provide a simple way to bring colorful characters to terminal interface.
//
// This example will output the text with a Blue foreground and a Black background
//      color.Println("@{bK}Example Text")
//
// This one will output the text with a red foreground
//      color.Println("@rExample Text")
//
// This one will escape the @
//      color.Println("@@")
//
// Full color syntax code
//      @{rgbcmykwRGBCMYKW}  foreground/background color
//        r/R:  Red
//        g/G:  Green
//        b/B:  Blue
//        c/C:  Cyan
//        m/M:  Magenta
//        y/Y:  Yellow
//        k/K:  Black
//        w/W:  White
//      @{|}  Reset format style
//      @{!./_} Bold / Dim / Italic / Underline
//      @{^&} Blink / Fast blink
//      @{*} High intensity foreground color
//      @{?} Reverse the foreground and background color
//      @{-} Hide the text
// Note some of the functions are not widely supported, like "Fast blink" and "Italic".
package color

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"log"
)

const (
	EscapeChar = '@'       // Escape character for color syntax
	ResetCode  = "\033[0m" // Short for reset to default style
)

// Mapping from character to concrete escape code.
var codeMap = map[int]int{
	'|': 0,
	'!': 1,
	'.': 2,
	'/': 3,
	'_': 4,
	'^': 5,
	'&': 6,
	'?': 7,
	'-': 8,
	'*': 60,

	'k': 30,
	'r': 31,
	'g': 32,
	'y': 33,
	'b': 34,
	'm': 35,
	'c': 36,
	'w': 37,
	'd': 39,

	'K': 40,
	'R': 41,
	'G': 42,
	'Y': 43,
	'B': 44,
	'M': 45,
	'C': 46,
	'W': 47,
	'D': 49,
}

// Compile color syntax string like "rG" to escape code.
func Colorize(x string) string {
	attr := 0
	fg := 39
	bg := 49

	for _, key := range x {
		c, ok := codeMap[int(key)]
		switch {
		case !ok:
			log.Printf("Wrong color syntax: %c", key)
		case 0 <= c && c <= 8:
			attr = c
		case 30 <= c && c <= 37:
			fg = c
		case 40 <= c && c <= 47:
			bg = c
		case c == 60:
			fg += c
		}
	}
	return fmt.Sprintf("\033[%d;%d;%dm", attr, fg, bg)
}

// Handle state after meeting one '@'
func compileColorSyntax(input, output *bytes.Buffer) {
	i, _, err := input.ReadRune()
	if err != nil {
		// EOF got
		log.Print("Parse failed on color syntax")
		return
	}

	switch i {
	default:
		output.WriteString(Colorize(string(i)))
	case '{':
		color := bytes.NewBufferString("")
		for {
			i, _, err := input.ReadRune()
			if err != nil {
				log.Print("Parse failed on color syntax")
				break
			}
			if i == '}' {
				break
			}
			color.WriteRune(i)
		}
		output.WriteString(Colorize(color.String()))
	case EscapeChar:
		output.WriteRune(EscapeChar)
	}
}

// Compile the string and replace color syntax with concrete escape code.
func compile(x string) string {
	if x == "" {
		return ""
	}

	input := bytes.NewBufferString(x)
	output := bytes.NewBufferString("")

	for {
		i, _, err := input.ReadRune()
		if err != nil {
			break
		}
		switch i {
		default:
			output.WriteRune(i)
		case EscapeChar:
			compileColorSyntax(input, output)
		}
	}
	return output.String()
}

// Compile multiple values, only do compiling on string type.
func compileValues(a *[]interface{}) {
	for i, x := range *a {
		if str, ok := x.(string); ok {
			(*a)[i] = compile(str)
		}
	}
}

// Similar to fmt.Print, will reset the color at the end.
func Print(a ...interface{}) (int, error) {
	a = append(a, ResetCode)
	compileValues(&a)
	return fmt.Print(a...)
}

// Similar to fmt.Println, will reset the color at the end.
func Println(a ...interface{}) (int, error) {
	a = append(a, ResetCode)
	compileValues(&a)
	return fmt.Println(a...)
}

// Similar to fmt.Printf, will reset the color at the end.
func Printf(format string, a ...interface{}) (int, error) {
	format += ResetCode
	format = compile(format)
	return fmt.Printf(format, a...)
}

// Similar to fmt.Fprint, will reset the color at the end.
func Fprint(w io.Writer, a ...interface{}) (int, error) {
	a = append(a, ResetCode)
	compileValues(&a)
	return fmt.Fprint(w, a...)
}

// Similar to fmt.Fprintln, will reset the color at the end.
func Fprintln(w io.Writer, a ...interface{}) (int, error) {
	a = append(a, ResetCode)
	compileValues(&a)
	return fmt.Fprintln(w, a...)
}

// Similar to fmt.Fprintf, will reset the color at the end.
func Fprintf(w io.Writer, format string, a ...interface{}) (int, error) {
	format += ResetCode
	format = compile(format)
	return fmt.Fprintf(w, format, a...)
}

// Similar to fmt.Sprint, will reset the color at the end.
func Sprint(a ...interface{}) string {
	a = append(a, ResetCode)
	compileValues(&a)
	return fmt.Sprint(a...)
}

// Similar to fmt.Sprintf, will reset the color at the end.
func Sprintf(format string, a ...interface{}) string {
	format += ResetCode
	format = compile(format)
	return fmt.Sprintf(format, a...)
}

// Similar to fmt.Errorf, will reset the color at the end.
func Errorf(format string, a ...interface{}) error {
	return errors.New(Sprintf(format, a...))
}


================================================
FILE: vendor/github.com/zackbloom/go-ini/.gitignore
================================================
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so

# Folders
_obj
_test

# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out

*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*

_testmain.go

*.exe
*.test
*.prof
*.nope


================================================
FILE: vendor/github.com/zackbloom/go-ini/README.md
================================================
go-ini
======

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.

For example, for an INI file like this:

    [Pod_mysql]
    cache_size = 2000
    default_socket = /tmp/mysql.sock

    [Mysql]
    default_socket = /tmp/mysql.sock

Decode into a structure like this:

    type MyIni struct {

        PdoMysql struct {
            CacheSize     int `ini:"cache_size"`
            DefaultSocket string `ini:"default_socket"`
        } `ini:"[Pdo_myqsl]"`

        Mysql struct {
            DefaultSocket string `ini:"default_socket"`
        } `ini:"[Myqsl]"`
    }

With code like this:

    var config MyIni
    var b []byte      // config file stored here
    err := ini.Unmarshal(b, &config)


Advanced Types
==============

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:

    [CREATE SONG]
    SongId=21348
    Title=Long Way to Go
    Artist=The Coach

    [CREATE SONG]
    SongId=9855
    Title=The Falcon Lead
    Artist=It Wasn't Safe

    [CREATE PLAYLIST]
    PlaylistId=438432
    Title=Acid Jazz
    Song=21348
    Song=482
    Song=9855

    [CREATE PLAYLIST]
    PlaylistId=2585
    Title=Lounge
    Song=7558
    Song=25828

With GO-INI, parsing is as simple as defining the structure and unmarshalling it.

    package main

    import (
        "encoding/json"
        "github.com/sspencer/go-ini"
        "io/ioutil"
        "log"
        "os"
    )

    type TunePlayer struct {
        Songs []struct {
            SongId int
            Title string
            Artist string
        } `ini:"[CREATE SONG]"`

        Playlists []struct {
            PlaylistId int
            Title string
            SongIds []int `ini:"Song"`
        } `ini:[CREATE PLAYLIST]`
    }

    func main() {
        var player TunePlayer

        content, err := ioutil.ReadFile("./tunes.ini")
        if err != nil {
            log.Fatal(err)
        }

        err = ini.Unmarshal(content, &player)
        if err != nil {
            log.Fatal(err)
        }

        // Output same struct as JSON to verify parsing worked
        enc := json.NewEncoder(os.Stdout)
        if err := enc.Encode(&player); err != nil {
            log.Println(err)
        }
    }





Todo
=====

Need to parse inner array of structs

    struct {
        Playlists []struct {
            Id int
            Title string
            Programs []struct {
                Id int
                Mix string
                Separation int
            } `ini:"Play Program"`
        } `ini:"[CREATE PLAYLIST]"`
    }

    [CREATE PLAYLIST]
    ID=6524
    Title=Pop
    Start Schedule

    Play Program
    ID=391
    Mix=RAND

    Play Program
    ID=3912
    Separation=10
    End Schedule


================================================
FILE: vendor/github.com/zackbloom/go-ini/decode.go
================================================
// Decode INI files with a syntax similar to JSON decoding
package ini

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"reflect"
	"strconv"
	"strings"
)

type Unmatched struct {
	lineNum int
	line    string
}

type IniError struct {
	lineNum int
	line    string
	error   string
}

// decodeState represents the state while decoding a INI value.
type decodeState struct {
	lineNum    int
	line       string
	scanner    *bufio.Scanner
	savedError error
	unmatched  []Unmatched
}

type property struct {
	tag      string
	value    reflect.Value
	children propertyMap
	isArray  bool
	//array         []interface{}
	isInitialized bool
}

type propertyMap map[string]property

//------------------------------------------------------------------

// NewStack returns a new stack.
func NewPropMapStack() *PropMapStack {
	return &PropMapStack{}
}

// Stack is a basic LIFO stack that resizes as needed.
type PropMapStack struct {
	items []propertyMap
	count int
}

// Push adds an iterm to the top of the stack
func (s *PropMapStack) Push(item propertyMap) {
	s.items = append(s.items[:s.count], item)
	s.count++
}

// Pop removes the top item (LIFO) from the stack
func (s *PropMapStack) Pop() propertyMap {
	if s.count == 0 {
		return nil
	}

	s.count--
	return s.items[s.count]
}

// Peek returns item at top of stack without removing it
func (s *PropMapStack) Peek() propertyMap {
	if s.count == 0 {
		return nil
	}

	return s.items[s.count-1]
}

// Empty returns true when stack is empty, false otherwise
func (s *PropMapStack) Empty() bool {
	return s.count == 0
}

// Size returns the number of items in the stack
func (s *PropMapStack) Size() int {
	return s.count
}

/*
 * Unmarshal parses the INI-encoded data and stores the result
 * in the value pointed to by v.
 */
func Unmarshal(data []byte, v interface{}) error {
	var d decodeState
	d.init(data)
	return d.unmarshal(v)
}

/*
 * String interfacer for Unmatched
 */
func (u Unmatched) String() string {
	return fmt.Sprintf("%d %s", u.lineNum, u.line)
}

/*
 * Conform to Error Interfacer
 */
func (e *IniError) Error() string {
	if e.lineNum > 0 {
		return fmt.Sprintf("%s on line %d: \"%s\"", e.error, e.lineNum, e.line)
	} else {
		return e.error
	}
}

/*
 * Stringer interface for property
 */
func (p property) String() string {
	return fmt.Sprintf("<property %s, isArray:%t>", p.tag, p.isArray)
}

/*
 * Convenience function to prep for decoding byte array.
 */
func (d *decodeState) init(data []byte) *decodeState {

	d.lineNum = 0
	d.line = ""
	d.scanner = bufio.NewScanner(bytes.NewReader(data))
	d.savedError = nil

	return d
}

/*
 * saveError saves the first err it is called with,
 * for reporting at the end of the unmarshal.
 */
func (d *decodeState) saveError(err error) {
	if d.savedError == nil {
		d.savedError = err
	}
}

/*
 * Recursive function to map data types in the describing structs
 * to string markers (tags) in the INI file.
 */
func (d *decodeState) generateMap(m propertyMap, v reflect.Value) {

	if v.Type().Kind() == reflect.Ptr {
		d.generateMap(m, v.Elem())
	} else if v.Kind() == reflect.Struct {
		typ := v.Type()
		for i := 0; i < typ.NumField(); i++ {

			sf := typ.Field(i)
			f := v.Field(i)
			kind := f.Type().Kind()

			tag := sf.Tag.Get("ini")
			if len(tag) == 0 {
				tag = sf.Name
			}
			tag = strings.TrimSpace(strings.ToLower(tag))

			st := property{tag, f, make(propertyMap), kind == reflect.Slice, true}

			// some structures are just for organizing data
			if tag != "-" {
				m[tag] = st
			}

			if kind == reflect.Struct {
				if tag == "-" {
					d.generateMap(m, f)
				} else {
					// little namespacing here so property names can
					// be the same under different sections
					//fmt.Printf("Struct tag: %s, type: %s\n", tag, f.Type())
					d.generateMap(st.children, f)
				}
			} else if kind == reflect.Slice {
				d.generateMap(st.children, reflect.New(f.Type().Elem()))
			}
		}
	}
}

/*
 * Iterates line-by-line through INI file setting values into a struct.
 */
func (d *decodeState) unmarshal(x interface{}) error {

	var topMap propertyMap
	topMap = make(propertyMap)

	d.generateMap(topMap, reflect.ValueOf(x))

	propStack := NewPropMapStack()
	propStack.Push(topMap)

	// for every line in file
	for d.scanner.Scan() {

		if d.savedError != nil {
			break // breaks on first error
		}

		d.line = d.scanner.Text()
		d.lineNum++

		line := strings.TrimSpace(d.line)

		if len(line) < 1 || line[0] == ';' || line[0] == '#' {
			continue // skip comments
		}

		// Two types of lines:
		//   1. NAME=VALUE   (at least one equal sign - breaks on first)
		//   2. [HEADER]     (no equals sign, square brackets NOT required)
		matches := strings.SplitN(line, "=", 2)
		matched := false
		pn := ""
		pv := ""

		if len(matches) == 2 {
			// NAME=VALUE
			pn = strings.ToLower(strings.TrimSpace(matches[0]))
			pv = strings.TrimSpace(matches[1])
			prop := propStack.Peek()[pn]

			if prop.isInitialized {
				if prop.isArray {
					value := reflect.New(prop.value.Type().Elem())
					d.setValue(reflect.Indirect(value), pv)
					appendValue(prop.value, value)

				} else {
					d.setValue(prop.value, pv)
				}

				matched = true
			}

			// What if property is umatched - keep popping the stack
			// until a potential map is found or stay within current section?
			// Think answer is pop.
			// NOPE
			// Section could have unmatched name=value if user doesn't
			// care about certain values - only stack crawling happens
			// during numMatches==1 time?
			// This means if there is > 1 section, there needs to be
			// section breaks for everything

		} else {
			// [Header] section
			pn = strings.ToLower(strings.TrimSpace(matches[0]))

			for propStack.Size() > 0 {
				prop := propStack.Peek()[pn]
				if prop.isInitialized {
					propStack.Push(prop.children)
					matched = true
					break
				} else if propStack.Size() > 1 {
					_ = propStack.Pop()
				} else {
					break
				}
			}
		}

		if !matched {
			d.unmatched = append(d.unmatched, Unmatched{d.lineNum, d.line})
		}
	}

	return d.savedError
}

func (d *decodeState) unmarshal2(x interface{}) error {

	var sectionMap propertyMap = make(propertyMap)
	var tempMap propertyMap = make(propertyMap)

	var section, nextSection property
	var inSection, nextHasSection bool = false, false
	var tempValue reflect.Value // "temp" is for filling in array of structs
	var numTempValue int

	d.generateMap(sectionMap, reflect.ValueOf(x))

	for d.scanner.Scan() {
		if d.savedError != nil {
			break
		}

		d.line = d.scanner.Text()
		d.lineNum++

		//fmt.Printf("%03d: %s\n", d.lineNum, d.line)

		line := strings.ToLower(strings.TrimSpace(d.line))

		if len(line) < 1 || line[0] == ';' || line[0] == '#' {
			continue // skip comments
		}

		// [Sections] could appear at any time (square brackets not required)
		// When in a section, also look in children map
		nextSection, nextHasSection = sectionMap[line]
		if nextHasSection {
			if numTempValue > 0 && section.isArray {
				appendValue(section.value, tempValue)
			}

			section = nextSection
			inSection = true

			if section.isArray {
				tempValue = reflect.New(section.value.Type().Elem())
				d.generateMap(tempMap, tempValue)
			}

			numTempValue = 0
			continue
		}

		// unrecognized section - exit out of current section
		if line[0] == '[' && line[len(line)-1] == ']' {
			inSection = false
			continue
		}

		matches := strings.SplitN(d.line, "=", 2)
		matched := false

		// potential property=value
		if len(matches) == 2 {
			n := strings.ToLower(strings.TrimSpace(matches[0]))
			s := strings.TrimSpace(matches[1])

			if inSection {
				// child property, within a section
				childProperty, hasProp := section.children[n]

				if hasProp {
					if section.isArray {
						tempProperty := tempMap[n]
						numTempValue++
						d.setValue(tempProperty.value, s)
					} else {
						d.setValue(childProperty.value, s)
					}

					matched = true
				}
			}

			if !matched {
				// top level property
				topLevelProperty, hasProp := sectionMap[n]
				if hasProp {
					// just encountered a top level property - switch out of section mode
					inSection = false
					matched = true
					d.setValue(topLevelProperty.value, s)
				}
			}
		}

		if !matched {
			d.unmatched = append(d.unmatched, Unmatched{d.lineNum, d.line})
		}
	}

	if numTempValue > 0 {
		appendValue(section.value, tempValue)
	}

	return d.savedError
}

func appendValue(arr, val reflect.Value) {
	arr.Set(reflect.Append(arr, reflect.Indirect(val)))
}

// Set Value with given string
func (d *decodeState) setValue(v reflect.Value, s string) {
	//fmt.Printf("SET(kind:%s, %s)\n", v.Kind(), s)

	switch v.Kind() {

	case reflect.String:
		v.SetString(s)

	case reflect.Bool:
		v.SetBool(boolValue(s))

	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		n, err := strconv.ParseInt(s, 10, 64)
		if err != nil || v.OverflowInt(n) {
			d.saveError(&IniError{d.lineNum, d.line, "Invalid int"})
			return
		}
		v.SetInt(n)

	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		n, err := strconv.ParseUint(s, 10, 64)
		if err != nil || v.OverflowUint(n) {
			d.saveError(&IniError{d.lineNum, d.line, "Invalid uint"})
			return
		}
		v.SetUint(n)

	case reflect.Float32, reflect.Float64:
		n, err := strconv.ParseFloat(s, v.Type().Bits())
		if err != nil || v.OverflowFloat(n) {
			d.saveError(&IniError{d.lineNum, d.line, "Invalid float"})
			return
		}
		v.SetFloat(n)

	case reflect.Slice:
		d.sliceValue(v, s)

	default:
		d.saveError(&IniError{d.lineNum, d.line, fmt.Sprintf("Can't set value of type %s", v.Kind())})
	}

}

func (d *decodeState) sliceValue(v reflect.Value, s string) {
	//fmt.Printf(":SLICE(%s, %s)\n", v.Kind(), s)

	switch v.Type().Elem().Kind() {

	case reflect.String:
		v.Set(reflect.Append(v, reflect.ValueOf(s)))

	case reflect.Bool:
		v.Set(reflect.Append(v, reflect.ValueOf(boolValue(s))))

	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		// Hardcoding of []int temporarily
		n, err := strconv.ParseInt(s, 10, 64)
		if err != nil {
			d.saveError(&IniError{d.lineNum, d.line, "Invalid int"})
			return
		}

		n1 := reflect.ValueOf(n)
		n2 := n1.Convert(v.Type().Elem())

		v.Set(reflect.Append(v, n2))

	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		n, err := strconv.ParseUint(s, 10, 64)
		if err != nil {
			d.saveError(&IniError{d.lineNum, d.line, "Invalid uint"})
			return
		}

		n1 := reflect.ValueOf(n)
		n2 := n1.Convert(v.Type().Elem())

		v.Set(reflect.Append(v, n2))

	case reflect.Float32, reflect.Float64:
		n, err := strconv.ParseFloat(s, 64)
		if err != nil {
			d.saveError(&IniError{d.lineNum, d.line, "Invalid float"})
			return
		}

		n1 := reflect.ValueOf(n)
		n2 := n1.Convert(v.Type().Elem())

		v.Set(reflect.Append(v, n2))

	default:
		d.saveError(&IniError{d.lineNum, d.line, fmt.Sprintf("Can't set value in array of type %s",
			v.Type().Elem().Kind())})
	}

}

// Returns true for truthy values like t/true/y/yes/1, false otherwise
func boolValue(s string) bool {
	v := false
	switch strings.ToLower(s) {
	case "t", "true", "y", "yes", "1":
		v = true
	}

	return v
}

// A Decoder reads and decodes INI object from an input stream.
type Decoder struct {
	r io.Reader
	d decodeState
}

// NewDecoder returns a new decoder that reads from r.
//
// The decoder introduces its own buffering and may
// read data from r beyond the JSON values requested.
func NewDecoder(r io.Reader) *Decoder {
	return &Decoder{r: r}
}

// Decode reads the INI file and stores it in the value pointed to by v.
//
// See the documentation for Unmarshal for details about
// the conversion of an INI into a Go value.
func (dec *Decoder) Decode(v interface{}) error {

	buf, readErr := ioutil.ReadAll(dec.r)
	if readErr != nil {
		return readErr
	}
	// Don't save err from unmarshal into dec.err:
	// the connection is still usable since we read a complete JSON
	// object from it before the error happened.
	dec.d.init(buf)
	err := dec.d.unmarshal(v)

	return err
}

// UnparsedLines returns an array of strings where each string is an
// unparsed line from the file.
func (dec *Decoder) Unmatched() []Unmatched {
	return dec.d.unmatched
}


================================================
FILE: vendor/github.com/zackbloom/go-ini/stack.go
================================================
package ini

// NewStack returns a new stack.
func NewStack() *Stack {
	return &Stack{}
}

// Stack is a basic LIFO stack that resizes as needed.
type Stack struct {
	items []interface{}
	count int
}

// Push adds an iterm to the top of the stack
func (s *Stack) Push(item interface{}) {
	s.items = append(s.items[:s.count], item)
	s.count++
}

// Pop removes the top item (LIFO) from the stack
func (s *Stack) Pop() interface{} {
	if s.count == 0 {
		return nil
	}

	s.count--
	return s.items[s.count]
}

// Peek returns item at top of stack without removing it
func (s *Stack) Peek() interface{} {
	if s.count == 0 {
		return nil
	}

	return s.items[s.count-1]
}

// Empty returns true when stack is empty, false otherwise
func (s *Stack) Empty() bool {
	return s.count == 0
}

// Size returns the number of items in the stack
func (s *Stack) Size() int {
	return s.count
}


================================================
FILE: vendor/github.com/zackbloom/goamz/LICENSE
================================================
This software is licensed under the LGPLv3, included below.

As a special exception to the GNU Lesser General Public License version 3
("LGPL3"), the copyright holders of this Library give you permission to
convey to a third party a Combined Work that links statically or dynamically
to this Library without providing any Minimal Corresponding Source or
Minimal Application Code as set out in 4d or providing the installation
information set out in section 4e, provided that you comply with the other
provisions of LGPL3 and provided that you meet, for the Application the
terms and conditions of the license(s) which apply to the Application.

Except as stated in this special exception, the provisions of LGPL3 will
continue to comply in full to this Library. If you modify this Library, you
may apply this exception to your version of this Library, but you are not
obliged to do so. If you do not wish to do so, delete this exception
statement from your version. This exception does not (and cannot) modify any
license terms which apply to the Application, with which you must still
comply.


                   GNU LESSER GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.


  This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.

  0. Additional Definitions.

  As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.

  "The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.

  An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.

  A "Combined Work" is a work produced by combining or linking an
Application with the Library.  The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".

  The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.

  The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.

  1. Exception to Section 3 of the GNU GPL.

  You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.

  2. Conveying Modified Versions.

  If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:

   a) under this License, provided that you make a good faith effort to
   ensure that, in the event an Application does not supply the
   function or data, the facility still operates, and performs
   whatever part of its purpose remains meaningful, or

   b) under the GNU GPL, with none of the additional permissions of
   this License applicable to that copy.

  3. Object Code Incorporating Material from Library Header Files.

  The object code form of an Application may incorporate material from
a header file that is part of the Library.  You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:

   a) Give prominent notice with each copy of the object code that the
   Library is used in it and that the Library and its use are
   covered by this License.

   b) Accompany the object code with a copy of the GNU GPL and this license
   document.

  4. Combined Works.

  You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:

   a) Give prominent notice with each copy of the Combined Work that
   the Library is used in it and that the Library and its use are
   covered by this License.

   b) Accompany the Combined Work with a copy of the GNU GPL and this license
   document.

   c) For a Combined Work that displays copyright notices during
   execution, include the copyright notice for the Library among
   these notices, as well as a reference directing the user to the
   copies of the GNU GPL and this license document.

   d) Do one of the following:

       0) Convey the Minimal Corresponding Source under the terms of this
       License, and the Corresponding Application Code in a form
       suitable for, and under terms that permit, the user to
       recombine or relink the Application with a modified version of
       the Linked Version to produce a modified Combined Work, in the
       manner specified by section 6 of the GNU GPL for conveying
       Corresponding Source.

       1) Use a suitable shared library mechanism for linking with the
       Library.  A suitable mechanism is one that (a) uses at run time
       a copy of the Library already present on the user's computer
       system, and (b) will operate properly with a modified version
       of the Library that is interface-compatible with the Linked
       Version.

   e) Provide Installation Information, but only if you would otherwise
   be required to provide such information under section 6 of the
   GNU GPL, and only to the extent that such information is
   necessary to install and execute a modified version of the
   Combined Work produced by recombining or relinking the
   Application with a modified version of the Linked Version. (If
   you use option 4d0, the Installation Information must accompany
   the Minimal Corresponding Source and Corresponding Application
   Code. If you use option 4d1, you must provide the Installation
   Information in the manner specified by section 6 of the GNU GPL
   for conveying Corresponding Source.)

  5. Combined Libraries.

  You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:

   a) Accompany the combined library with a copy of the same work based
   on the Library, uncombined with any other library facilities,
   conveyed under the terms of this License.

   b) Give prominent notice with the combined library that part of it
   is a work based on the Library, and explaining where to find the
   accompanying uncombined form of the same work.

  6. Revised Versions of the GNU Lesser General Public License.

  The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.

  Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.

  If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.


================================================
FILE: vendor/github.com/zackbloom/goamz/aws/attempt.go
================================================
package aws

import (
	"time"
)

// AttemptStrategy represents a strategy for waiting for an action
// to complete successfully. This is an internal type used by the
// implementation of other goamz packages.
type AttemptStrategy struct {
	Total time.Duration // total duration of attempt.
	Delay time.Duration // interval between each try in the burst.
	Min   int           // minimum number of retries; overrides Total
}

type Attempt struct {
	strategy AttemptStrategy
	last     time.Time
	end      time.Time
	force    bool
	count    int
}

// Start begins a new sequence of attempts for the given strategy.
func (s AttemptStrategy) Start() *Attempt {
	now := time.Now()
	return &Attempt{
		strategy: s,
		last:     now,
		end:      now.Add(s.Total),
		force:    true,
	}
}

// Next waits until it is time to perform the next attempt or returns
// false if it is time to stop trying.
func (a *Attempt) Next() bool {
	now := time.Now()
	sleep := a.nextSleep(now)
	if !a.force && !now.Add(sleep).Before(a.end) && a.strategy.Min <= a.count {
		return false
	}
	a.force = false
	if sleep > 0 && a.count > 0 {
		time.Sleep(sleep)
		now = time.Now()
	}
	a.count++
	a.last = now
	return true
}

func (a *Attempt) nextSleep(now time.Time) time.Duration {
	sleep := a.strategy.Delay - now.Sub(a.last)
	if sleep < 0 {
		return 0
	}
	return sleep
}

// HasNext returns whether another attempt will be made if the current
// one fails. If it returns true, the following call to Next is
// guaranteed to return true.
func (a *Attempt) HasNext() bool {
	if a.force || a.strategy.Min > a.count {
		return true
	}
	now := time.Now()
	if now.Add(a.nextSleep(now)).Before(a.end) {
		a.force = true
		return true
	}
	return false
}


================================================
FILE: vendor/github.com/zackbloom/goamz/aws/aws.go
================================================
//
// goamz - Go packages to interact with the Amazon Web Services.
//
//   https://wiki.ubuntu.com/goamz
//
// Copyright (c) 2011 Canonical Ltd.
//
// Written by Gustavo Niemeyer <gustavo.niemeyer@canonical.com>
//
package aws

import (
	"encoding/json"
	"encoding/xml"
	"errors"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"os"
	"os/user"
	"path"
	"regexp"
	"strings"
	"time"
)

// Regular expressions for INI files
var (
	iniSectionRegexp = regexp.MustCompile(`^\s*\[([^\[\]]+)\]\s*$`)
	iniSettingRegexp = regexp.MustCompile(`^\s*(.+?)\s*=\s*(.*\S)\s*$`)
)

// Defines the valid signers
const (
	V2Signature      = iota
	V4Signature      = iota
	Route53Signature = iota
)

// Defines the service endpoint and correct Signer implementation to use
// to sign requests for this endpoint
type ServiceInfo struct {
	Endpoint string
	Signer   uint
}

// Region defines the URLs where AWS services may be accessed.
//
// See http://goo.gl/d8BP1 for more details.
type Region struct {
	Name                   string // the canonical name of this region.
	EC2Endpoint            string
	S3Endpoint             string
	S3BucketEndpoint       string // Not needed by AWS S3. Use ${bucket} for bucket name.
	S3LocationConstraint   bool   // true if this region requires a LocationConstraint declaration.
	S3LowercaseBucket      bool   // true if the region requires bucket names to be lower case.
	SDBEndpoint            string
	SNSEndpoint            string
	SQSEndpoint            string
	SESEndpoint            string
	IAMEndpoint            string
	ELBEndpoint            string
	DynamoDBEndpoint       string
	CloudWatchServicepoint ServiceInfo
	AutoScalingEndpoint    string
	RDSEndpoint            ServiceInfo
	KinesisEndpoint        string
	STSEndpoint            string
	CloudFormationEndpoint string
	ElastiCacheEndpoint    string
}

var Regions = map[string]Region{
	APNortheast.Name:  APNortheast,
	APSoutheast.Name:  APSoutheast,
	APSoutheast2.Name: APSoutheast2,
	EUCentral.Name:    EUCentral,
	EUWest.Name:       EUWest,
	USEast.Name:       USEast,
	USWest.Name:       USWest,
	USWest2.Name:      USWest2,
	USGovWest.Name:    USGovWest,
	SAEast.Name:       SAEast,
}

// Designates a signer interface suitable for signing AWS requests, params
// should be appropriately encoded for the request before signing.
//
// A signer should be initialized with Auth and the appropriate endpoint.
type Signer interface {
	Sign(method, path string, params map[string]string)
}

// An AWS Service interface with the API to query the AWS service
//
// Supplied as an easy way to mock out service calls during testing.
type AWSService interface {
	// Queries the AWS service at a given method/path with the params and
	// returns an http.Response and error
	Query(method, path string, params map[string]string) (*http.Response, error)
	// Builds an error given an XML payload in the http.Response, can be used
	// to process an error if the status code is not 200 for example.
	BuildError(r *http.Response) error
}

// Implements a Server Query/Post API to easily query AWS services and build
// errors when desired
type Service struct {
	service ServiceInfo
	signer  Signer
}

// Create a base set of params for an action
func MakeParams(action string) map[string]string {
	params := make(map[string]string)
	params["Action"] = action
	return params
}

// Create a new AWS server to handle making requests
func NewService(auth Auth, service ServiceInfo) (s *Service, err error) {
	var signer Signer
	switch service.Signer {
	case V2Signature:
		signer, err = NewV2Signer(auth, service)
	// case V4Signature:
	// 	signer, err = NewV4Signer(auth, service, Regions["eu-west-1"])
	default:
		err = fmt.Errorf("Unsupported signer for service")
	}
	if err != nil {
		return
	}
	s = &Service{service: service, signer: signer}
	return
}

func (s *Service) Query(method, path string, params map[string]string) (resp *http.Response, err error) {
	params["Timestamp"] = time.Now().UTC().Format(time.RFC3339)
	u, err := url.Parse(s.service.Endpoint)
	if err != nil {
		return nil, err
	}
	u.Path = path

	s.signer.Sign(method, path, params)
	if method == "GET" {
		u.RawQuery = multimap(params).Encode()
		resp, err = http.Get(u.String())
	} else if method == "POST" {
		resp, err = http.PostForm(u.String(), multimap(params))
	}

	return
}

func (s *Service) BuildError(r *http.Response) error {
	errors := ErrorResponse{}
	xml.NewDecoder(r.Body).Decode(&errors)
	var err Error
	err = errors.Errors
	err.RequestId = errors.RequestId
	err.StatusCode = r.StatusCode
	if err.Message == "" {
		err.Message = r.Status
	}
	return &err
}

type ServiceError interface {
	error
	ErrorCode() string
}

type ErrorResponse struct {
	Errors    Error  `xml:"Error"`
	RequestId string // A unique ID for tracking the request
}

type Error struct {
	StatusCode int
	Type       string
	Code       string
	Message    string
	RequestId  string
}

func (err *Error) Error() string {
	return fmt.Sprintf("Type: %s, Code: %s, Message: %s",
		err.Type, err.Code, err.Message,
	)
}

func (err *Error) ErrorCode() string {
	return err.Code
}

type Auth struct {
	AccessKey, SecretKey string
	token                string
	expiration           time.Time
}

func (a *Auth) Token() string {
	if a.token == "" {
		return ""
	}
	if time.Since(a.expiration) >= -30*time.Second { //in an ideal world this should be zero assuming the instance is synching it's clock
		*a, _ = GetAuth("", "", "", time.Time{})
	}
	return a.token
}

func (a *Auth) Expiration() time.Time {
	return a.expiration
}

// To be used with other APIs that return auth credentials such as STS
func NewAuth(accessKey, secretKey, token string, expiration time.Time) *Auth {
	return &Auth{
		AccessKey:  accessKey,
		SecretKey:  secretKey,
		token:      token,
		expiration: expiration,
	}
}

// ResponseMetadata
type ResponseMetadata struct {
	RequestId string // A unique ID for tracking the request
}

type BaseResponse struct {
	ResponseMetadata ResponseMetadata
}

var unreserved = make([]bool, 128)
var hex = "0123456789ABCDEF"

func init() {
	// RFC3986
	u := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890-_.~"
	for _, c := range u {
		unreserved[c] = true
	}
}

func multimap(p map[string]string) url.Values {
	q := make(url.Values, len(p))
	for k, v := range p {
		q[k] = []string{v}
	}
	return q
}

type credentials struct {
	Code            string
	LastUpdated     string
	Type            string
	AccessKeyId     string
	SecretAccessKey string
	Token           string
	Expiration      string
}

// GetMetaData retrieves instance metadata about the current machine.
//
// See http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AESDG-chapter-instancedata.html for more details.
func GetMetaData(path string) (contents []byte, err error) {
	c := http.Client{
		Transport: &http.Transport{
			Dial: func(netw, addr string) (net.Conn, error) {
				deadline := time.Now().Add(5 * time.Second)
				c, err := net.DialTimeout(netw, addr, time.Second*2)
				if err != nil {
					return nil, err
				}
				c.SetDeadline(deadline)
				return c, nil
			},
		},
	}

	url := "http://169.254.169.254/latest/meta-data/" + path

	resp, err := c.Get(url)
	if err != nil {
		return
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		err = fmt.Errorf("Code %d returned for url %s", resp.StatusCode, url)
		return
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	return []byte(body), err
}

func GetRegion(regionName string) (region Region) {
	region = Regions[regionName]
	return
}

// GetInstanceCredentials creates an Auth based on the instance's role credentials.
// If the running instance is not in EC2 or does not have a valid IAM role, an error will be returned.
// For more info about setting up IAM roles, see http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html
func GetInstanceCredentials() (cred credentials, err error) {
	credentialPath := "iam/security-credentials/"

	// Get the instance role
	role, err := GetMetaData(credentialPath)
	if err != nil {
		return
	}

	// Get the instance role credentials
	credentialJSON, err := GetMetaData(credentialPath + string(role))
	if err != nil {
		return
	}

	err = json.Unmarshal([]byte(credentialJSON), &cred)
	return
}

// GetAuth creates an Auth based on either passed in credentials,
// environment information or instance based role credentials.
func GetAuth(accessKey string, secretKey, token string, expiration time.Time) (auth Auth, err error) {
	// First try passed in credentials
	if accessKey != "" && secretKey != "" {
		return Auth{accessKey, secretKey, token, expiration}, nil
	}

	// Next try to get auth from the environment
	auth, err = EnvAuth()
	if err == nil {
		// Found auth, return
		return
	}

	// Next try getting auth from the instance role
	cred, err := GetInstanceCredentials()
	if err == nil {
		// Found auth, return
		auth.AccessKey = cred.AccessKeyId
		auth.SecretKey = cred.SecretAccessKey
		auth.token = cred.Token
		exptdate, err := time.Parse("2006-01-02T15:04:05Z", cred.Expiration)
		if err != nil {
			err = fmt.Errorf("Error Parsing expiration date: cred.Expiration :%s , error: %s \n", cred.Expiration, err)
		}
		auth.expiration = exptdate
		return auth, err
	}

	// Next try getting auth from the credentials file
	auth, err = CredentialFileAuth("", "", time.Minute*5)
	if err == nil {
		return
	}

	//err = errors.New("No valid AWS authentication found")
	err = fmt.Errorf("No valid AWS authentication found: %s", err)
	return auth, err
}

// EnvAuth creates an Auth based on environment information.
// The AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment
// variables are used.
func EnvAuth() (auth Auth, err error) {
	auth.AccessKey = os.Getenv("AWS_ACCESS_KEY_ID")
	if auth.AccessKey == "" {
		auth.AccessKey = os.Getenv("AWS_ACCESS_KEY")
	}

	auth.SecretKey = os.Getenv("AWS_SECRET_ACCESS_KEY")
	if auth.SecretKey == "" {
		auth.SecretKey = os.Getenv("AWS_SECRET_KEY")
	}
	if auth.AccessKey == "" {
		err = errors.New("AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY not found in environment")
	}
	if auth.SecretKey == "" {
		err = errors.New("AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY not found in environment")
	}
	return
}

// CredentialFileAuth creates and Auth based on a credentials file. The file
// contains various authentication profiles for use with AWS.
//
// The credentials file, which is used by other AWS SDKs, is documented at
// http://blogs.aws.amazon.com/security/post/Tx3D6U6WSFGOK2H/A-New-and-Standardized-Way-to-Manage-Credentials-in-the-AWS-SDKs
func CredentialFileAuth(filePath string, profile string, expiration time.Duration) (auth Auth, err error) {
	if profile == "" {
		profile = "default"
	}

	if filePath == "" {
		u, err := user.Current()
		if err != nil {
			return auth, err
		}

		filePath = path.Join(u.HomeDir, ".aws", "credentials")
	}

	// read the file, then parse the INI
	contents, err := ioutil.ReadFile(filePath)
	if err != nil {
		return
	}

	profiles := parseINI(string(contents))
	profileData, ok := profiles[profile]

	if !ok {
		err = errors.New("The credentials file did not contain the profile")
		return
	}

	keyId, ok := profileData["aws_access_key_id"]
	if !ok {
		err = errors.New("The credentials file did not contain required attribute aws_access_key_id")
		return
	}

	secretKey, ok := profileData["aws_secret_access_key"]
	if !ok {
		err = errors.New("The credentials file did not contain required attribute aws_secret_access_key")
		return
	}

	auth.AccessKey = keyId
	auth.SecretKey = secretKey

	if token, ok := profileData["aws_session_token"]; ok {
		auth.token = token
	}

	auth.expiration = time.Now().Add(expiration)

	return
}

// parseINI takes the contents of a credentials file and returns a map, whose keys
// are the various profiles, and whose values are maps of the settings for the
// profiles
func parseINI(fileContents string) map[string]map[string]string {
	profiles := make(map[string]map[string]string)

	lines := strings.Split(fileContents, "\n")

	var currentSection map[string]string
	for _, line := range lines {
		// remove comments, which start with a semi-colon
		if split := strings.Split(line, ";"); len(split) > 1 {
			line = split[0]
		}

		// check if the line is the start of a profile.
		//
		// for example:
		//     [default]
		//
		// otherwise, check for the proper setting
		//     property=value
		if sectMatch := iniSectionRegexp.FindStringSubmatch(line); len(sectMatch) == 2 {
			currentSection = make(map[string]string)
			profiles[sectMatch[1]] = currentSection
		} else if setMatch := iniSettingRegexp.FindStringSubmatch(line); len(setMatch) == 3 && currentSection != nil {
			currentSection[setMatch[1]] = setMatch[2]
		}
	}

	return profiles
}

// Encode takes a string and URI-encodes it in a way suitable
// to be used in AWS signatures.
func Encode(s string) string {
	encode := false
	for i := 0; i != len(s); i++ {
		c := s[i]
		if c > 127 || !unreserved[c] {
			encode = true
			break
		}
	}
	if !encode {
		return s
	}
	e := make([]byte, len(s)*3)
	ei := 0
	for i := 0; i != len(s); i++ {
		c := s[i]
		if c > 127 || !unreserved[c] {
			e[ei] = '%'
			e[ei+1] = hex[c>>4]
			e[ei+2] = hex[c&0xF]
			ei += 3
		} else {
			e[ei] = c
			ei += 1
		}
	}
	return string(e[:ei])
}

func dialTimeout(network, addr string) (net.Conn, error) {
	return net.DialTimeout(network, addr, time.Duration(2*time.Second))
}

func AvailabilityZone() string {
	transport := http.Transport{Dial: dialTimeout}
	client := http.Client{
		Transport: &transport,
	}
	resp, err := client.Get("http://169.254.169.254/latest/meta-data/placement/availability-zone")
	if err != nil {
		return "unknown"
	} else {
		defer resp.Body.Close()
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return "unknown"
		} else {
			return string(body)
		}
	}
}

func InstanceRegion() string {
	az := AvailabilityZone()
	if az == "unknown" {
		return az
	} else {
		region := az[:len(az)-1]
		return region
	}
}

func InstanceId() string {
	transport := http.Transport{Dial: dialTimeout}
	client := http.Client{
		Transport: &transport,
	}
	resp, err := client.Get("http://169.254.169.254/latest/meta-data/instance-id")
	if err != nil {
		return "unknown"
	} else {
		defer resp.Body.Close()
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return "unknown"
		} else {
			return string(body)
		}
	}
}

func InstanceType() string {
	transport := http.Transport{Dial: dialTimeout}
	client := http.Client{
		Transport: &transport,
	}
	resp, err := client.Get("http://169.254.169.254/latest/meta-data/instance-type")
	if err != nil {
		return "unknown"
	} else {
		defer resp.Body.Close()
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return "unknown"
		} else {
			return string(body)
		}
	}
}

func ServerLocalIp() string {
	transport := http.Transport{Dial: dialTimeout}
	client := http.Client{
		Transport: &transport,
	}
	resp, err := client.Get("http://169.254.169.254/latest/meta-data/local-ipv4")
	if err != nil {
		return "127.0.0.1"
	} else {
		defer resp.Body.Close()
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return "127.0.0.1"
		} else {
			return string(body)
		}
	}
}

func ServerPublicIp() string {
	transport := http.Transport{Dial: dialTimeout}
	client := http.Client{
		Transport: &transport,
	}
	resp, err := client.Get("http://169.254.169.254/latest/meta-data/public-ipv4")
	if err != nil {
		return "127.0.0.1"
	} else {
		defer resp.Body.Close()
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return "127.0.0.1"
		} else {
			return string(body)
		}
	}
}


================================================
FILE: vendor/github.com/zackbloom/goamz/aws/client.go
================================================
package aws

import (
	"math"
	"net"
	"net/http"
	"time"
)

type RetryableFunc func(*http.Request, *http.Response, error) bool
type WaitFunc func(try int)
type DeadlineFunc func() time.Time

type ResilientTransport struct {
	// Timeout is the maximum amount of time a dial will wait for
	// a connect to complete.
	//
	// The default is no timeout.
	//
	// With or without a timeout, the operating system may impose
	// its own earlier timeout. For instance, TCP timeouts are
	// often around 3 minutes.
	DialTimeout time.Duration

	// MaxTries, if non-zero, specifies the number of times we will retry on
	// failure. Retries are only attempted for temporary network errors or known
	// safe failures.
	MaxTries    int
	Deadline    DeadlineFunc
	ShouldRetry RetryableFunc
	Wait        WaitFunc
	transport   *http.Transport
}

// Convenience method for creating an http client
func NewClient(rt *ResilientTransport) *http.Client {
	rt.transport = &http.Transport{
		Dial: func(netw, addr string) (net.Conn, error) {
			c, err := net.DialTimeout(netw, addr, rt.DialTimeout)
			if err != nil {
				return nil, err
			}
			c.SetDeadline(rt.Deadline())
			return c, nil
		},
		Proxy: http.ProxyFromEnvironment,
	}
	// TODO: Would be nice is ResilientTransport allowed clients to initialize
	// with http.Transport attributes.
	return &http.Client{
		Transport: rt,
	}
}

var retryingTransport = &ResilientTransport{
	Deadline: func() time.Time {
		return time.Now().Add(5 * time.Second)
	},
	DialTimeout: 10 * time.Second,
	MaxTries:    3,
	ShouldRetry: awsRetry,
	Wait:        ExpBackoff,
}

// Exported default client
var RetryingClient = NewClient(retryingTransport)

func (t *ResilientTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	return t.tries(req)
}

// Retry a request a maximum of t.MaxTries times.
// We'll only retry if the proper criteria are met.
// If a wait function is specified, wait that amount of time
// In between requests.
func (t *ResilientTransport) tries(req *http.Request) (res *http.Response, err error) {
	for try := 0; try < t.MaxTries; try += 1 {
		res, err = t.transport.RoundTrip(req)

		if !t.ShouldRetry(req, res, err) {
			break
		}
		if res != nil {
			res.Body.Close()
		}
		if t.Wait != nil {
			t.Wait(try)
		}
	}

	return
}

func ExpBackoff(try int) {
	time.Sleep(100 * time.Millisecond *
		time.Duration(math.Exp2(float64(try))))
}

func LinearBackoff(try int) {
	time.Sleep(time.Duration(try*100) * time.Millisecond)
}

// Decide if we should retry a request.
// In general, the criteria for retrying a request is described here
// http://docs.aws.amazon.com/general/latest/gr/api-retries.html
func awsRetry(req *http.Request, res *http.Response, err error) bool {
	retry := false

	// Retry if there's a temporary network error.
	if neterr, ok := err.(net.Error); ok {
		if neterr.Temporary() {
			retry = true
		}
	}

	// Retry if we get a 5xx series error.
	if res != nil {
		if res.StatusCode >= 500 && res.StatusCode < 600 {
			retry = true
		}
	}

	return retry
}


================================================
FILE: vendor/github.com/zackbloom/goamz/aws/regions.go
================================================
package aws

var USGovWest = Region{
	"us-gov-west-1",
	"https://ec2.us-gov-west-1.amazonaws.com",
	"https://s3-fips-us-gov-west-1.amazonaws.com",
	"",
	true,
	true,
	"",
	"https://sns.us-gov-west-1.amazonaws.com",
	"https://sqs.us-gov-west-1.amazonaws.com",
	"",
	"https://iam.us-gov.amazonaws.com",
	"https://elasticloadbalancing.us-gov-west-1.amazonaws.com",
	"https://dynamodb.us-gov-west-1.amazonaws.com",
	ServiceInfo{"https://monitoring.us-gov-west-1.amazonaws.com", V2Signature},
	"https://autoscaling.us-gov-west-1.amazonaws.com",
	ServiceInfo{"https://rds.us-gov-west-1.amazonaws.com", V2Signature},
	"",
	"https://sts.amazonaws.com",
	"https://cloudformation.us-gov-west-1.amazonaws.com",
	"",
}

var USEast = Region{
	"us-east-1",
	"https://ec2.us-east-1.amazonaws.com",
	"https://s3.amazonaws.com",
	"",
	false,
	false,
	"https://sdb.amazonaws.com",
	"https://sns.us-east-1.amazonaws.com",
	"https://sqs.us-east-1.amazonaws.com",
	"https://email.us-east-1.amazonaws.com",
	"https://iam.amazonaws.com",
	"https://elasticloadbalancing.us-east-1.amazonaws.com",
	"https://dynamodb.us-east-1.amazonaws.com",
	ServiceInfo{"https://monitoring.us-east-1.amazonaws.com", V2Signature},
	"https://autoscaling.us-east-1.amazonaws.com",
	ServiceInfo{"https://rds.us-east-1.amazonaws.com", V2Signature},
	"https://kinesis.us-east-1.amazonaws.com",
	"https://sts.amazonaws.com",
	"https://cloudformation.us-east-1.amazonaws.com",
	"https://elasticache.us-east-1.amazonaws.com",
}

var USWest = Region{
	"us-west-1",
	"https://ec2.us-west-1.amazonaws.com",
	"https://s3-us-west-1.amazonaws.com",
	"",
	true,
	true,
	"https://sdb.us-west-1.amazonaws.com",
	"https://sns.us-west-1.amazonaws.com",
	"https://sqs.us-west-1.amazonaws.com",
	"",
	"https://iam.amazonaws.com",
	"https://elasticloadbalancing.us-west-1.amazonaws.com",
	"https://dynamodb.us-west-1.amazonaws.com",
	ServiceInfo{"https://monitoring.us-west-1.amazonaws.com", V2Signature},
	"https://autoscaling.us-west-1.amazonaws.com",
	ServiceInfo{"https://rds.us-west-1.amazonaws.com", V2Signature},
	"https://kinesis.us-west-1.amazonaws.com",
	"https://sts.amazonaws.com",
	"https://cloudformation.us-west-1.amazonaws.com",
	"https://elasticache.us-west-1.amazonaws.com",
}

var USWest2 = Region{
	"us-west-2",
	"https://ec2.us-west-2.amazonaws.com",
	"https://s3-us-west-2.amazonaws.com",
	"",
	true,
	true,
	"https://sdb.us-west-2.amazonaws.com",
	"https://sns.us-west-2.amazonaws.com",
	"https://sqs.us-west-2.amazonaws.com",
	"https://email.us-west-2.amazonaws.com",
	"https://iam.amazonaws.com",
	"https://elasticloadbalancing.us-west-2.amazonaws.com",
	"https://dynamodb.us-west-2.amazonaws.com",
	ServiceInfo{"https://monitoring.us-west-2.amazonaws.com", V2Signature},
	"https://autoscaling.us-west-2.amazonaws.com",
	ServiceInfo{"https://rds.us-west-2.amazonaws.com", V2Signature},
	"https://kinesis.us-west-2.amazonaws.com",
	"https://sts.amazonaws.com",
	"https://cloudformation.us-west-2.amazonaws.com",
	"https://elasticache.us-west-2.amazonaws.com",
}

var EUWest = Region{
	"eu-west-1",
	"https://ec2.eu-west-1.amazonaws.com",
	"https://s3-eu-west-1.amazonaws.com",
	"",
	true,
	true,
	"https://sdb.eu-west-1.amazonaws.com",
	"https://sns.eu-west-1.amazonaws.com",
	"https://sqs.eu-west-1.amazonaws.com",
	"https://email.eu-west-1.amazonaws.com",
	"https://iam.amazonaws.com",
	"https://elasticloadbalancing.eu-west-1.amazonaws.com",
	"https://dynamodb.eu-west-1.amazonaws.com",
	ServiceInfo{"https://monitoring.eu-west-1.amazonaws.com", V2Signature},
	"https://autoscaling.eu-west-1.amazonaws.com",
	ServiceInfo{"https://rds.eu-west-1.amazonaws.com", V2Signature},
	"https://kinesis.eu-west-1.amazonaws.com",
	"https://sts.amazonaws.com",
	"https://cloudformation.eu-west-1.amazonaws.com",
	"https://elasticache.eu-west-1.amazonaws.com",
}

var EUCentral = Region{
	"eu-central-1",
	"https://ec2.eu-central-1.amazonaws.com",
	"https://s3-eu-central-1.amazonaws.com",
	"",
	true,
	true,
	"https://sdb.eu-central-1.amazonaws.com",
	"https://sns.eu-central-1.amazonaws.com",
	"https://sqs.eu-central-1.amazonaws.com",
	"",
	"https://iam.amazonaws.com",
	"https://elasticloadbalancing.eu-central-1.amazonaws.com",
	"https://dynamodb.eu-central-1.amazonaws.com",
	ServiceInfo{"https://monitoring.eu-central-1.amazonaws.com", V2Signature},
	"https://autoscaling.eu-central-1.amazonaws.com",
	ServiceInfo{"https://rds.eu-central-1.amazonaws.com", V2Signature},
	"https://kinesis.eu-central-1.amazonaws.com",
	"https://sts.amazonaws.com",
	"https://cloudformation.eu-central-1.amazonaws.com",
	"",
}

var APSoutheast = Region{
	"ap-southeast-1",
	"https://ec2.ap-southeast-1.amazonaws.com",
	"https://s3-ap-southeast-1.amazonaws.com",
	"",
	true,
	true,
	"https://sdb.ap-southeast-1.amazonaws.com",
	"https://sns.ap-southeast-1.amazonaws.com",
	"https://sqs.ap-southeast-1.amazonaws.com",
	"",
	"https://iam.amazonaws.com",
	"https://elasticloadbalancing.ap-southeast-1.amazonaws.com",
	"https://dynamodb.ap-southeast-1.amazonaws.com",
	ServiceInfo{"https://monitoring.ap-southeast-1.amazonaws.com", V2Signature},
	"https://autoscaling.ap-southeast-1.amazonaws.com",
	ServiceInfo{"https://rds.ap-southeast-1.amazonaws.com", V2Signature},
	"https://kinesis.ap-southeast-1.amazonaws.com",
	"https://sts.amazonaws.com",
	"https://cloudformation.ap-southeast-1.amazonaws.com",
	"https://elasticache.ap-southeast-1.amazonaws.com",
}

var APSoutheast2 = Region{
	"ap-southeast-2",
	"https://ec2.ap-southeast-2.amazonaws.com",
	"https://s3-ap-southeast-2.amazonaws.com",
	"",
	true,
	true,
	"https://sdb.ap-southeast-2.amazonaws.com",
	"https://sns.ap-southeast-2.amazonaws.com",
	"https://sqs.ap-southeast-2.amazonaws.com",
	"",
	"https://iam.amazonaws.com",
	"https://elasticloadbalancing.ap-southeast-2.amazonaws.com",
	"https://dynamodb.ap-southeast-2.amazonaws.com",
	ServiceInfo{"https://monitoring.ap-southeast-2.amazonaws.com", V2Signature},
	"https://autoscaling.ap-southeast-2.amazonaws.com",
	ServiceInfo{"https://rds.ap-southeast-2.amazonaws.com", V2Signature},
	"https://kinesis.ap-southeast-2.amazonaws.com",
	"https://sts.amazonaws.com",
	"https://cloudformation.ap-southeast-2.amazonaws.com",
	"https://elasticache.ap-southeast-2.amazonaws.com",
}

var APNortheast = Region{
	"ap-northeast-1",
	"https://ec2.ap-northeast-1.amazonaws.com",
	"https://s3-ap-northeast-1.amazonaws.com",
	"",
	true,
	true,
	"https://sdb.ap-northeast-1.amazonaws.com",
	"https://sns.ap-northeast-1.amazonaws.com",
	"https://sqs.ap-northeast-1.amazonaws.com",
	"",
	"https://iam.amazonaws.com",
	"https://elasticloadbalancing.ap-northeast-1.amazonaws.com",
	"https://dynamodb.ap-northeast-1.amazonaws.com",
	ServiceInfo{"https://monitoring.ap-northeast-1.amazonaws.com", V2Signature},
	"https://autoscaling.ap-northeast-1.amazonaws.com",
	ServiceInfo{"https://rds.ap-northeast-1.amazonaws.com", V2Signature},
	"https://kinesis.ap-northeast-1.amazonaws.com",
	"https://sts.amazonaws.com",
	"https://cloudformation.ap-northeast-1.amazonaws.com",
	"https://elasticache.ap-northeast-1.amazonaws.com",
}

var SAEast = Region{
	"sa-east-1",
	"https://ec2.sa-east-1.amazonaws.com",
	"https://s3-sa-east-1.amazonaws.com",
	"",
	true,
	true,
	"https://sdb.sa-east-1.amazonaws.com",
	"https://sns.sa-east-1.amazonaws.com",
	"https://sqs.sa-east-1.amazonaws.com",
	"",
	"https://iam.amazonaws.com",
	"https://elasticloadbalancing.sa-east-1.amazonaws.com",
	"https://dynamodb.sa-east-1.amazonaws.com",
	ServiceInfo{"https://monitoring.sa-east-1.amazonaws.com", V2Signature},
	"https://autoscaling.sa-east-1.amazonaws.com",
	ServiceInfo{"https://rds.sa-east-1.amazonaws.com", V2Signature},
	"",
	"https://sts.amazonaws.com",
	"https://cloudformation.sa-east-1.amazonaws.com",
	"https://elasticache.sa-east-1.amazonaws.com",
}


================================================
FILE: vendor/github.com/zackbloom/goamz/aws/retry.go
================================================
package aws

import (
	"math/rand"
	"net"
	"net/http"
	"time"
)

const (
	maxDelay             = 20 * time.Second
	defaultScale         = 300 * time.Millisecond
	throttlingScale      = 500 * time.Millisecond
	throttlingScaleRange = throttlingScale / 4
	defaultMaxRetries    = 3
	dynamoDBScale        = 25 * time.Millisecond
	dynamoDBMaxRetries   = 10
)

// A RetryPolicy encapsulates a strategy for implementing client retries.
//
// Default implementations are provided which match the AWS SDKs.
type RetryPolicy interface {
	// ShouldRetry returns whether a client should retry a failed request.
	ShouldRetry(target string, r *http.Response, err error, numRetries int) bool

	// Delay returns the time a client should wait before issuing a retry.
	Delay(target string, r *http.Response, err error, numRetries int) time.Duration
}

// DefaultRetryPolicy implements the AWS SDK default retry policy.
//
// It will retry up to 3 times, and uses an exponential backoff with a scale
// factor of 300ms (300ms, 600ms, 1200ms). If the retry is because of
// throttling, the delay will also include some randomness.
//
// See https://github.com/aws/aws-sdk-java/blob/master/aws-java-sdk-core/src/main/java/com/amazonaws/retry/PredefinedRetryPolicies.java#L90.
type DefaultRetryPolicy struct {
}

// ShouldRetry implements the RetryPolicy ShouldRetry method.
func (policy DefaultRetryPolicy) ShouldRetry(target string, r *http.Response, err error, numRetries int) bool {
	return shouldRetry(r, err, numRetries, defaultMaxRetries)
}

// Delay implements the RetryPolicy Delay method.
func (policy DefaultRetryPolicy) Delay(target string, r *http.Response, err error, numRetries int) time.Duration {
	scale := defaultScale
	if err, ok := err.(*Error); ok && isThrottlingException(err) {
		scale = throttlingScale + time.Duration(rand.Int63n(int64(throttlingScaleRange)))
	}
	return exponentialBackoff(numRetries, scale)
}

// DynamoDBRetryPolicy implements the AWS SDK DynamoDB retry policy.
//
// It will retry up to 10 times, and uses an exponential backoff with a scale
// factor of 25ms (25ms, 50ms, 100ms, ...).
//
// See https://github.com/aws/aws-sdk-java/blob/master/aws-java-sdk-core/src/main/java/com/amazonaws/retry/PredefinedRetryPolicies.java#L103.
type DynamoDBRetryPolicy struct {
}

// ShouldRetry implements the RetryPolicy ShouldRetry method.
func (policy DynamoDBRetryPolicy) ShouldRetry(target string, r *http.Response, err error, numRetries int) bool {
	return shouldRetry(r, err, numRetries, dynamoDBMaxRetries)
}

// Delay implements the RetryPolicy Delay method.
func (policy DynamoDBRetryPolicy) Delay(target string, r *http.Response, err error, numRetries int) time.Duration {
	return exponentialBackoff(numRetries, dynamoDBScale)
}

// NeverRetryPolicy never retries requests and returns immediately on failure.
type NeverRetryPolicy struct {
}

// ShouldRetry implements the RetryPolicy ShouldRetry method.
func (policy NeverRetryPolicy) ShouldRetry(target string, r *http.Response, err error, numRetries int) bool {
	return false
}

// Delay implements the RetryPolicy Delay method.
func (policy NeverRetryPolicy) Delay(target string, r *http.Response, err error, numRetries int) time.Duration {
	return time.Duration(0)
}

// shouldRetry determines if we should retry the request.
//
// See http://docs.aws.amazon.com/general/latest/gr/api-retries.html.
func shouldRetry(r *http.Response, err error, numRetries int, maxRetries int) bool {
	// Once we've exceeded the max retry attempts, game over.
	if numRetries >= maxRetries {
		return false
	}

	// Always retry temporary network errors.
	if err, ok := err.(net.Error); ok && err.Temporary() {
		return true
	}

	// Always retry 5xx responses.
	if r != nil && r.StatusCode >= 500 {
		return true
	}

	// Always retry throttling exceptions.
	if err, ok := err.(ServiceError); ok && isThrottlingException(err) {
		return true
	}

	// Other classes of failures indicate a problem with the request. Retrying
	// won't help.
	return false
}

func exponentialBackoff(numRetries int, scale time.Duration) time.Duration {
	if numRetries < 0 {
		return time.Duration(0)
	}

	delay := (1 << uint(numRetries)) * scale
	if delay > maxDelay {
		return maxDelay
	}
	return delay
}

func isThrottlingException(err ServiceError) bool {
	switch err.ErrorCode() {
	case "Throttling", "ThrottlingException", "ProvisionedThroughputExceededException":
		return true
	default:
		return false
	}
}


================================================
FILE: vendor/github.com/zackbloom/goamz/aws/sign.go
================================================
package aws

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"path"
	"sort"
	"strings"
	"time"
)

type V2Signer struct {
	auth    Auth
	service ServiceInfo
	host    string
}

var b64 = base64.StdEncoding

func NewV2Signer(auth Auth, service ServiceInfo) (*V2Signer, error) {
	u, err := url.Parse(service.Endpoint)
	if err != nil {
		return nil, err
	}
	return &V2Signer{auth: auth, service: service, host: u.Host}, nil
}

func (s *V2Signer) Sign(method, path string, params map[string]string) {
	params["AWSAccessKeyId"] = s.auth.AccessKey
	params["SignatureVersion"] = "2"
	params["SignatureMethod"] = "HmacSHA256"
	if s.auth.Token() != "" {
		params["SecurityToken"] = s.auth.Token()
	}

	// AWS specifies that the parameters in a signed request must
	// be provided in the natural order of the keys. This is distinct
	// from the natural order of the encoded value of key=value.
	// Percent and gocheck.Equals affect the sorting order.
	var keys, sarray []string
	for k, _ := range params {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	for _, k := range keys {
		sarray = append(sarray, Encode(k)+"="+Encode(params[k]))
	}
	joined := strings.Join(sarray, "&")
	payload := method + "\n" + s.host + "\n" + path + "\n" + joined
	hash := hmac.New(sha256.New, []byte(s.auth.SecretKey))
	hash.Write([]byte(payload))
	signature := make([]byte, b64.EncodedLen(hash.Size()))
	b64.Encode(signature, hash.Sum(nil))

	params["Signature"] = string(signature)
}

// Common date formats for signing requests
const (
	ISO8601BasicFormat      = "20060102T150405Z"
	ISO8601BasicFormatShort = "20060102"
)

type Route53Signer struct {
	auth Auth
}

func NewRoute53Signer(auth Auth) *Route53Signer {
	return &Route53Signer{auth: auth}
}

// getCurrentDate fetches the date stamp from the aws servers to
// ensure the auth headers are within 5 minutes of the server time
func (s *Route53Signer) getCurrentDate() string {
	response, err := http.Get("https://route53.amazonaws.com/date")
	if err != nil {
		fmt.Print("Unable to get date from amazon: ", err)
		return ""
	}

	response.Body.Close()
	return response.Header.Get("Date")
}

// Creates the authorize signature based on the date stamp and secret key
func (s *Route53Signer) getHeaderAuthorize(message string) string {
	hmacSha256 := hmac.New(sha256.New, []byte(s.auth.SecretKey))
	hmacSha256.Write([]byte(message))
	cryptedString := hmacSha256.Sum(nil)

	return base64.StdEncoding.EncodeToString(cryptedString)
}

// Adds all the required headers for AWS Route53 API to the request
// including the authorization
func (s *Route53Signer) Sign(req *http.Request) {
	date := s.getCurrentDate()
	authHeader := fmt.Sprintf("AWS3-HTTPS AWSAccessKeyId=%s,Algorithm=%s,Signature=%s",
		s.auth.AccessKey, "HmacSHA256", s.getHeaderAuthorize(date))

	req.Header.Set("Host", req.Host)
	req.Header.Set("X-Amzn-Authorization", authHeader)
	req.Header.Set("X-Amz-Date", date)
	req.Header.Set("Content-Type", "application/xml")
	if s.auth.Token() != "" {
		req.Header.Set("X-Amzn-Security-Token", s.auth.Token())
	}
}

/*
The V4Signer encapsulates all of the functionality to sign a request with the AWS
Signature Version 4 Signing Process. (http://goo.gl/u1OWZz)
*/
type V4Signer struct {
	auth        Auth
	serviceName string
	region      Region
	// Add the x-amz-content-sha256 header
	IncludeXAmzContentSha256 bool
}

/*
Return a new instance of a V4Signer capable of signing AWS requests.
*/
func NewV4Signer(auth Auth, serviceName string, region Region) *V4Signer {
	return &V4Signer{
		auth:        auth,
		serviceName: serviceName,
		region:      region,
		IncludeXAmzContentSha256: false,
	}
}

/*
Sign a request according to the AWS Signature Version 4 Signing Process. (http://goo.gl/u1OWZz)

The signed request will include an "x-amz-date" header with a current timestamp if a valid "x-amz-date"
or "date" header was not available in the original request. In addition, AWS Signature Version 4 requires
the "host" header to be a signed header, therefor the Sign method will manually set a "host" header from
the request.Host.

The signed request will include a new "Authorization" header indicating that the request has been signed.

Any changes to the request after signing the request will invalidate the signature.
*/
func (s *V4Signer) Sign(req *http.Request) {
	req.Header.Set("host", req.Host) // host header must be included as a signed header
	t := s.requestTime(req)          // Get request time

	payloadHash := ""

	if _, ok := req.Form["X-Amz-Expires"]; ok {
		// We are authenticating the the request by using query params
		// (also known as pre-signing a url, http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html)
		payloadHash = "UNSIGNED-PAYLOAD"
		req.Header.Del("x-amz-date")

		req.Form["X-Amz-SignedHeaders"] = []string{s.signedHeaders(req.Header)}
		req.Form["X-Amz-Algorithm"] = []string{"AWS4-HMAC-SHA256"}
		req.Form["X-Amz-Credential"] = []string{s.auth.AccessKey + "/" + s.credentialScope(t)}
		req.Form["X-Amz-Date"] = []string{t.Format(ISO8601BasicFormat)}
		req.URL.RawQuery = req.Form.Encode()
	} else {
		payloadHash = s.payloadHash(req)
		if s.IncludeXAmzContentSha256 {
			req.Header.Set("x-amz-content-sha256", payloadHash) // x-amz-content-sha256 contains the payload hash
		}
	}
	creq := s.canonicalRequest(req, payloadHash)      // Build canonical request
	sts := s.stringToSign(t, creq)                    // Build string to sign
	signature := s.signature(t, sts)                  // Calculate the AWS Signature Version 4
	auth := s.authorization(req.Header, t, signature) // Create Authorization header value

	if _, ok := req.Form["X-Amz-Expires"]; ok {
		req.Form["X-Amz-Signature"] = []string{signature}
	} else {
		req.Header.Set("Authorization", auth) // Add Authorization header to request
	}
	return
}

/*
requestTime method will parse the time from the request "x-amz-date" or "date" headers.
If the "x-amz-date" header is present, that will take priority over the "date" header.
If neither header is defined or we are unable to parse either header as a valid date
then we will create a new "x-amz-date" header with the current time.
*/
func (s *V4Signer) requestTime(req *http.Request) time.Time {

	// Get "x-amz-date" header
	date := req.Header.Get("x-amz-date")

	// Attempt to parse as ISO8601BasicFormat
	t, err := time.Parse(ISO8601BasicFormat, date)
	if err == nil {
		return t
	}

	// Attempt to parse as http.TimeFormat
	t, err = time.Parse(http.TimeFormat, date)
	if err == nil {
		req.Header.Set("x-amz-date", t.Format(ISO8601BasicFormat))
		return t
	}

	// Get "date" header
	date = req.Header.Get("date")

	// Attempt to parse as http.TimeFormat
	t, err = time.Parse(http.TimeFormat, date)
	if err == nil {
		return t
	}

	// Create a current time header to be used
	t = time.Now().UTC()
	req.Header.Set("x-amz-date", t.Format(ISO8601BasicFormat))
	return t
}

/*
canonicalRequest method creates the canonical request according to Task 1 of the AWS Signature Version 4 Signing Process. (http://goo.gl/eUUZ3S)

    CanonicalRequest =
      HTTPRequestMethod + '\n' +
      CanonicalURI + '\n' +
      CanonicalQueryString + '\n' +
      CanonicalHeaders + '\n' +
      SignedHeaders + '\n' +
      HexEncode(Hash(Payload))

payloadHash is optional; use the empty string and it will be calculated from the request
*/
func (s *V4Signer) canonicalRequest(req *http.Request, payloadHash string) string {
	if payloadHash == "" {
		payloadHash = s.payloadHash(req)
	}
	c := new(bytes.Buffer)
	fmt.Fprintf(c, "%s\n", req.Method)
	fmt.Fprintf(c, "%s\n", s.canonicalURI(req.URL))
	fmt.Fprintf(c, "%s\n", s.canonicalQueryString(req.URL))
	fmt.Fprintf(c, "%s\n\n", s.canonicalHeaders(req.Header))
	fmt.Fprintf(c, "%s\n", s.signedHeaders(req.Header))
	fmt.Fprintf(c, "%s", payloadHash)
	return c.String()
}

func (s *V4Signer) canonicalURI(u *url.URL) string {
	u = &url.URL{Path: u.Path}
	canonicalPath := u.String()

	slash := strings.HasSuffix(canonicalPath, "/")
	canonicalPath = path.Clean(canonicalPath)

	if canonicalPath == "" || canonicalPath == "." {
		canonicalPath = "/"
	}

	if canonicalPath != "/" && slash {
		canonicalPath += "/"
	}

	return canonicalPath
}

func (s *V4Signer) canonicalQueryString(u *url.URL) string {
	var a []string
	for k, vs := range u.Query() {
		k = url.QueryEscape(k)
		for _, v := range vs {
			if v == "" {
				a = append(a, k+"=")
			} else {
				v = url.QueryEscape(v)
				a = append(a, k+"="+v)
			}
		}
	}
	sort.Strings(a)
	return strings.Join(a, "&")
}

func (s *V4Signer) canonicalHeaders(h http.Header) string {
	i, a, lowerCase := 0, make([]string, len(h)), make(map[string][]string)

	for k, v := range h {
		lowerCase[strings.ToLower(k)] = v
	}

	var keys []string
	for k := range lowerCase {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	for _, k := range keys {
		v := lowerCase[k]
		for j, w := range v {
			v[j] = strings.Trim(w, " ")
		}
		sort.Strings(v)
		a[i] = strings.ToLower(k) + ":" + strings.Join(v, ",")
		i++
	}
	return strings.Join(a, "\n")
}

func (s *V4Signer) signedHeaders(h http.Header) string {
	i, a := 0, make([]string, len(h))
	for k, _ := range h {
		a[i] = strings.ToLower(k)
		i++
	}
	sort.Strings(a)
	return strings.Join(a, ";")
}

func (s *V4Signer) payloadHash(req *http.Request) string {
	var b []byte
	if req.Body == nil {
		b = []byte("")
	} else {
		var err error
		b, err = ioutil.ReadAll(req.Body)
		if err != nil {
			// TODO: I REALLY DON'T LIKE THIS PANIC!!!!
			panic(err)
		}
	}
	req.Body = ioutil.NopCloser(bytes.NewBuffer(b))
	return s.hash(string(b))
}

/*
stringToSign method creates the string to sign accorting to Task 2 of the AWS Signature Version 4 Signing Process. (http://goo.gl/es1PAu)

    StringToSign  =
      Algorithm + '\n' +
      RequestDate + '\n' +
      CredentialScope + '\n' +
      HexEncode(Hash(CanonicalRequest))
*/
func (s *V4Signer) stringToSign(t time.Time, creq string) string {
	w := new(bytes.Buffer)
	fmt.Fprint(w, "AWS4-HMAC-SHA256\n")
	fmt.Fprintf(w, "%s\n", t.Format(ISO8601BasicFormat))
	fmt.Fprintf(w, "%s\n", s.credentialScope(t))
	fmt.Fprintf(w, "%s", s.hash(creq))
	return w.String()
}

func (s *V4Signer) credentialScope(t time.Time) string {
	return fmt.Sprintf("%s/%s/%s/aws4_request", t.Format(ISO8601BasicFormatShort), s.region.Name, s.serviceName)
}

/*
signature method calculates the AWS Signature Version 4 according to Task 3 of the AWS Signature Version 4 Signing Process. (http://goo.gl/j0Yqe1)

	signature = HexEncode(HMAC(derived-signing-key, string-to-sign))
*/
func (s *V4Signer) signature(t time.Time, sts string) string {
	h := s.hmac(s.derivedKey(t), []byte(sts))
	return fmt.Sprintf("%x", h)
}

/*
derivedKey method derives a signing key to be used for signing a request.

	kSecret = Your AWS Secret Access Key
    kDate = HMAC("AWS4" + kSecret, Date)
    kRegion = HMAC(kDate, Region)
    kService = HMAC(kRegion, Service)
    kSigning = HMAC(kService, "aws4_request")
*/
func (s *V4Signer) derivedKey(t time.Time) []byte {
	h := s.hmac([]byte("AWS4"+s.auth.SecretKey), []byte(t.Format(ISO8601BasicFormatShort)))
	h = s.hmac(h, []byte(s.region.Name))
	h = s.hmac(h, []byte(s.serviceName))
	h = s.hmac(h, []byte("aws4_request"))
	return h
}

/*
authorization method generates the authorization header value.
*/
func (s *V4Signer) authorization(header http.Header, t time.Time, signature string) string {
	w := new(bytes.Buffer)
	fmt.Fprint(w, "AWS4-HMAC-SHA256 ")
	fmt.Fprintf(w, "Credential=%s/%s, ", s.auth.AccessKey, s.credentialScope(t))
	fmt.Fprintf(w, "SignedHeaders=%s, ", s.signedHeaders(header))
	fmt.Fprintf(w, "Signature=%s", signature)
	return w.String()
}

// hash method calculates the sha256 hash for a given string
func (s *V4Signer) hash(in string) string {
	h := sha256.New()
	fmt.Fprintf(h, "%s", in)
	return fmt.Sprintf("%x", h.Sum(nil))
}

// hmac method calculates the sha256 hmac for a given slice of bytes
func (s *V4Signer) hmac(key, data []byte) []byte {
	h := hmac.New(sha256.New, key)
	h.Write(data)
	return h.Sum(nil)
}


================================================
FILE: vendor/github.com/zackbloom/goamz/cloudfront/cloudfront.go
================================================
package cloudfront

import (
	"bytes"
	"crypto"
	"crypto/rsa"
	"crypto/sha1"
	"encoding/base64"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"

	"github.com/zackbloom/goamz/aws"
)

const (
	ServiceName = "cloudfront"
	ApiVersion  = "2014-11-06"
)

// TODO Reconcile with 'New' fn below
func NewCloudFront(auth aws.Auth) *CloudFront {
	signer := aws.NewV4Signer(auth, "cloudfront", aws.USEast)

	return &CloudFront{
		Signer: signer,
		Auth:   auth,
	}
}

type CloudFront struct {
	Signer    *aws.V4Signer
	Auth      aws.Auth
	BaseURL   string
	keyPairId string
	key       *rsa.PrivateKey
}

type DistributionConfig struct {
	XMLName              xml.Name `xml:"DistributionConfig"`
	CallerReference      string
	Aliases              Aliases
	DefaultRootObject    string
	Origins              Origins
	DefaultCacheBehavior CacheBehavior
	Comment              string
	CacheBehaviors       CacheBehaviors
	CustomErrorResponses CustomErrorResponses
	Restrictions         *GeoRestriction `xml:"Restrictions>GeoRestriction,omitempty"`
	Logging              Logging
	ViewerCertificate    *ViewerCertificate `xml:",omitempty"`
	PriceClass           string
	Enabled              bool
}

type DistributionSummary struct {
	XMLName xml.Name `xml:"Distribution"`
	DistributionConfig
	DomainName       string
	Status           string
	Id               string
	LastModifiedTime time.Time
}

type Aliases []string

type EncodedAliases struct {
	Quantity int
	Items    []string `xml:"Items>CNAME"`
}

func (a Aliases) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	enc := EncodedAliases{
		Quantity: len(a),
		Items:    []string(a),
	}

	return e.EncodeElement(enc, start)
}

func (n *Aliases) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	enc := EncodedAliases{}
	err := d.DecodeElement(&enc, &start)
	if err != nil {
		return err
	}

	*n = enc.Items
	return nil
}

type CustomErrorResponses []CustomErrorResponse

type EncodedCustomErrorResponses struct {
	Quantity int
	Items    []CustomErrorResponse `xml:"Items>CustomErrorResponse"`
}

func (a CustomErrorResponses) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	enc := EncodedCustomErrorResponses{
		Quantity: len(a),
		Items:    []CustomErrorResponse(a),
	}

	return e.EncodeElement(enc, start)
}

func (n *CustomErrorResponses) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	enc := EncodedCustomErrorResponses{}
	err := d.DecodeElement(&enc, &start)
	if err != nil {
		return err
	}

	*n = enc.Items
	return nil
}

type CacheBehaviors []CacheBehavior

type EncodedCacheBehaviors struct {
	Quantity int
	Items    []CacheBehavior `xml:"Items>CacheBehavior"`
}

func (a CacheBehaviors) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	enc := EncodedCacheBehaviors{
		Quantity: len(a),
		Items:    []CacheBehavior(a),
	}

	return e.EncodeElement(enc, start)
}

func (n *CacheBehaviors) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	enc := EncodedCacheBehaviors{}
	err := d.DecodeElement(&enc, &start)
	if err != nil {
		return err
	}

	*n = enc.Items
	return nil
}

type Logging struct {
	Enabled        bool
	IncludeCookies bool
	Bucket         string
	Prefix         string
}

type ViewerCertificate struct {
	IAMCertificateId             string `xml:",omitempty"`
	CloudFrontDefaultCertificate bool   `xml:",omitempty"`
	SSLSupportMethod             string
	MinimumProtocolVersion       string
}

type GeoRestriction struct {
	RestrictionType string
	Locations       []string
}

type EncodedGeoRestriction struct {
	RestrictionType string
	Quantity        int
	Locations       []string `xml:"Items>Location"`
}

func (a GeoRestriction) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	enc := EncodedGeoRestriction{
		RestrictionType: a.RestrictionType,
		Quantity:        len(a.Locations),
		Locations:       []string(a.Locations),
	}

	return e.EncodeElement(enc, start)
}

func (n *GeoRestriction) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	enc := EncodedGeoRestriction{}
	err := d.DecodeElement(&enc, &start)
	if err != nil {
		return err
	}

	n.Locations = enc.Locations
	n.RestrictionType = enc.RestrictionType
	return nil
}

type CustomErrorResponse struct {
	XMLName            xml.Name `xml:"CustomErrorResponse"`
	ErrorCode          int
	ResponsePagePath   string
	ResponseCode       int
	ErrorCachingMinTTL int
}

type Origin struct {
	XMLName            xml.Name `xml:"Origin"`
	Id                 string
	DomainName         string
	OriginPath         string              `xml:"OriginPath,omitempty"`
	S3OriginConfig     *S3OriginConfig     `xml:",omitempty"`
	CustomOriginConfig *CustomOriginConfig `xml:",omitempty"`
}

type S3OriginConfig struct {
	OriginAccessIdentity string
}

type CustomOriginConfig struct {
	HTTPPort             int
	HTTPSPort            int
	OriginProtocolPolicy string
}

type Origins []Origin

type EncodedOrigins struct {
	Quantity int
	Items    []Origin `xml:"Items>Origin"`
}

func (o Origins) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	enc := EncodedOrigins{
		Quantity: len(o),
		Items:    []Origin(o),
	}

	return e.EncodeElement(enc, start)
}

func (o *Origins) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	enc := EncodedOrigins{}
	err := d.DecodeElement(&enc, &start)
	if err != nil {
		return err
	}

	*o = Origins(enc.Items)
	return nil
}

type CacheBehavior struct {
	TargetOriginId       string
	PathPattern          string `xml:",omitempty"`
	ForwardedValues      ForwardedValues
	TrustedSigners       TrustedSigners
	ViewerProtocolPolicy string
	MinTTL               int
	AllowedMethods       AllowedMethods
	SmoothStreaming      bool
}

type ForwardedValues struct {
	QueryString bool
	Cookies     *Cookies
	Headers     Names
}

type Cookies struct {
	Forward          string
	WhitelistedNames Names
}

var CookiesDefault = Cookies{
	Forward:          "none",
	WhitelistedNames: Names{},
}

func cacheBehaviorDefault(cache *CacheBehavior) {
	if cache.ForwardedValues.Cookies == nil {
		clone := CookiesDefault
		cache.ForwardedValues.Cookies = &clone
	}
}

type Names []string

type EncodedNames struct {
	Quantity int
	Items    []string `xml:"Items>Name"`
}

func (w Names) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	enc := EncodedNames{
		Quantity: len(w),
		Items:    []string(w),
	}

	return e.EncodeElement(enc, start)
}

func (n *Names) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	enc := EncodedNames{}
	err := d.DecodeElement(&enc, &start)
	if err != nil {
		return err
	}

	*n = Names(enc.Items)
	return nil
}

type ItemsList []string

type TrustedSigners struct {
	Enabled           bool
	AWSAccountNumbers []string
}

type EncodedTrustedSigners struct {
	Enabled  bool
	Quantity int
	Items    []string `xml:"Items>AWSAccountNumber"`
}

func (n TrustedSigners) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	enc := EncodedTrustedSigners{
		Enabled:  n.Enabled,
		Quantity: len(n.AWSAccountNumbers),
		Items:    n.AWSAccountNumbers,
	}

	return e.EncodeElement(enc, start)
}

func (n *TrustedSigners) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	enc := EncodedTrustedSigners{}
	err := d.DecodeElement(&enc, &start)
	if err != nil {
		return err
	}

	n.AWSAccountNumbers = enc.Items
	n.Enabled = enc.Enabled
	return nil
}

type AllowedMethods struct {
	Allowed []string `xml:"Items"`
	Cached  []string `xml:"CachedMethods>Items,omitempty"`
}

type EncodedAllowedMethods struct {
	AllowedQuantity int      `xml:"Quantity"`
	Allowed         []string `xml:"Items>Method"`
	CachedQuantity  int      `xml:"CachedMethods>Quantity"`
	Cached          []string `xml:"CachedMethods>Items>Method"`
}

func (n AllowedMethods) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	enc := EncodedAllowedMethods{
		AllowedQuantity: len(n.Allowed),
		Allowed:         n.Allowed,
		CachedQuantity:  len(n.Cached),
		Cached:          n.Cached,
	}

	return e.EncodeElement(enc, start)
}

func (n *AllowedMethods) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	enc := EncodedAllowedMethods{}
	err := d.DecodeElement(&enc, &start)
	if err != nil {
		return err
	}

	n.Allowed = enc.Allowed
	n.Cached = enc.Cached
	return nil
}

var base64Replacer = strings.NewReplacer("=", "_", "+", "-", "/", "~")

func NewKeyLess(auth aws.Auth, baseurl string) *CloudFront {
	return &CloudFront{keyPairId: auth.AccessKey, BaseURL: baseurl}
}

func New(baseurl string, key *rsa.PrivateKey, keyPairId string) *CloudFront {
	return &CloudFront{
		BaseURL:   baseurl,
		keyPairId: keyPairId,
		key:       key,
	}
}

type epochTime struct {
	EpochTime int64 `json:"AWS:EpochTime"`
}

type condition struct {
	DateLessThan epochTime
}

type statement struct {
	Resource  string
	Condition condition
}

type policy struct {
	Statement []statement
}

func buildPolicy(resource string, expireTime time.Time) ([]byte, error) {
	p := &policy{
		Statement: []statement{
			statement{
				Resource: resource,
				Condition: condition{
					DateLessThan: epochTime{
						EpochTime: expireTime.Truncate(time.Millisecond).Unix(),
					},
				},
			},
		},
	}

	return json.Marshal(p)
}

func (cf *CloudFront) generateSignature(policy []byte) (string, error) {
	hash := sha1.New()
	_, err := hash.Write(policy)
	if err != nil {
		return "", err
	}

	hashed := hash.Sum(nil)
	var signed []byte
	if cf.key.Validate() == nil {
		signed, err = rsa.SignPKCS1v15(nil, cf.key, crypto.SHA1, hashed)
		if err != nil {
			return "", err
		}
	} else {
		signed = hashed
	}
	encoded := base64Replacer.Replace(base64.StdEncoding.EncodeToString(signed))

	return encoded, nil
}

// Create a CloudFront distribution
//
// Usage:
//	conf := cloudfront.DistributionConfig{
//    Enabled: true,
//
//		Origins: cloudfront.Origins{
//			cloudfront.Origin{
//				Id:         "test",
//				DomainName: "example.com",
//				CustomOriginConfig: &cloudfront.CustomOriginConfig{
//					HTTPPort:             80,
//					HTTPSPort:            443,
//					OriginProtocolPolicy: "http-only",
//				},
//			},
//		},
//
//		DefaultCacheBehavior: cloudfront.CacheBehavior{
//			TargetOriginId: "test",
//			PathPattern:    "/test",
//			ForwardedValues: cloudfront.ForwardedValues{
//				QueryString: true,
//				Cookies: cloudfront.Cookies{
//					Forward: "whitelist",
//					WhitelistedNames: cloudfront.Names{
//						"cat",
//						"dog",
//					},
//				},
//				Headers: cloudfront.Names{
//					"horse",
//					"pig",
//				},
//			},
//			ViewerProtocolPolicy: "allow-all",
//			MinTTL:               300,
//			AllowedMethods: cloudfront.AllowedMethods{
//				Allowed: []string{"GET", "HEAD"},
//				Cached:  []string{"GET", "HEAD"},
//			},
//		},
//
//		Restrictions: cloudfront.GeoRestriction{
//			RestrictionType: "blacklist",
//			Locations: []string{
//				"CA",
//				"DE",
//			},
//		},
//
//		CustomErrorResponses: cloudfront.CustomErrorResponses{
//			cloudfront.CustomErrorResponse{
//				ErrorCode:        404,
//				ResponseCode:     403,
//				ResponsePagePath: "/index.html",
//			},
//		},
//
//		PriceClass: "PriceClass_All",
//	}
//
//	cf := cloudfront.NewCloudFront(aws.Auth{
//		AccessKey: // ...
//		SecretKey: // ...
//	})
//	cf.CreateDistribution(conf)
func (cf *CloudFront) Create(config DistributionConfig) (summary DistributionSummary, err error) {
	if config.CallerReference == "" {
		config.CallerReference = strconv.FormatInt(time.Now().Unix(), 10)
	}

	cacheBehaviorDefault(&config.DefaultCacheBehavior)
	for i, _ := range config.CacheBehaviors {
		cacheBehaviorDefault(&(config.CacheBehaviors[i]))
	}

	body, err := xml.Marshal(config)
	if err != nil {
		return
	}

	client := http.Client{}
	req, err := http.NewRequest("POST", "https://"+ServiceName+".amazonaws.com/"+ApiVersion+"/distribution", bytes.NewReader(body))
	if err != nil {
		return
	}

	cf.Signer.Sign(req)

	resp, err := client.Do(req)
	if err != nil {
		return
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errors := aws.ErrorResponse{}
		xml.NewDecoder(resp.Body).Decode(&errors)

		err := errors.Errors
		err.RequestId = errors.RequestId
		err.StatusCode = resp.StatusCode
		if err.Message == "" {
			err.Message = resp.Status
		}
		return summary, &err
	} else {
		err = xml.NewDecoder(resp.Body).Decode(&summary)
	}

	return
}

type DistributionItem struct {
	XMLName xml.Name `xml:"DistributionSummary"`
	DistributionSummary
}

type DistributionsResp struct {
	Items       []DistributionItem `xml:"Items>DistributionSummary"`
	IsTruncated bool
	Marker      string

	// Use this to get the next page of results if IsTruncated is true
	NextMarker string

	// Total number in account
	Quantity int
	MaxItems int
}

// Marker is an optional pointer to the NextMarker from the previous page of results
// Max is the maximum number of results to return, max 100
func (cf *CloudFront) List(marker string, max int) (items *DistributionsResp, err error) {
	params := url.Values{
		"MaxItems": []string{strconv.FormatInt(int64(max), 10)},
	}

	if marker != "" {
		params["Marker"] = []string{marker}
	}

	uri, _ := url.Parse("https://" + ServiceName + ".amazonaws.com/" + ApiVersion + "/distribution")
	uri.RawQuery = params.Encode()

	client := http.Client{}
	req, err := http.NewRequest("GET", uri.String(), nil)
	if err != nil {
		return
	}

	cf.Signer.Sign(req)

	resp, err := client.Do(req)
	if err != nil {
		return
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errors := aws.ErrorResponse{}
		xml.NewDecoder(resp.Body).Decode(&errors)

		errors.Errors.RequestId = errors.RequestId
		errors.Errors.StatusCode = resp.StatusCode
		if errors.Errors.Message == "" {
			errors.Errors.Message = resp.Status
		}
		err = &errors.Errors
	} else {
		items = &DistributionsResp{}
		err = xml.NewDecoder(resp.Body).Decode(items)
	}

	return
}

func (cf *CloudFront) FindDistributionByAlias(alias string) (dist *DistributionSummary, err error) {
	marker := ""
	for page := 0; page < 10; page++ {
		var resp *DistributionsResp
		resp, err = cf.List(marker, 100)
		if err != nil {
			return
		}

		if resp.Quantity > 1000 {
			panic("More than 1000 CloudFront distributions in account, not all will be correctly searched")
		}

		var item DistributionItem
		for _, item = range resp.Items {
			for _, _alias := range item.Aliases {
				if _alias == alias {
					dist = &(item.DistributionSummary)
					return
				}
			}
		}

		marker = resp.NextMarker
		if !resp.IsTruncated {
			break
		}
	}

	return
}

// Creates a signed url using RSAwithSHA1 as specified by
// http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-creating-signed-url-canned-policy.html#private-content-canned-policy-creating-signature
func (cf *CloudFront) CannedSignedURL(path, queryString string, expires time.Time) (string, error) {
	resource := cf.BaseURL + path
	if queryString != "" {
		resource = path + "?" + queryString
	}

	policy, err := buildPolicy(resource, expires)
	if err != nil {
		return "", err
	}

	signature, err := cf.generateSignature(policy)
	if err != nil {
		return "", err
	}

	// TOOD: Do this once
	uri, err := url.Parse(cf.BaseURL)
	if err != nil {
		return "", err
	}

	uri.RawQuery = queryString
	if queryString != "" {
		uri.RawQuery += "&"
	}

	expireTime := expires.Truncate(time.Millisecond).Unix()

	uri.Path = path
	uri.RawQuery += fmt.Sprintf("Expires=%d&Signature=%s&Key-Pair-Id=%s", expireTime, signature, cf.keyPairId)

	return uri.String(), nil
}

func (cloudfront *CloudFront) SignedURL(path, querystrings string, expires time.Time) string {
	policy := `{"Statement":[{"Resource":"` + path + "?" + querystrings + `,"Condition":{"DateLessThan":{"AWS:EpochTime":` + strconv.FormatInt(expires.Truncate(time.Millisecond).Unix(), 10) + `}}}]}`

	hash := sha1.New()
	hash.Write([]byte(policy))
	b := hash.Sum(nil)
	he := base64.StdEncoding.EncodeToString(b)

	policySha1 := he

	url := cloudfront.BaseURL + path + "?" + querystrings + "&Expires=" + strconv.FormatInt(expires.Unix(), 10) + "&Signature=" + policySha1 + "&Key-Pair-Id=" + cloudfront.keyPairId

	return url
}


================================================
FILE: vendor/github.com/zackbloom/goamz/iam/iam.go
================================================
// The iam package provides types and functions for interaction with the AWS
// Identity and Access Management (IAM) service.
package iam

import (
	"encoding/xml"
	"github.com/zackbloom/goamz/aws"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
)

// The IAM type encapsulates operations operations with the IAM endpoint.
type IAM struct {
	aws.Auth
	aws.Region
}

// New creates a new IAM instance.
func New(auth aws.Auth, region aws.Region) *IAM {
	return &IAM{auth, region}
}

func (iam *IAM) query(params map[string]string, resp interface{}) error {
	params["Version"] = "2010-05-08"
	params["Timestamp"] = time.Now().In(time.UTC).Format(time.RFC3339)
	endpoint, err := url.Parse(iam.IAMEndpoint)
	if err != nil {
		return err
	}
	sign(iam.Auth, "GET", "/", params, endpoint.Host)
	endpoint.RawQuery = multimap(params).Encode()
	r, err := http.Get(endpoint.String())
	if err != nil {
		return err
	}
	defer r.Body.Close()
	if r.StatusCode > 200 {
		return buildError(r)
	}
	return xml.NewDecoder(r.Body).Decode(resp)
}

func (iam *IAM) postQuery(params map[string]string, resp interface{}) error {
	endpoint, err := url.Parse(iam.IAMEndpoint)
	if err != nil {
		return err
	}
	params["Version"] = "2010-05-08"
	params["Timestamp"] = time.Now().In(time.UTC).Format(time.RFC3339)
	sign(iam.Auth, "POST", "/", params, endpoint.Host)
	encoded := multimap(params).Encode()
	body := strings.NewReader(encoded)
	req, err := http.NewRequest("POST", endpoint.String(), body)
	if err != nil {
		return err
	}
	req.Header.Set("Host", endpoint.Host)
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Set("Content-Length", strconv.Itoa(len(encoded)))
	r, err := http.DefaultClient.Do(req)
	if err != nil {
		return err
	}
	defer r.Body.Close()
	if r.StatusCode > 200 {
		return buildError(r)
	}
	return xml.NewDecoder(r.Body).Decode(resp)
}

func buildError(r *http.Response) error {
	var (
		err    Error
		errors xmlErrors
	)
	xml.NewDecoder(r.Body).Decode(&errors)
	if len(errors.Errors) > 0 {
		err = errors.Errors[0]
	}
	err.StatusCode = r.StatusCode
	if err.Message == "" {
		err.Message = r.Status
	}
	return &err
}

func multimap(p map[string]string) url.Values {
	q := make(url.Values, len(p))
	for k, v := range p {
		q[k] = []string{v}
	}
	return q
}

// Response to a CreateUser request.
//
// See http://goo.gl/JS9Gz for more details.
type CreateUserResp struct {
	RequestId string `xml:"ResponseMetadata>RequestId"`
	User      User   `xml:"CreateUserResult>User"`
}

// User encapsulates a user managed by IAM.
//
// See http://goo.gl/BwIQ3 for more details.
type User struct {
	Arn  string
	Path string
	Id   string `xml:"UserId"`
	Name string `xml:"UserName"`
}

// CreateUser creates a new user in IAM.
//
// See http://goo.gl/JS9Gz for more details.
func (iam *IAM) CreateUser(name, path string) (*CreateUserResp, error) {
	params := map[string]string{
		"Action":   "CreateUser",
		"Path":     path,
		"UserName": name,
	}
	resp := new(CreateUserResp)
	if err := iam.query(params, resp); err != nil {
		return nil, err
	}
	return resp, nil
}

// Response for GetUser requests.
//
// See http://goo.gl/ZnzRN for more details.
type GetUserResp struct {
	RequestId string `xml:"ResponseMetadata>RequestId"`
	User      User   `xml:"GetUserResult>User"`
}

// GetUser gets a user from IAM.
//
// See http://goo.gl/ZnzRN for more details.
func (iam *IAM) GetUser(name string) (*GetUserResp, error) {
	params := map[string]string{
		"Action": "GetUser",
	}
	if name != "" {
		params["UserName"] = name
	}
	resp := new(GetUserResp)
	if err := iam.query(params, resp); err != nil {
		return nil, err
	}
	return resp, nil
}

// DeleteUser deletes a user from IAM.
//
// See http://goo.gl/jBuCG for more details.
func (iam *IAM) DeleteUser(name string) (*SimpleResp, error) {
	params := map[string]string{
		"Action":   "DeleteUser",
		"UserName": name,
	}
	resp := new(SimpleResp)
	if err := iam.query(params, resp); err != nil {
		return nil, err
	}
	return resp, nil
}

// Response to a CreateGroup request.
//
// See http://goo.gl/n7NNQ for more details.
type CreateGroupResp struct {
	Group     Group  `xml:"CreateGroupResult>Group"`
	RequestId string `xml:"ResponseMetadata>RequestId"`
}

// Group encapsulates a group managed by IAM.
//
// See http://goo.gl/ae7Vs for more details.
type Group struct {
	Arn  string
	Id   string `xml:"GroupId"`
	Name string `xml:"GroupName"`
	Path string
}

// CreateGroup creates a new group in IAM.
//
// The path parameter can be used to identify which division or part of the
// organization the user belongs to.
//
// If path is unset ("") it defaults to "/".
//
// See http://goo.gl/n7NNQ for more details.
func (iam *IAM) CreateGroup(name string, path string) (*CreateGroupResp, error) {
	params := map[string]string{
		"Action":    "CreateGroup",
		"GroupName": name,
	}
	if path != "" {
		params["Path"] = path
	}
	resp := new(CreateGroupResp)
	if err := iam.query(params, resp); err != nil {
		return nil, err
	}
	return resp, nil
}

// Response to a ListGroups request.
//
// See http://goo.gl/W2TRj for more details.
type GroupsResp struct {
	Groups    []Group `xml:"ListGroupsResult>Groups>member"`
	RequestId string  `xml:"ResponseMetadata>RequestId"`
}

// Groups list the groups that have the specified path prefix.
//
// The parameter pathPrefix is optional. If pathPrefix is "", all groups are
// returned.
//
// See http://goo.gl/W2TRj for more details.
func (iam *IAM) Groups(pathPrefix string) (*GroupsResp, error) {
	params := map[string]string{
		"Action": "ListGroups",
	}
	if pathPrefix != "" {
		params["PathPrefix"] = pathPrefix
	}
	resp := new(GroupsResp)
	if err := iam.query(params, resp); err != nil {
		return nil, err
	}
	return resp, nil
}

// DeleteGroup deletes a group from IAM.
//
// See http://goo.gl/d5i2i for more details.
func (iam *IAM) DeleteGroup(name string) (*SimpleResp, error) {
	params := map[string]string{
		"Action":    "DeleteGroup",
		"GroupName": name,
	}
	resp := new(SimpleResp)
	if err := iam.query(params, resp); err != nil {
		return nil, err
	}
	return resp, nil
}

// Response to a CreateAccessKey request.
//
// See http://goo.gl/L46Py for more details.
type CreateAccessKeyResp struct {
	RequestId string    `xml:"ResponseMetadata>RequestId"`
	AccessKey AccessKey `xml:"Crea
Download .txt
gitextract_dxdit0ui/

├── .github/
│   └── workflows/
│       └── semgrep.yml
├── .gitignore
├── Godeps/
│   ├── Godeps.json
│   └── Readme
├── LICENSE
├── README.md
├── docs/
│   └── getting-started.md
├── 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
Download .txt
SYMBOL INDEX (1617 symbols across 63 files)

FILE: src/admin.go
  function CreateBucket (line 17) | func CreateBucket(options Options) error {
  function GetDistribution (line 55) | func GetDistribution(options Options) (dist cloudfront.DistributionSumma...
  function CreateUser (line 120) | func CreateUser(options Options) (key iam.AccessKey, err error) {
  function UpdateRoute (line 164) | func UpdateRoute(options Options, dist cloudfront.DistributionSummary) e...
  function Create (line 233) | func Create(options Options) {
  function createCmd (line 318) | func createCmd() {

FILE: src/cli.go
  function printUsage (line 8) | func printUsage() {
  function main (line 30) | func main() {

FILE: src/deploy.go
  constant SCRIPT (line 30) | SCRIPT = iota
  constant STYLE (line 31) | STYLE
  constant UPLOAD_WORKERS (line 34) | UPLOAD_WORKERS = 20
  function hashFile (line 42) | func hashFile(path string) []byte {
  function hashBytes (line 57) | func hashBytes(data []byte) []byte {
  function hashFiles (line 63) | func hashFiles(files []string) string {
  function getRef (line 75) | func getRef() string {
  function guessContentType (line 87) | func guessContentType(file string) string {
  function shouldCompress (line 91) | func shouldCompress(file string) bool {
  type UploadFileRequest (line 102) | type UploadFileRequest struct
  function uploadFile (line 111) | func uploadFile(req UploadFileRequest) (remotePath string) {
  type FileRef (line 161) | type FileRef struct
  type FileInst (line 167) | type FileInst struct
  function writeFiles (line 172) | func writeFiles(options Options, includeHash bool, files chan *FileRef) {
  function deployFiles (line 205) | func deployFiles(options Options, includeHash bool, files []*FileRef) {
  function addFiles (line 230) | func addFiles(form uint8, parent *html.Node, files []string) {
  function isLocal (line 265) | func isLocal(href string) bool {
  function formatHref (line 270) | func formatHref(path string) string {
  function renderHTML (line 277) | func renderHTML(options Options, file HTMLFile) string {
  function parseHTML (line 335) | func parseHTML(options Options, path string) (files []string, base strin...
  function deployHTML (line 389) | func deployHTML(options Options, id string, file HTMLFile) {
  function expandFiles (line 413) | func expandFiles(root string, glob string) []string {
  function listFiles (line 447) | func listFiles(options Options) []*FileRef {
  function ignoreFiles (line 467) | func ignoreFiles(full []*FileRef, rem []*FileRef) []*FileRef {
  function extractFileList (line 489) | func extractFileList(options Options, pattern string) (files []string) {
  function filesWithExtension (line 509) | func filesWithExtension(files []*FileRef, ext string) (outFiles []*FileR...
  type HTMLFile (line 520) | type HTMLFile struct
    method GetLocalPath (line 526) | func (f HTMLFile) GetLocalPath() string {
  function Deploy (line 530) | func Deploy(options Options) {
  function deployCmd (line 681) | func deployCmd() {

FILE: src/rollback.go
  function Rollback (line 12) | func Rollback(options Options, version string) {
  function rollbackCmd (line 64) | func rollbackCmd() {

FILE: src/utils.go
  constant LIMITED (line 25) | LIMITED = 60
  constant FOREVER (line 26) | FOREVER = 31556926
  function getRegion (line 34) | func getRegion(region string, s3Host string) aws.Region {
  function openS3 (line 48) | func openS3(key, secret, region, s3Host string) *s3.S3 {
  function openIAM (line 58) | func openIAM(key, secret, region string) *iam.IAM {
  function openCloudFront (line 68) | func openCloudFront(key, secret string) *cloudfront.CloudFront {
  function openRoute53 (line 76) | func openRoute53(key, secret string) *route53.Route53 {
  function panicIf (line 86) | func panicIf(err error) {
  function must (line 91) | func must(val interface{}, err error) interface{} {
  function mustString (line 98) | func mustString(val string, err error) string {
  function mustInt (line 102) | func mustInt(val int, err error) int {
  type Options (line 107) | type Options struct
  function parseOptions (line 121) | func parseOptions() (o Options, set *flag.FlagSet) {
  type ConfigFile (line 142) | type ConfigFile
  function loadConfigFile (line 144) | func loadConfigFile(o *Options) {
  function addAWSConfig (line 180) | func addAWSConfig(o *Options) {
  type AWSConfig (line 186) | type AWSConfig struct
  function loadAWSConfig (line 193) | func loadAWSConfig() (access string, secret string) {
  function copyFile (line 217) | func copyFile(bucket *s3.Bucket, from string, to string, contentType str...
  function joinPath (line 235) | func joinPath(parts ...string) string {

FILE: vendor/github.com/cenk/backoff/backoff.go
  type BackOff (line 9) | type BackOff interface
  constant Stop (line 29) | Stop time.Duration = -1
  type ZeroBackOff (line 33) | type ZeroBackOff struct
    method Reset (line 35) | func (b *ZeroBackOff) Reset() {}
    method NextBackOff (line 37) | func (b *ZeroBackOff) NextBackOff() time.Duration { return 0 }
  type StopBackOff (line 41) | type StopBackOff struct
    method Reset (line 43) | func (b *StopBackOff) Reset() {}
    method NextBackOff (line 45) | func (b *StopBackOff) NextBackOff() time.Duration { return Stop }
  type ConstantBackOff (line 50) | type ConstantBackOff struct
    method Reset (line 54) | func (b *ConstantBackOff) Reset()                     {}
    method NextBackOff (line 55) | func (b *ConstantBackOff) NextBackOff() time.Duration { return b.Inter...
  function NewConstantBackOff (line 57) | func NewConstantBackOff(d time.Duration) *ConstantBackOff {

FILE: vendor/github.com/cenk/backoff/exponential.go
  type ExponentialBackOff (line 54) | type ExponentialBackOff struct
    method Reset (line 111) | func (b *ExponentialBackOff) Reset() {
    method NextBackOff (line 118) | func (b *ExponentialBackOff) NextBackOff() time.Duration {
    method GetElapsedTime (line 131) | func (b *ExponentialBackOff) GetElapsedTime() time.Duration {
    method incrementCurrentInterval (line 136) | func (b *ExponentialBackOff) incrementCurrentInterval() {
  type Clock (line 69) | type Clock interface
  constant DefaultInitialInterval (line 75) | DefaultInitialInterval     = 500 * time.Millisecond
  constant DefaultRandomizationFactor (line 76) | DefaultRandomizationFactor = 0.5
  constant DefaultMultiplier (line 77) | DefaultMultiplier          = 1.5
  constant DefaultMaxInterval (line 78) | DefaultMaxInterval         = 60 * time.Second
  constant DefaultMaxElapsedTime (line 79) | DefaultMaxElapsedTime      = 15 * time.Minute
  function NewExponentialBackOff (line 83) | func NewExponentialBackOff() *ExponentialBackOff {
  type systemClock (line 101) | type systemClock struct
    method Now (line 103) | func (t systemClock) Now() time.Time {
  function getRandomValueFromInterval (line 147) | func getRandomValueFromInterval(randomizationFactor, random float64, cur...

FILE: vendor/github.com/cenk/backoff/retry.go
  type Operation (line 7) | type Operation
  type Notify (line 14) | type Notify
  function Retry (line 22) | func Retry(o Operation, b BackOff) error { return RetryNotify(o, b, nil) }
  function RetryNotify (line 26) | func RetryNotify(operation Operation, b BackOff, notify Notify) error {

FILE: vendor/github.com/cenk/backoff/ticker.go
  type Ticker (line 13) | type Ticker struct
    method Stop (line 38) | func (t *Ticker) Stop() {
    method run (line 42) | func (t *Ticker) run() {
    method send (line 65) | func (t *Ticker) send(tick time.Time) <-chan time.Time {
  function NewTicker (line 24) | func NewTicker(b BackOff) *Ticker {

FILE: vendor/github.com/imdario/mergo/map.go
  function changeInitialCase (line 18) | func changeInitialCase(s string, mapper func(rune) rune) string {
  function isExported (line 26) | func isExported(field reflect.StructField) bool {
  function deepMap (line 34) | func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth i...
  function Map (line 120) | func Map(dst, src interface{}) error {
  function MapWithOverwrite (line 126) | func MapWithOverwrite(dst, src interface{}) error {
  function _map (line 130) | func _map(dst, src interface{}, overwrite bool) error {

FILE: vendor/github.com/imdario/mergo/merge.go
  function deepMerge (line 18) | func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth...
  function Merge (line 101) | func Merge(dst, src interface{}) error {
  function MergeWithOverwrite (line 107) | func MergeWithOverwrite(dst, src interface{}) error {
  function merge (line 111) | func merge(dst, src interface{}, overwrite bool) error {

FILE: vendor/github.com/imdario/mergo/mergo.go
  type visit (line 29) | type visit struct
  function isEmptyValue (line 36) | func isEmptyValue(v reflect.Value) bool {
  function resolveValues (line 54) | func resolveValues(dst, src interface{}) (vDst, vSrc reflect.Value, err ...
  function deeper (line 75) | func deeper(dst, src reflect.Value, visited map[uintptr]*visit, depth in...

FILE: vendor/github.com/mitchellh/go-homedir/homedir.go
  function Dir (line 26) | func Dir() (string, error) {
  function Expand (line 58) | func Expand(path string) (string, error) {
  function dirUnix (line 79) | func dirUnix() (string, error) {
  function dirWindows (line 120) | func dirWindows() (string, error) {

FILE: vendor/github.com/wsxiaoys/terminal/color/color.go
  constant EscapeChar (line 40) | EscapeChar = '@'
  constant ResetCode (line 41) | ResetCode  = "\033[0m"
  function Colorize (line 79) | func Colorize(x string) string {
  function compileColorSyntax (line 103) | func compileColorSyntax(input, output *bytes.Buffer) {
  function compile (line 134) | func compile(x string) string {
  function compileValues (line 158) | func compileValues(a *[]interface{}) {
  function Print (line 167) | func Print(a ...interface{}) (int, error) {
  function Println (line 174) | func Println(a ...interface{}) (int, error) {
  function Printf (line 181) | func Printf(format string, a ...interface{}) (int, error) {
  function Fprint (line 188) | func Fprint(w io.Writer, a ...interface{}) (int, error) {
  function Fprintln (line 195) | func Fprintln(w io.Writer, a ...interface{}) (int, error) {
  function Fprintf (line 202) | func Fprintf(w io.Writer, format string, a ...interface{}) (int, error) {
  function Sprint (line 209) | func Sprint(a ...interface{}) string {
  function Sprintf (line 216) | func Sprintf(format string, a ...interface{}) string {
  function Errorf (line 223) | func Errorf(format string, a ...interface{}) error {

FILE: vendor/github.com/zackbloom/go-ini/decode.go
  type Unmatched (line 15) | type Unmatched struct
    method String (line 107) | func (u Unmatched) String() string {
  type IniError (line 20) | type IniError struct
    method Error (line 114) | func (e *IniError) Error() string {
  type decodeState (line 27) | type decodeState struct
    method init (line 132) | func (d *decodeState) init(data []byte) *decodeState {
    method saveError (line 146) | func (d *decodeState) saveError(err error) {
    method generateMap (line 156) | func (d *decodeState) generateMap(m propertyMap, v reflect.Value) {
    method unmarshal (line 200) | func (d *decodeState) unmarshal(x interface{}) error {
    method unmarshal2 (line 289) | func (d *decodeState) unmarshal2(x interface{}) error {
    method setValue (line 397) | func (d *decodeState) setValue(v reflect.Value, s string) {
    method sliceValue (line 441) | func (d *decodeState) sliceValue(v reflect.Value, s string) {
  type property (line 35) | type property struct
    method String (line 125) | func (p property) String() string {
  type propertyMap (line 44) | type propertyMap
  function NewPropMapStack (line 49) | func NewPropMapStack() *PropMapStack {
  type PropMapStack (line 54) | type PropMapStack struct
    method Push (line 60) | func (s *PropMapStack) Push(item propertyMap) {
    method Pop (line 66) | func (s *PropMapStack) Pop() propertyMap {
    method Peek (line 76) | func (s *PropMapStack) Peek() propertyMap {
    method Empty (line 85) | func (s *PropMapStack) Empty() bool {
    method Size (line 90) | func (s *PropMapStack) Size() int {
  function Unmarshal (line 98) | func Unmarshal(data []byte, v interface{}) error {
  function appendValue (line 392) | func appendValue(arr, val reflect.Value) {
  function boolValue (line 497) | func boolValue(s string) bool {
  type Decoder (line 508) | type Decoder struct
    method Decode (line 525) | func (dec *Decoder) Decode(v interface{}) error {
    method Unmatched (line 542) | func (dec *Decoder) Unmatched() []Unmatched {
  function NewDecoder (line 517) | func NewDecoder(r io.Reader) *Decoder {

FILE: vendor/github.com/zackbloom/go-ini/stack.go
  function NewStack (line 4) | func NewStack() *Stack {
  type Stack (line 9) | type Stack struct
    method Push (line 15) | func (s *Stack) Push(item interface{}) {
    method Pop (line 21) | func (s *Stack) Pop() interface{} {
    method Peek (line 31) | func (s *Stack) Peek() interface{} {
    method Empty (line 40) | func (s *Stack) Empty() bool {
    method Size (line 45) | func (s *Stack) Size() int {

FILE: vendor/github.com/zackbloom/goamz/aws/attempt.go
  type AttemptStrategy (line 10) | type AttemptStrategy struct
    method Start (line 25) | func (s AttemptStrategy) Start() *Attempt {
  type Attempt (line 16) | type Attempt struct
    method Next (line 37) | func (a *Attempt) Next() bool {
    method nextSleep (line 53) | func (a *Attempt) nextSleep(now time.Time) time.Duration {
    method HasNext (line 64) | func (a *Attempt) HasNext() bool {

FILE: vendor/github.com/zackbloom/goamz/aws/aws.go
  constant V2Signature (line 37) | V2Signature      = iota
  constant V4Signature (line 38) | V4Signature      = iota
  constant Route53Signature (line 39) | Route53Signature = iota
  type ServiceInfo (line 44) | type ServiceInfo struct
  type Region (line 52) | type Region struct
  type Signer (line 92) | type Signer interface
  type AWSService (line 99) | type AWSService interface
  type Service (line 110) | type Service struct
    method Query (line 140) | func (s *Service) Query(method, path string, params map[string]string)...
    method BuildError (line 159) | func (s *Service) BuildError(r *http.Response) error {
  function MakeParams (line 116) | func MakeParams(action string) map[string]string {
  function NewService (line 123) | func NewService(auth Auth, service ServiceInfo) (s *Service, err error) {
  type ServiceError (line 172) | type ServiceError interface
  type ErrorResponse (line 177) | type ErrorResponse struct
  type Error (line 182) | type Error struct
    method Error (line 190) | func (err *Error) Error() string {
    method ErrorCode (line 196) | func (err *Error) ErrorCode() string {
  type Auth (line 200) | type Auth struct
    method Token (line 206) | func (a *Auth) Token() string {
    method Expiration (line 216) | func (a *Auth) Expiration() time.Time {
  function NewAuth (line 221) | func NewAuth(accessKey, secretKey, token string, expiration time.Time) *...
  type ResponseMetadata (line 231) | type ResponseMetadata struct
  type BaseResponse (line 235) | type BaseResponse struct
  function init (line 242) | func init() {
  function multimap (line 250) | func multimap(p map[string]string) url.Values {
  type credentials (line 258) | type credentials struct
  function GetMetaData (line 271) | func GetMetaData(path string) (contents []byte, err error) {
  function GetRegion (line 306) | func GetRegion(regionName string) (region Region) {
  function GetInstanceCredentials (line 314) | func GetInstanceCredentials() (cred credentials, err error) {
  function GetAuth (line 335) | func GetAuth(accessKey string, secretKey, token string, expiration time....
  function EnvAuth (line 377) | func EnvAuth() (auth Auth, err error) {
  function CredentialFileAuth (line 401) | func CredentialFileAuth(filePath string, profile string, expiration time...
  function parseINI (line 456) | func parseINI(fileContents string) map[string]map[string]string {
  function Encode (line 488) | func Encode(s string) string {
  function dialTimeout (line 517) | func dialTimeout(network, addr string) (net.Conn, error) {
  function AvailabilityZone (line 521) | func AvailabilityZone() string {
  function InstanceRegion (line 540) | func InstanceRegion() string {
  function InstanceId (line 550) | func InstanceId() string {
  function InstanceType (line 569) | func InstanceType() string {
  function ServerLocalIp (line 588) | func ServerLocalIp() string {
  function ServerPublicIp (line 607) | func ServerPublicIp() string {

FILE: vendor/github.com/zackbloom/goamz/aws/client.go
  type RetryableFunc (line 10) | type RetryableFunc
  type WaitFunc (line 11) | type WaitFunc
  type DeadlineFunc (line 12) | type DeadlineFunc
  type ResilientTransport (line 14) | type ResilientTransport struct
    method RoundTrip (line 68) | func (t *ResilientTransport) RoundTrip(req *http.Request) (*http.Respo...
    method tries (line 76) | func (t *ResilientTransport) tries(req *http.Request) (res *http.Respo...
  function NewClient (line 36) | func NewClient(rt *ResilientTransport) *http.Client {
  function ExpBackoff (line 94) | func ExpBackoff(try int) {
  function LinearBackoff (line 99) | func LinearBackoff(try int) {
  function awsRetry (line 106) | func awsRetry(req *http.Request, res *http.Response, err error) bool {

FILE: vendor/github.com/zackbloom/goamz/aws/retry.go
  constant maxDelay (line 11) | maxDelay             = 20 * time.Second
  constant defaultScale (line 12) | defaultScale         = 300 * time.Millisecond
  constant throttlingScale (line 13) | throttlingScale      = 500 * time.Millisecond
  constant throttlingScaleRange (line 14) | throttlingScaleRange = throttlingScale / 4
  constant defaultMaxRetries (line 15) | defaultMaxRetries    = 3
  constant dynamoDBScale (line 16) | dynamoDBScale        = 25 * time.Millisecond
  constant dynamoDBMaxRetries (line 17) | dynamoDBMaxRetries   = 10
  type RetryPolicy (line 23) | type RetryPolicy interface
  type DefaultRetryPolicy (line 38) | type DefaultRetryPolicy struct
    method ShouldRetry (line 42) | func (policy DefaultRetryPolicy) ShouldRetry(target string, r *http.Re...
    method Delay (line 47) | func (policy DefaultRetryPolicy) Delay(target string, r *http.Response...
  type DynamoDBRetryPolicy (line 61) | type DynamoDBRetryPolicy struct
    method ShouldRetry (line 65) | func (policy DynamoDBRetryPolicy) ShouldRetry(target string, r *http.R...
    method Delay (line 70) | func (policy DynamoDBRetryPolicy) Delay(target string, r *http.Respons...
  type NeverRetryPolicy (line 75) | type NeverRetryPolicy struct
    method ShouldRetry (line 79) | func (policy NeverRetryPolicy) ShouldRetry(target string, r *http.Resp...
    method Delay (line 84) | func (policy NeverRetryPolicy) Delay(target string, r *http.Response, ...
  function shouldRetry (line 91) | func shouldRetry(r *http.Response, err error, numRetries int, maxRetries...
  function exponentialBackoff (line 117) | func exponentialBackoff(numRetries int, scale time.Duration) time.Durati...
  function isThrottlingException (line 129) | func isThrottlingException(err ServiceError) bool {

FILE: vendor/github.com/zackbloom/goamz/aws/sign.go
  type V2Signer (line 18) | type V2Signer struct
    method Sign (line 34) | func (s *V2Signer) Sign(method, path string, params map[string]string) {
  function NewV2Signer (line 26) | func NewV2Signer(auth Auth, service ServiceInfo) (*V2Signer, error) {
  constant ISO8601BasicFormat (line 66) | ISO8601BasicFormat      = "20060102T150405Z"
  constant ISO8601BasicFormatShort (line 67) | ISO8601BasicFormatShort = "20060102"
  type Route53Signer (line 70) | type Route53Signer struct
    method getCurrentDate (line 80) | func (s *Route53Signer) getCurrentDate() string {
    method getHeaderAuthorize (line 92) | func (s *Route53Signer) getHeaderAuthorize(message string) string {
    method Sign (line 102) | func (s *Route53Signer) Sign(req *http.Request) {
  function NewRoute53Signer (line 74) | func NewRoute53Signer(auth Auth) *Route53Signer {
  type V4Signer (line 120) | type V4Signer struct
    method Sign (line 152) | func (s *V4Signer) Sign(req *http.Request) {
    method requestTime (line 194) | func (s *V4Signer) requestTime(req *http.Request) time.Time {
    method canonicalRequest (line 240) | func (s *V4Signer) canonicalRequest(req *http.Request, payloadHash str...
    method canonicalURI (line 254) | func (s *V4Signer) canonicalURI(u *url.URL) string {
    method canonicalQueryString (line 272) | func (s *V4Signer) canonicalQueryString(u *url.URL) string {
    method canonicalHeaders (line 289) | func (s *V4Signer) canonicalHeaders(h http.Header) string {
    method signedHeaders (line 314) | func (s *V4Signer) signedHeaders(h http.Header) string {
    method payloadHash (line 324) | func (s *V4Signer) payloadHash(req *http.Request) string {
    method stringToSign (line 349) | func (s *V4Signer) stringToSign(t time.Time, creq string) string {
    method credentialScope (line 358) | func (s *V4Signer) credentialScope(t time.Time) string {
    method signature (line 367) | func (s *V4Signer) signature(t time.Time, sts string) string {
    method derivedKey (line 381) | func (s *V4Signer) derivedKey(t time.Time) []byte {
    method authorization (line 392) | func (s *V4Signer) authorization(header http.Header, t time.Time, sign...
    method hash (line 402) | func (s *V4Signer) hash(in string) string {
    method hmac (line 409) | func (s *V4Signer) hmac(key, data []byte) []byte {
  function NewV4Signer (line 131) | func NewV4Signer(auth Auth, serviceName string, region Region) *V4Signer {

FILE: vendor/github.com/zackbloom/goamz/cloudfront/cloudfront.go
  constant ServiceName (line 22) | ServiceName = "cloudfront"
  constant ApiVersion (line 23) | ApiVersion  = "2014-11-06"
  function NewCloudFront (line 27) | func NewCloudFront(auth aws.Auth) *CloudFront {
  type CloudFront (line 36) | type CloudFront struct
    method generateSignature (line 431) | func (cf *CloudFront) generateSignature(policy []byte) (string, error) {
    method Create (line 520) | func (cf *CloudFront) Create(config DistributionConfig) (summary Distr...
    method List (line 587) | func (cf *CloudFront) List(marker string, max int) (items *Distributio...
    method FindDistributionByAlias (line 631) | func (cf *CloudFront) FindDistributionByAlias(alias string) (dist *Dis...
    method CannedSignedURL (line 665) | func (cf *CloudFront) CannedSignedURL(path, queryString string, expire...
    method SignedURL (line 700) | func (cloudfront *CloudFront) SignedURL(path, querystrings string, exp...
  type DistributionConfig (line 44) | type DistributionConfig struct
  type DistributionSummary (line 61) | type DistributionSummary struct
  type Aliases (line 70) | type Aliases
    method MarshalXML (line 77) | func (a Aliases) MarshalXML(e *xml.Encoder, start xml.StartElement) er...
    method UnmarshalXML (line 86) | func (n *Aliases) UnmarshalXML(d *xml.Decoder, start xml.StartElement)...
  type EncodedAliases (line 72) | type EncodedAliases struct
  type CustomErrorResponses (line 97) | type CustomErrorResponses
    method MarshalXML (line 104) | func (a CustomErrorResponses) MarshalXML(e *xml.Encoder, start xml.Sta...
    method UnmarshalXML (line 113) | func (n *CustomErrorResponses) UnmarshalXML(d *xml.Decoder, start xml....
  type EncodedCustomErrorResponses (line 99) | type EncodedCustomErrorResponses struct
  type CacheBehaviors (line 124) | type CacheBehaviors
    method MarshalXML (line 131) | func (a CacheBehaviors) MarshalXML(e *xml.Encoder, start xml.StartElem...
    method UnmarshalXML (line 140) | func (n *CacheBehaviors) UnmarshalXML(d *xml.Decoder, start xml.StartE...
  type EncodedCacheBehaviors (line 126) | type EncodedCacheBehaviors struct
  type Logging (line 151) | type Logging struct
  type ViewerCertificate (line 158) | type ViewerCertificate struct
  type GeoRestriction (line 165) | type GeoRestriction struct
    method MarshalXML (line 176) | func (a GeoRestriction) MarshalXML(e *xml.Encoder, start xml.StartElem...
    method UnmarshalXML (line 186) | func (n *GeoRestriction) UnmarshalXML(d *xml.Decoder, start xml.StartE...
  type EncodedGeoRestriction (line 170) | type EncodedGeoRestriction struct
  type CustomErrorResponse (line 198) | type CustomErrorResponse struct
  type Origin (line 206) | type Origin struct
  type S3OriginConfig (line 215) | type S3OriginConfig struct
  type CustomOriginConfig (line 219) | type CustomOriginConfig struct
  type Origins (line 225) | type Origins
    method MarshalXML (line 232) | func (o Origins) MarshalXML(e *xml.Encoder, start xml.StartElement) er...
    method UnmarshalXML (line 241) | func (o *Origins) UnmarshalXML(d *xml.Decoder, start xml.StartElement)...
  type EncodedOrigins (line 227) | type EncodedOrigins struct
  type CacheBehavior (line 252) | type CacheBehavior struct
  type ForwardedValues (line 263) | type ForwardedValues struct
  type Cookies (line 269) | type Cookies struct
  function cacheBehaviorDefault (line 279) | func cacheBehaviorDefault(cache *CacheBehavior) {
  type Names (line 286) | type Names
    method MarshalXML (line 293) | func (w Names) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
    method UnmarshalXML (line 302) | func (n *Names) UnmarshalXML(d *xml.Decoder, start xml.StartElement) e...
  type EncodedNames (line 288) | type EncodedNames struct
  type ItemsList (line 313) | type ItemsList
  type TrustedSigners (line 315) | type TrustedSigners struct
    method MarshalXML (line 326) | func (n TrustedSigners) MarshalXML(e *xml.Encoder, start xml.StartElem...
    method UnmarshalXML (line 336) | func (n *TrustedSigners) UnmarshalXML(d *xml.Decoder, start xml.StartE...
  type EncodedTrustedSigners (line 320) | type EncodedTrustedSigners struct
  type AllowedMethods (line 348) | type AllowedMethods struct
    method MarshalXML (line 360) | func (n AllowedMethods) MarshalXML(e *xml.Encoder, start xml.StartElem...
    method UnmarshalXML (line 371) | func (n *AllowedMethods) UnmarshalXML(d *xml.Decoder, start xml.StartE...
  type EncodedAllowedMethods (line 353) | type EncodedAllowedMethods struct
  function NewKeyLess (line 385) | func NewKeyLess(auth aws.Auth, baseurl string) *CloudFront {
  function New (line 389) | func New(baseurl string, key *rsa.PrivateKey, keyPairId string) *CloudFr...
  type epochTime (line 397) | type epochTime struct
  type condition (line 401) | type condition struct
  type statement (line 405) | type statement struct
  type policy (line 410) | type policy struct
  function buildPolicy (line 414) | func buildPolicy(resource string, expireTime time.Time) ([]byte, error) {
  type DistributionItem (line 567) | type DistributionItem struct
  type DistributionsResp (line 572) | type DistributionsResp struct

FILE: vendor/github.com/zackbloom/goamz/iam/iam.go
  type IAM (line 16) | type IAM struct
    method query (line 26) | func (iam *IAM) query(params map[string]string, resp interface{}) error {
    method postQuery (line 46) | func (iam *IAM) postQuery(params map[string]string, resp interface{}) ...
    method CreateUser (line 119) | func (iam *IAM) CreateUser(name, path string) (*CreateUserResp, error) {
    method GetUser (line 143) | func (iam *IAM) GetUser(name string) (*GetUserResp, error) {
    method DeleteUser (line 160) | func (iam *IAM) DeleteUser(name string) (*SimpleResp, error) {
    method CreateGroup (line 198) | func (iam *IAM) CreateGroup(name string, path string) (*CreateGroupRes...
    method Groups (line 227) | func (iam *IAM) Groups(pathPrefix string) (*GroupsResp, error) {
    method DeleteGroup (line 244) | func (iam *IAM) DeleteGroup(name string) (*SimpleResp, error) {
    method CreateAccessKey (line 277) | func (iam *IAM) CreateAccessKey(userName string) (*CreateAccessKeyResp...
    method AccessKeys (line 303) | func (iam *IAM) AccessKeys(userName string) (*AccessKeysResp, error) {
    method DeleteAccessKey (line 323) | func (iam *IAM) DeleteAccessKey(id, userName string) (*SimpleResp, err...
    method GetUserPolicy (line 358) | func (iam *IAM) GetUserPolicy(userName, policyName string) (*GetUserPo...
    method PutUserPolicy (line 375) | func (iam *IAM) PutUserPolicy(userName, policyName, policyDocument str...
    method DeleteUserPolicy (line 392) | func (iam *IAM) DeleteUserPolicy(userName, policyName string) (*Simple...
  function New (line 22) | func New(auth aws.Auth, region aws.Region) *IAM {
  function buildError (line 74) | func buildError(r *http.Response) error {
  function multimap (line 90) | func multimap(p map[string]string) url.Values {
  type CreateUserResp (line 101) | type CreateUserResp struct
  type User (line 109) | type User struct
  type GetUserResp (line 135) | type GetUserResp struct
  type CreateGroupResp (line 175) | type CreateGroupResp struct
  type Group (line 183) | type Group struct
  type GroupsResp (line 216) | type GroupsResp struct
  type CreateAccessKeyResp (line 259) | type CreateAccessKeyResp struct
  type AccessKey (line 267) | type AccessKey struct
  type AccessKeysResp (line 292) | type AccessKeysResp struct
  type GetUserPolicyResp (line 341) | type GetUserPolicyResp struct
  type UserPolicy (line 349) | type UserPolicy struct
  type SimpleResp (line 405) | type SimpleResp struct
  type xmlErrors (line 409) | type xmlErrors struct
  type Error (line 414) | type Error struct
    method Error (line 425) | func (e *Error) Error() string {

FILE: vendor/github.com/zackbloom/goamz/iam/sign.go
  function sign (line 17) | func sign(auth aws.Auth, method, path string, params map[string]string, ...

FILE: vendor/github.com/zackbloom/goamz/route53/route53.go
  type Route53 (line 15) | type Route53 struct
    method query (line 231) | func (r *Route53) query(method string, path string, body io.Reader, re...
    method CreateHostedZone (line 260) | func (r *Route53) CreateHostedZone(hostedZoneReq *CreateHostedZoneRequ...
    method ListResourceRecordSets (line 273) | func (r *Route53) ListResourceRecordSets(hostedZone string, name strin...
    method ChangeResourceRecordSet (line 306) | func (r *Route53) ChangeResourceRecordSet(req *ChangeResourceRecordSet...
    method ListHostedZones (line 323) | func (r *Route53) ListHostedZones(marker string, maxItems int) (result...
    method ListHostedZonesByName (line 339) | func (r *Route53) ListHostedZonesByName(DNSName string, nextHostedZone...
    method GetHostedZone (line 359) | func (r *Route53) GetHostedZone(id string) (result *GetHostedZoneRespo...
    method DeleteHostedZone (line 367) | func (r *Route53) DeleteHostedZone(id string) (result *DeleteHostedZon...
    method AssociateVPCWithHostedZone (line 377) | func (r *Route53) AssociateVPCWithHostedZone(zoneid string, req *Assoc...
    method DisassociateVPCWithHostedZone (line 392) | func (r *Route53) DisassociateVPCWithHostedZone(zoneid string, req *Di...
  constant route53_host (line 22) | route53_host = "https://route53.amazonaws.com"
  constant route53_ver (line 23) | route53_ver = "2013-04-01"
  function NewRoute53 (line 26) | func NewRoute53(auth aws.Auth) (*Route53, error) {
  type HostedZone (line 37) | type HostedZone struct
  type Config (line 47) | type Config struct
  type ListHostedZonesResponse (line 54) | type ListHostedZonesResponse struct
  type ListHostedZonesByNameResponse (line 63) | type ListHostedZonesByNameResponse struct
  type CreateHostedZoneRequest (line 75) | type CreateHostedZoneRequest struct
  type ResourceRecordValue (line 84) | type ResourceRecordValue struct
  type Change (line 88) | type Change struct
  type ChangeResourceRecordSetsRequest (line 97) | type ChangeResourceRecordSetsRequest struct
  type AssociateVPCWithHostedZoneRequest (line 103) | type AssociateVPCWithHostedZoneRequest struct
  type DisassociateVPCWithHostedZoneRequest (line 110) | type DisassociateVPCWithHostedZoneRequest struct
  type HostedZoneConfig (line 117) | type HostedZoneConfig struct
  type HostedZoneVPC (line 122) | type HostedZoneVPC struct
  type CreateHostedZoneResponse (line 128) | type CreateHostedZoneResponse struct
  type AliasTarget (line 135) | type AliasTarget struct
  type ResourceRecord (line 141) | type ResourceRecord struct
  type ResourceRecords (line 146) | type ResourceRecords struct
  type ResourceRecordSet (line 151) | type ResourceRecordSet struct
    method GetValues (line 294) | func (recordset *ResourceRecordSet) GetValues() []string {
  type ResourceRecordSets (line 163) | type ResourceRecordSets struct
  type ListResourceRecordSetsResponse (line 168) | type ListResourceRecordSetsResponse struct
    method GetResourceRecordSets (line 290) | func (response *ListResourceRecordSetsResponse) GetResourceRecordSets(...
  type ChangeResourceRecordSetsResponse (line 178) | type ChangeResourceRecordSetsResponse struct
  type ChangeInfo (line 185) | type ChangeInfo struct
  type DelegationSet (line 192) | type DelegationSet struct
  type NameServers (line 197) | type NameServers struct
  type GetHostedZoneResponse (line 202) | type GetHostedZoneResponse struct
  type DeleteHostedZoneResponse (line 209) | type DeleteHostedZoneResponse struct
  type AssociateVPCWithHostedZoneResponse (line 215) | type AssociateVPCWithHostedZoneResponse struct
  type DisassociateVPCWithHostedZoneResponse (line 221) | type DisassociateVPCWithHostedZoneResponse struct
  function addParam (line 406) | func addParam(buffer *bytes.Buffer, name, value string) {

FILE: vendor/github.com/zackbloom/goamz/s3/lifecycle.go
  constant LifecycleRuleStatusEnabled (line 16) | LifecycleRuleStatusEnabled  = "Enabled"
  constant LifecycleRuleStatusDisabled (line 17) | LifecycleRuleStatusDisabled = "Disabled"
  constant LifecycleRuleDateFormat (line 18) | LifecycleRuleDateFormat     = "2006-01-02"
  constant StorageClassGlacier (line 19) | StorageClassGlacier         = "GLACIER"
  type Expiration (line 22) | type Expiration struct
    method ParseDate (line 28) | func (r *Expiration) ParseDate() (time.Time, error) {
  type Transition (line 32) | type Transition struct
    method ParseDate (line 39) | func (r *Transition) ParseDate() (time.Time, error) {
  type NoncurrentVersionExpiration (line 43) | type NoncurrentVersionExpiration struct
  type NoncurrentVersionTransition (line 47) | type NoncurrentVersionTransition struct
  type LifecycleRule (line 52) | type LifecycleRule struct
    method SetTransitionDays (line 74) | func (r *LifecycleRule) SetTransitionDays(days uint) {
    method SetTransitionDate (line 82) | func (r *LifecycleRule) SetTransitionDate(date time.Time) {
    method SetExpirationDays (line 91) | func (r *LifecycleRule) SetExpirationDays(days uint) {
    method SetExpirationDate (line 98) | func (r *LifecycleRule) SetExpirationDate(date time.Time) {
    method SetNoncurrentVersionTransitionDays (line 106) | func (r *LifecycleRule) SetNoncurrentVersionTransitionDays(days uint) {
    method SetNoncurrentVersionExpirationDays (line 115) | func (r *LifecycleRule) SetNoncurrentVersionExpirationDays(days uint) {
    method Disable (line 122) | func (r *LifecycleRule) Disable() {
    method Enable (line 127) | func (r *LifecycleRule) Enable() {
  function NewLifecycleRule (line 64) | func NewLifecycleRule(id, prefix string) *LifecycleRule {
  type LifecycleConfiguration (line 131) | type LifecycleConfiguration struct
    method AddRule (line 137) | func (c *LifecycleConfiguration) AddRule(r *LifecycleRule) {
  method PutLifecycleConfiguration (line 147) | func (b *Bucket) PutLifecycleConfiguration(c *LifecycleConfiguration) er...
  method GetLifecycleConfiguration (line 179) | func (b *Bucket) GetLifecycleConfiguration() (*LifecycleConfiguration, e...
  method DeleteLifecycleConfiguration (line 193) | func (b *Bucket) DeleteLifecycleConfiguration() error {

FILE: vendor/github.com/zackbloom/goamz/s3/multi.go
  type Multi (line 24) | type Multi struct
    method PutPartCopy (line 143) | func (m *Multi) PutPartCopy(n int, options CopyOptions, source string)...
    method PutPart (line 187) | func (m *Multi) PutPart(n int, r io.ReadSeeker) (Part, error) {
    method putPart (line 195) | func (m *Multi) putPart(n int, r io.ReadSeeker, partSize int64, md5b64...
    method ListParts (line 275) | func (m *Multi) ListParts() ([]Part, error) {
    method ListPartsFull (line 285) | func (m *Multi) ListPartsFull(partNumberMarker int, maxParts int) ([]P...
    method PutAll (line 333) | func (m *Multi) PutAll(r ReaderAtSeeker, partSize int64) ([]Part, erro...
    method Complete (line 401) | func (m *Multi) Complete(parts []Part) error {
    method Abort (line 446) | func (m *Multi) Abort() error {
  type listMultiResp (line 33) | type listMultiResp struct
  method ListMulti (line 53) | func (b *Bucket) ListMulti(prefix, delim string) (multis []*Multi, prefi...
  method Multi (line 93) | func (b *Bucket) Multi(key, contType string, perm ACL, options Options) ...
  method InitMulti (line 110) | func (b *Bucket) InitMulti(key string, contType string, perm ACL, option...
  function seekerInfo (line 237) | func seekerInfo(r io.ReadSeeker) (size int64, md5hex string, md5b64 stri...
  type Part (line 253) | type Part struct
  type partSlice (line 259) | type partSlice
    method Len (line 261) | func (s partSlice) Len() int           { return len(s) }
    method Less (line 262) | func (s partSlice) Less(i, j int) bool { return s[i].N < s[j].N }
    method Swap (line 263) | func (s partSlice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
  type listPartsResp (line 265) | type listPartsResp struct
  type ReaderAtSeeker (line 322) | type ReaderAtSeeker interface
  type completeUpload (line 381) | type completeUpload struct
  type completePart (line 386) | type completePart struct
  type completeParts (line 391) | type completeParts
    method Len (line 393) | func (p completeParts) Len() int           { return len(p) }
    method Less (line 394) | func (p completeParts) Less(i, j int) bool { return p[i].PartNumber < ...
    method Swap (line 395) | func (p completeParts) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

FILE: vendor/github.com/zackbloom/goamz/s3/s3.go
  constant debug (line 35) | debug = false
  type S3 (line 38) | type S3 struct
    method Bucket (line 103) | func (s3 *S3) Bucket(name string) *Bucket {
    method GetService (line 123) | func (s3 *S3) GetService() (*GetServiceResp, error) {
    method locationConstraint (line 148) | func (s3 *S3) locationConstraint() io.Reader {
    method query (line 963) | func (s3 *S3) query(req *request, resp interface{}) error {
    method queryV4Sign (line 978) | func (s3 *S3) queryV4Sign(req *request, resp interface{}) error {
    method setBaseURL (line 1005) | func (s3 *S3) setBaseURL(req *request) error {
    method prepare (line 1053) | func (s3 *S3) prepare(req *request) error {
    method setupHttpRequest (line 1121) | func (s3 *S3) setupHttpRequest(req *request) (*http.Request, error) {
    method doHttpRequest (line 1159) | func (s3 *S3) doHttpRequest(hreq *http.Request, resp interface{}) (*ht...
    method run (line 1207) | func (s3 *S3) run(req *request, resp interface{}) (*http.Response, err...
  type Bucket (line 48) | type Bucket struct
    method PutBucket (line 170) | func (b *Bucket) PutBucket(perm ACL) error {
    method DelBucket (line 188) | func (b *Bucket) DelBucket() (err error) {
    method Get (line 206) | func (b *Bucket) Get(path string) (data []byte, err error) {
    method GetReader (line 220) | func (b *Bucket) GetReader(path string) (rc io.ReadCloser, err error) {
    method GetResponse (line 232) | func (b *Bucket) GetResponse(path string) (resp *http.Response, err er...
    method GetResponseWithHeaders (line 241) | func (b *Bucket) GetResponseWithHeaders(path string, headers map[strin...
    method Exists (line 265) | func (b *Bucket) Exists(path string) (exists bool, err error) {
    method Head (line 303) | func (b *Bucket) Head(path string, headers map[string][]string) (*http...
    method Put (line 331) | func (b *Bucket) Put(path string, data []byte, contType string, perm A...
    method PutCopy (line 337) | func (b *Bucket) PutCopy(path string, perm ACL, options CopyOptions, s...
    method PutReader (line 359) | func (b *Bucket) PutReader(path string, r io.Reader, length int64, con...
    method PutBucketWebsite (line 460) | func (b *Bucket) PutBucketWebsite(configuration WebsiteConfiguration) ...
    method PutBucketSubresource (line 471) | func (b *Bucket) PutBucketSubresource(subresource string, r io.Reader,...
    method Del (line 490) | func (b *Bucket) Del(path string) error {
    method DelMulti (line 512) | func (b *Bucket) DelMulti(objects Delete) error {
    method List (line 629) | func (b *Bucket) List(prefix, delim, marker string, max int) (result *...
    method Versions (line 690) | func (b *Bucket) Versions(prefix, delim, keyMarker string, versionIdMa...
    method Location (line 728) | func (b *Bucket) Location() (string, error) {
    method GetPolicy (line 748) | func (b *Bucket) GetPolicy() ([]byte, error) {
    method PutPolicy (line 774) | func (b *Bucket) PutPolicy(data []byte) error {
    method URL (line 788) | func (b *Bucket) URL(path string) string {
    method SignedURL (line 807) | func (b *Bucket) SignedURL(path string, expires time.Time) string {
    method SignedURLWithArgs (line 813) | func (b *Bucket) SignedURLWithArgs(path string, expires time.Time, par...
    method SignedURLWithMethod (line 819) | func (b *Bucket) SignedURLWithMethod(method, path string, expires time...
    method UploadSignedURL (line 858) | func (b *Bucket) UploadSignedURL(path, method, content_type string, ex...
    method PostFormArgsEx (line 901) | func (b *Bucket) PostFormArgsEx(path string, expires time.Time, redire...
    method PostFormArgs (line 935) | func (b *Bucket) PostFormArgs(path string, expires time.Time, redirect...
  type Owner (line 54) | type Owner struct
  type Options (line 61) | type Options struct
    method addHeaders (line 377) | func (o Options) addHeaders(headers map[string][]string) {
  type CopyOptions (line 78) | type CopyOptions struct
    method addHeaders (line 410) | func (o CopyOptions) addHeaders(headers map[string][]string) {
  type CopyObjectResult (line 86) | type CopyObjectResult struct
  function New (line 98) | func New(auth aws.Auth, region aws.Region) *S3 {
  type BucketInfo (line 110) | type BucketInfo struct
  type GetServiceResp (line 115) | type GetServiceResp struct
  type ACL (line 156) | type ACL
  constant Private (line 159) | Private           = ACL("private")
  constant PublicRead (line 160) | PublicRead        = ACL("public-read")
  constant PublicReadWrite (line 161) | PublicReadWrite   = ACL("public-read-write")
  constant AuthenticatedRead (line 162) | AuthenticatedRead = ACL("authenticated-read")
  constant BucketOwnerRead (line 163) | BucketOwnerRead   = ACL("bucket-owner-read")
  constant BucketOwnerFull (line 164) | BucketOwnerFull   = ACL("bucket-owner-full-control")
  function makeXmlBuffer (line 423) | func makeXmlBuffer(doc []byte) *bytes.Buffer {
  type IndexDocument (line 430) | type IndexDocument struct
  type ErrorDocument (line 434) | type ErrorDocument struct
  type RoutingRule (line 438) | type RoutingRule struct
  type RedirectAllRequestsTo (line 444) | type RedirectAllRequestsTo struct
  type WebsiteConfiguration (line 449) | type WebsiteConfiguration struct
  type Delete (line 499) | type Delete struct
  type Object (line 504) | type Object struct
  type ListResp (line 543) | type ListResp struct
  type Key (line 562) | type Key struct
  type VersionsResp (line 664) | type VersionsResp struct
  type Version (line 677) | type Version struct
  type GetLocationResp (line 724) | type GetLocationResp struct
  type request (line 939) | type request struct
    method url (line 950) | func (req *request) url() (*url.URL, error) {
  function partiallyEscapedPath (line 1039) | func partiallyEscapedPath(path string) string {
  type Error (line 1221) | type Error struct
    method Error (line 1230) | func (e *Error) Error() string {
  function buildError (line 1234) | func buildError(r *http.Response) error {
  function shouldRetry (line 1260) | func shouldRetry(err error) bool {
  function hasCode (line 1298) | func hasCode(err error, code string) bool {

FILE: vendor/github.com/zackbloom/goamz/s3/sign.go
  function sign (line 42) | func sign(auth aws.Auth, method, canonicalPath string, params, headers m...

FILE: vendor/golang.org/x/crypto/ssh/terminal/terminal.go
  type EscapeCodes (line 16) | type EscapeCodes struct
  type Terminal (line 39) | type Terminal struct
    method queue (line 218) | func (t *Terminal) queue(data []rune) {
    method moveCursorToPos (line 232) | func (t *Terminal) moveCursorToPos(pos int) {
    method move (line 266) | func (t *Terminal) move(up, down, left, right int) {
    method clearLineToRight (line 297) | func (t *Terminal) clearLineToRight() {
    method setLine (line 304) | func (t *Terminal) setLine(newLine []rune, newPos int) {
    method advanceCursor (line 317) | func (t *Terminal) advanceCursor(places int) {
    method eraseNPreviousChars (line 340) | func (t *Terminal) eraseNPreviousChars(n int) {
    method countToLeftWord (line 365) | func (t *Terminal) countToLeftWord() int {
    method countToRightWord (line 390) | func (t *Terminal) countToRightWord() int {
    method handleKey (line 430) | func (t *Terminal) handleKey(key rune) (line string, ok bool) {
    method addKeyToLine (line 567) | func (t *Terminal) addKeyToLine(key rune) {
    method writeLine (line 583) | func (t *Terminal) writeLine(line []rune) {
    method Write (line 596) | func (t *Terminal) Write(buf []byte) (n int, err error) {
    method ReadPassword (line 643) | func (t *Terminal) ReadPassword(prompt string) (line string, err error) {
    method ReadLine (line 660) | func (t *Terminal) ReadLine() (line string, err error) {
    method readLine (line 667) | func (t *Terminal) readLine() (line string, err error) {
    method SetPrompt (line 748) | func (t *Terminal) SetPrompt(prompt string) {
    method clearAndRepaintLinePlusNPrevious (line 755) | func (t *Terminal) clearAndRepaintLinePlusNPrevious(numPrevLines int) {
    method SetSize (line 776) | func (t *Terminal) SetSize(width, height int) error {
    method SetBracketedPasteMode (line 846) | func (t *Terminal) SetBracketedPasteMode(on bool) {
  function NewTerminal (line 101) | func NewTerminal(c io.ReadWriter, prompt string) *Terminal {
  constant keyCtrlD (line 114) | keyCtrlD     = 4
  constant keyCtrlU (line 115) | keyCtrlU     = 21
  constant keyEnter (line 116) | keyEnter     = '\r'
  constant keyEscape (line 117) | keyEscape    = 27
  constant keyBackspace (line 118) | keyBackspace = 127
  constant keyUnknown (line 119) | keyUnknown   = 0xd800 /* UTF-16 surrogate area */ + iota
  constant keyUp (line 120) | keyUp
  constant keyDown (line 121) | keyDown
  constant keyLeft (line 122) | keyLeft
  constant keyRight (line 123) | keyRight
  constant keyAltLeft (line 124) | keyAltLeft
  constant keyAltRight (line 125) | keyAltRight
  constant keyHome (line 126) | keyHome
  constant keyEnd (line 127) | keyEnd
  constant keyDeleteWord (line 128) | keyDeleteWord
  constant keyDeleteLine (line 129) | keyDeleteLine
  constant keyClearScreen (line 130) | keyClearScreen
  constant keyPasteStart (line 131) | keyPasteStart
  constant keyPasteEnd (line 132) | keyPasteEnd
  function bytesToKey (line 140) | func bytesToKey(b []byte, pasteActive bool) (rune, []byte) {
  function isPrintable (line 225) | func isPrintable(key rune) bool {
  constant maxLineLength (line 302) | maxLineLength = 4096
  function visualLength (line 408) | func visualLength(runes []rune) int {
  type pasteIndicatorError (line 829) | type pasteIndicatorError struct
    method Error (line 831) | func (pasteIndicatorError) Error() string {
  type stRingBuffer (line 855) | type stRingBuffer struct
    method Add (line 865) | func (s *stRingBuffer) Add(a string) {
    method NthPreviousEntry (line 883) | func (s *stRingBuffer) NthPreviousEntry(n int) (value string, ok bool) {

FILE: vendor/golang.org/x/crypto/ssh/terminal/util.go
  type State (line 26) | type State struct
  function IsTerminal (line 31) | func IsTerminal(fd int) bool {
  function MakeRaw (line 40) | func MakeRaw(fd int) (*State, error) {
  function GetState (line 58) | func GetState(fd int) (*State, error) {
  function Restore (line 69) | func Restore(fd int, state *State) error {
  function GetSize (line 75) | func GetSize(fd int) (width, height int, err error) {
  function ReadPassword (line 87) | func ReadPassword(fd int) ([]byte, error) {

FILE: vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go
  constant ioctlReadTermios (line 11) | ioctlReadTermios = syscall.TIOCGETA
  constant ioctlWriteTermios (line 12) | ioctlWriteTermios = syscall.TIOCSETA

FILE: vendor/golang.org/x/crypto/ssh/terminal/util_linux.go
  constant ioctlReadTermios (line 10) | ioctlReadTermios = 0x5401
  constant ioctlWriteTermios (line 11) | ioctlWriteTermios = 0x5402

FILE: vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go
  type State (line 22) | type State struct
  function IsTerminal (line 25) | func IsTerminal(fd int) bool {
  function MakeRaw (line 32) | func MakeRaw(fd int) (*State, error) {
  function GetState (line 38) | func GetState(fd int) (*State, error) {
  function Restore (line 44) | func Restore(fd int, state *State) error {
  function GetSize (line 49) | func GetSize(fd int) (width, height int, err error) {
  function ReadPassword (line 56) | func ReadPassword(fd int) ([]byte, error) {

FILE: vendor/golang.org/x/crypto/ssh/terminal/util_windows.go
  constant enableLineInput (line 26) | enableLineInput       = 2
  constant enableEchoInput (line 27) | enableEchoInput       = 4
  constant enableProcessedInput (line 28) | enableProcessedInput  = 1
  constant enableWindowInput (line 29) | enableWindowInput     = 8
  constant enableMouseInput (line 30) | enableMouseInput      = 16
  constant enableInsertMode (line 31) | enableInsertMode      = 32
  constant enableQuickEditMode (line 32) | enableQuickEditMode   = 64
  constant enableExtendedFlags (line 33) | enableExtendedFlags   = 128
  constant enableAutoPosition (line 34) | enableAutoPosition    = 256
  constant enableProcessedOutput (line 35) | enableProcessedOutput = 1
  constant enableWrapAtEolOutput (line 36) | enableWrapAtEolOutput = 2
  type short (line 48) | type short
  type word (line 49) | type word
  type coord (line 51) | type coord struct
  type smallRect (line 55) | type smallRect struct
  type consoleScreenBufferInfo (line 61) | type consoleScreenBufferInfo struct
  type State (line 70) | type State struct
  function IsTerminal (line 75) | func IsTerminal(fd int) bool {
  function MakeRaw (line 84) | func MakeRaw(fd int) (*State, error) {
  function GetState (line 100) | func GetState(fd int) (*State, error) {
  function Restore (line 111) | func Restore(fd int, state *State) error {
  function GetSize (line 117) | func GetSize(fd int) (width, height int, err error) {
  function ReadPassword (line 129) | func ReadPassword(fd int) ([]byte, error) {

FILE: vendor/golang.org/x/net/html/atom/atom.go
  type Atom (line 21) | type Atom
    method String (line 24) | func (a Atom) String() string {
    method string (line 33) | func (a Atom) string() string {
  function fnv (line 38) | func fnv(h uint32, s []byte) uint32 {
  function match (line 46) | func match(s string, t []byte) bool {
  function Lookup (line 57) | func Lookup(s []byte) Atom {
  function String (line 73) | func String(s []byte) string {

FILE: vendor/golang.org/x/net/html/atom/gen.go
  function identifier (line 26) | func identifier(s string) string {
  function main (line 45) | func main() {
  type byLen (line 198) | type byLen
    method Less (line 200) | func (x byLen) Less(i, j int) bool { return len(x[i]) > len(x[j]) }
    method Swap (line 201) | func (x byLen) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
    method Len (line 202) | func (x byLen) Len() int           { return len(x) }
  function fnv (line 205) | func fnv(h uint32, s string) uint32 {
  type table (line 216) | type table struct
    method hash (line 224) | func (t *table) hash(s string) (h1, h2 uint32) {
    method init (line 236) | func (t *table) init(h0 uint32, k uint, x []string) bool {
    method insert (line 250) | func (t *table) insert(s string) bool {
    method push (line 272) | func (t *table) push(i uint32, depth int) bool {

FILE: vendor/golang.org/x/net/html/atom/table.go
  constant A (line 6) | A                   Atom = 0x1
  constant Abbr (line 7) | Abbr                Atom = 0x4
  constant Accept (line 8) | Accept              Atom = 0x2106
  constant AcceptCharset (line 9) | AcceptCharset       Atom = 0x210e
  constant Accesskey (line 10) | Accesskey           Atom = 0x3309
  constant Action (line 11) | Action              Atom = 0x1f606
  constant Address (line 12) | Address             Atom = 0x4f307
  constant Align (line 13) | Align               Atom = 0x1105
  constant Alt (line 14) | Alt                 Atom = 0x4503
  constant Annotation (line 15) | Annotation          Atom = 0x1670a
  constant AnnotationXml (line 16) | AnnotationXml       Atom = 0x1670e
  constant Applet (line 17) | Applet              Atom = 0x2b306
  constant Area (line 18) | Area                Atom = 0x2fa04
  constant Article (line 19) | Article             Atom = 0x38807
  constant Aside (line 20) | Aside               Atom = 0x8305
  constant Async (line 21) | Async               Atom = 0x7b05
  constant Audio (line 22) | Audio               Atom = 0xa605
  constant Autocomplete (line 23) | Autocomplete        Atom = 0x1fc0c
  constant Autofocus (line 24) | Autofocus           Atom = 0xb309
  constant Autoplay (line 25) | Autoplay            Atom = 0xce08
  constant B (line 26) | B                   Atom = 0x101
  constant Base (line 27) | Base                Atom = 0xd604
  constant Basefont (line 28) | Basefont            Atom = 0xd608
  constant Bdi (line 29) | Bdi                 Atom = 0x1a03
  constant Bdo (line 30) | Bdo                 Atom = 0xe703
  constant Bgsound (line 31) | Bgsound             Atom = 0x11807
  constant Big (line 32) | Big                 Atom = 0x12403
  constant Blink (line 33) | Blink               Atom = 0x12705
  constant Blockquote (line 34) | Blockquote          Atom = 0x12c0a
  constant Body (line 35) | Body                Atom = 0x2f04
  constant Br (line 36) | Br                  Atom = 0x202
  constant Button (line 37) | Button              Atom = 0x13606
  constant Canvas (line 38) | Canvas              Atom = 0x7f06
  constant Caption (line 39) | Caption             Atom = 0x1bb07
  constant Center (line 40) | Center              Atom = 0x5b506
  constant Challenge (line 41) | Challenge           Atom = 0x21f09
  constant Charset (line 42) | Charset             Atom = 0x2807
  constant Checked (line 43) | Checked             Atom = 0x32807
  constant Cite (line 44) | Cite                Atom = 0x3c804
  constant Class (line 45) | Class               Atom = 0x4de05
  constant Code (line 46) | Code                Atom = 0x14904
  constant Col (line 47) | Col                 Atom = 0x15003
  constant Colgroup (line 48) | Colgroup            Atom = 0x15008
  constant Color (line 49) | Color               Atom = 0x15d05
  constant Cols (line 50) | Cols                Atom = 0x16204
  constant Colspan (line 51) | Colspan             Atom = 0x16207
  constant Command (line 52) | Command             Atom = 0x17507
  constant Content (line 53) | Content             Atom = 0x42307
  constant Contenteditable (line 54) | Contenteditable     Atom = 0x4230f
  constant Contextmenu (line 55) | Contextmenu         Atom = 0x3310b
  constant Controls (line 56) | Controls            Atom = 0x18808
  constant Coords (line 57) | Coords              Atom = 0x19406
  constant Crossorigin (line 58) | Crossorigin         Atom = 0x19f0b
  constant Data (line 59) | Data                Atom = 0x44a04
  constant Datalist (line 60) | Datalist            Atom = 0x44a08
  constant Datetime (line 61) | Datetime            Atom = 0x23c08
  constant Dd (line 62) | Dd                  Atom = 0x26702
  constant Default (line 63) | Default             Atom = 0x8607
  constant Defer (line 64) | Defer               Atom = 0x14b05
  constant Del (line 65) | Del                 Atom = 0x3ef03
  constant Desc (line 66) | Desc                Atom = 0x4db04
  constant Details (line 67) | Details             Atom = 0x4807
  constant Dfn (line 68) | Dfn                 Atom = 0x6103
  constant Dialog (line 69) | Dialog              Atom = 0x1b06
  constant Dir (line 70) | Dir                 Atom = 0x6903
  constant Dirname (line 71) | Dirname             Atom = 0x6907
  constant Disabled (line 72) | Disabled            Atom = 0x10c08
  constant Div (line 73) | Div                 Atom = 0x11303
  constant Dl (line 74) | Dl                  Atom = 0x11e02
  constant Download (line 75) | Download            Atom = 0x40008
  constant Draggable (line 76) | Draggable           Atom = 0x17b09
  constant Dropzone (line 77) | Dropzone            Atom = 0x39108
  constant Dt (line 78) | Dt                  Atom = 0x50902
  constant Em (line 79) | Em                  Atom = 0x6502
  constant Embed (line 80) | Embed               Atom = 0x6505
  constant Enctype (line 81) | Enctype             Atom = 0x21107
  constant Face (line 82) | Face                Atom = 0x5b304
  constant Fieldset (line 83) | Fieldset            Atom = 0x1b008
  constant Figcaption (line 84) | Figcaption          Atom = 0x1b80a
  constant Figure (line 85) | Figure              Atom = 0x1cc06
  constant Font (line 86) | Font                Atom = 0xda04
  constant Footer (line 87) | Footer              Atom = 0x8d06
  constant For (line 88) | For                 Atom = 0x1d803
  constant ForeignObject (line 89) | ForeignObject       Atom = 0x1d80d
  constant Foreignobject (line 90) | Foreignobject       Atom = 0x1e50d
  constant Form (line 91) | Form                Atom = 0x1f204
  constant Formaction (line 92) | Formaction          Atom = 0x1f20a
  constant Formenctype (line 93) | Formenctype         Atom = 0x20d0b
  constant Formmethod (line 94) | Formmethod          Atom = 0x2280a
  constant Formnovalidate (line 95) | Formnovalidate      Atom = 0x2320e
  constant Formtarget (line 96) | Formtarget          Atom = 0x2470a
  constant Frame (line 97) | Frame               Atom = 0x9a05
  constant Frameset (line 98) | Frameset            Atom = 0x9a08
  constant H1 (line 99) | H1                  Atom = 0x26e02
  constant H2 (line 100) | H2                  Atom = 0x29402
  constant H3 (line 101) | H3                  Atom = 0x2a702
  constant H4 (line 102) | H4                  Atom = 0x2e902
  constant H5 (line 103) | H5                  Atom = 0x2f302
  constant H6 (line 104) | H6                  Atom = 0x50b02
  constant Head (line 105) | Head                Atom = 0x2d504
  constant Header (line 106) | Header              Atom = 0x2d506
  constant Headers (line 107) | Headers             Atom = 0x2d507
  constant Height (line 108) | Height              Atom = 0x25106
  constant Hgroup (line 109) | Hgroup              Atom = 0x25906
  constant Hidden (line 110) | Hidden              Atom = 0x26506
  constant High (line 111) | High                Atom = 0x26b04
  constant Hr (line 112) | Hr                  Atom = 0x27002
  constant Href (line 113) | Href                Atom = 0x27004
  constant Hreflang (line 114) | Hreflang            Atom = 0x27008
  constant Html (line 115) | Html                Atom = 0x25504
  constant HttpEquiv (line 116) | HttpEquiv           Atom = 0x2780a
  constant I (line 117) | I                   Atom = 0x601
  constant Icon (line 118) | Icon                Atom = 0x42204
  constant Id (line 119) | Id                  Atom = 0x8502
  constant Iframe (line 120) | Iframe              Atom = 0x29606
  constant Image (line 121) | Image               Atom = 0x29c05
  constant Img (line 122) | Img                 Atom = 0x2a103
  constant Input (line 123) | Input               Atom = 0x3e805
  constant Inputmode (line 124) | Inputmode           Atom = 0x3e809
  constant Ins (line 125) | Ins                 Atom = 0x1a803
  constant Isindex (line 126) | Isindex             Atom = 0x2a907
  constant Ismap (line 127) | Ismap               Atom = 0x2b005
  constant Itemid (line 128) | Itemid              Atom = 0x33c06
  constant Itemprop (line 129) | Itemprop            Atom = 0x3c908
  constant Itemref (line 130) | Itemref             Atom = 0x5ad07
  constant Itemscope (line 131) | Itemscope           Atom = 0x2b909
  constant Itemtype (line 132) | Itemtype            Atom = 0x2c308
  constant Kbd (line 133) | Kbd                 Atom = 0x1903
  constant Keygen (line 134) | Keygen              Atom = 0x3906
  constant Keytype (line 135) | Keytype             Atom = 0x53707
  constant Kind (line 136) | Kind                Atom = 0x10904
  constant Label (line 137) | Label               Atom = 0xf005
  constant Lang (line 138) | Lang                Atom = 0x27404
  constant Legend (line 139) | Legend              Atom = 0x18206
  constant Li (line 140) | Li                  Atom = 0x1202
  constant Link (line 141) | Link                Atom = 0x12804
  constant List (line 142) | List                Atom = 0x44e04
  constant Listing (line 143) | Listing             Atom = 0x44e07
  constant Loop (line 144) | Loop                Atom = 0xf404
  constant Low (line 145) | Low                 Atom = 0x11f03
  constant Malignmark (line 146) | Malignmark          Atom = 0x100a
  constant Manifest (line 147) | Manifest            Atom = 0x5f108
  constant Map (line 148) | Map                 Atom = 0x2b203
  constant Mark (line 149) | Mark                Atom = 0x1604
  constant Marquee (line 150) | Marquee             Atom = 0x2cb07
  constant Math (line 151) | Math                Atom = 0x2d204
  constant Max (line 152) | Max                 Atom = 0x2e103
  constant Maxlength (line 153) | Maxlength           Atom = 0x2e109
  constant Media (line 154) | Media               Atom = 0x6e05
  constant Mediagroup (line 155) | Mediagroup          Atom = 0x6e0a
  constant Menu (line 156) | Menu                Atom = 0x33804
  constant Menuitem (line 157) | Menuitem            Atom = 0x33808
  constant Meta (line 158) | Meta                Atom = 0x45d04
  constant Meter (line 159) | Meter               Atom = 0x24205
  constant Method (line 160) | Method              Atom = 0x22c06
  constant Mglyph (line 161) | Mglyph              Atom = 0x2a206
  constant Mi (line 162) | Mi                  Atom = 0x2eb02
  constant Min (line 163) | Min                 Atom = 0x2eb03
  constant Minlength (line 164) | Minlength           Atom = 0x2eb09
  constant Mn (line 165) | Mn                  Atom = 0x23502
  constant Mo (line 166) | Mo                  Atom = 0x3ed02
  constant Ms (line 167) | Ms                  Atom = 0x2bc02
  constant Mtext (line 168) | Mtext               Atom = 0x2f505
  constant Multiple (line 169) | Multiple            Atom = 0x30308
  constant Muted (line 170) | Muted               Atom = 0x30b05
  constant Name (line 171) | Name                Atom = 0x6c04
  constant Nav (line 172) | Nav                 Atom = 0x3e03
  constant Nobr (line 173) | Nobr                Atom = 0x5704
  constant Noembed (line 174) | Noembed             Atom = 0x6307
  constant Noframes (line 175) | Noframes            Atom = 0x9808
  constant Noscript (line 176) | Noscript            Atom = 0x3d208
  constant Novalidate (line 177) | Novalidate          Atom = 0x2360a
  constant Object (line 178) | Object              Atom = 0x1ec06
  constant Ol (line 179) | Ol                  Atom = 0xc902
  constant Onabort (line 180) | Onabort             Atom = 0x13a07
  constant Onafterprint (line 181) | Onafterprint        Atom = 0x1c00c
  constant Onautocomplete (line 182) | Onautocomplete      Atom = 0x1fa0e
  constant Onautocompleteerror (line 183) | Onautocompleteerror Atom = 0x1fa13
  constant Onbeforeprint (line 184) | Onbeforeprint       Atom = 0x6040d
  constant Onbeforeunload (line 185) | Onbeforeunload      Atom = 0x4e70e
  constant Onblur (line 186) | Onblur              Atom = 0xaa06
  constant Oncancel (line 187) | Oncancel            Atom = 0xe908
  constant Oncanplay (line 188) | Oncanplay           Atom = 0x28509
  constant Oncanplaythrough (line 189) | Oncanplaythrough    Atom = 0x28510
  constant Onchange (line 190) | Onchange            Atom = 0x3a708
  constant Onclick (line 191) | Onclick             Atom = 0x31007
  constant Onclose (line 192) | Onclose             Atom = 0x31707
  constant Oncontextmenu (line 193) | Oncontextmenu       Atom = 0x32f0d
  constant Oncuechange (line 194) | Oncuechange         Atom = 0x3420b
  constant Ondblclick (line 195) | Ondblclick          Atom = 0x34d0a
  constant Ondrag (line 196) | Ondrag              Atom = 0x35706
  constant Ondragend (line 197) | Ondragend           Atom = 0x35709
  constant Ondragenter (line 198) | Ondragenter         Atom = 0x3600b
  constant Ondragleave (line 199) | Ondragleave         Atom = 0x36b0b
  constant Ondragover (line 200) | Ondragover          Atom = 0x3760a
  constant Ondragstart (line 201) | Ondragstart         Atom = 0x3800b
  constant Ondrop (line 202) | Ondrop              Atom = 0x38f06
  constant Ondurationchange (line 203) | Ondurationchange    Atom = 0x39f10
  constant Onemptied (line 204) | Onemptied           Atom = 0x39609
  constant Onended (line 205) | Onended             Atom = 0x3af07
  constant Onerror (line 206) | Onerror             Atom = 0x3b607
  constant Onfocus (line 207) | Onfocus             Atom = 0x3bd07
  constant Onhashchange (line 208) | Onhashchange        Atom = 0x3da0c
  constant Oninput (line 209) | Oninput             Atom = 0x3e607
  constant Oninvalid (line 210) | Oninvalid           Atom = 0x3f209
  constant Onkeydown (line 211) | Onkeydown           Atom = 0x3fb09
  constant Onkeypress (line 212) | Onkeypress          Atom = 0x4080a
  constant Onkeyup (line 213) | Onkeyup             Atom = 0x41807
  constant Onlanguagechange (line 214) | Onlanguagechange    Atom = 0x43210
  constant Onload (line 215) | Onload              Atom = 0x44206
  constant Onloadeddata (line 216) | Onloadeddata        Atom = 0x4420c
  constant Onloadedmetadata (line 217) | Onloadedmetadata    Atom = 0x45510
  constant Onloadstart (line 218) | Onloadstart         Atom = 0x46b0b
  constant Onmessage (line 219) | Onmessage           Atom = 0x47609
  constant Onmousedown (line 220) | Onmousedown         Atom = 0x47f0b
  constant Onmousemove (line 221) | Onmousemove         Atom = 0x48a0b
  constant Onmouseout (line 222) | Onmouseout          Atom = 0x4950a
  constant Onmouseover (line 223) | Onmouseover         Atom = 0x4a20b
  constant Onmouseup (line 224) | Onmouseup           Atom = 0x4ad09
  constant Onmousewheel (line 225) | Onmousewheel        Atom = 0x4b60c
  constant Onoffline (line 226) | Onoffline           Atom = 0x4c209
  constant Ononline (line 227) | Ononline            Atom = 0x4cb08
  constant Onpagehide (line 228) | Onpagehide          Atom = 0x4d30a
  constant Onpageshow (line 229) | Onpageshow          Atom = 0x4fe0a
  constant Onpause (line 230) | Onpause             Atom = 0x50d07
  constant Onplay (line 231) | Onplay              Atom = 0x51706
  constant Onplaying (line 232) | Onplaying           Atom = 0x51709
  constant Onpopstate (line 233) | Onpopstate          Atom = 0x5200a
  constant Onprogress (line 234) | Onprogress          Atom = 0x52a0a
  constant Onratechange (line 235) | Onratechange        Atom = 0x53e0c
  constant Onreset (line 236) | Onreset             Atom = 0x54a07
  constant Onresize (line 237) | Onresize            Atom = 0x55108
  constant Onscroll (line 238) | Onscroll            Atom = 0x55f08
  constant Onseeked (line 239) | Onseeked            Atom = 0x56708
  constant Onseeking (line 240) | Onseeking           Atom = 0x56f09
  constant Onselect (line 241) | Onselect            Atom = 0x57808
  constant Onshow (line 242) | Onshow              Atom = 0x58206
  constant Onsort (line 243) | Onsort              Atom = 0x58b06
  constant Onstalled (line 244) | Onstalled           Atom = 0x59509
  constant Onstorage (line 245) | Onstorage           Atom = 0x59e09
  constant Onsubmit (line 246) | Onsubmit            Atom = 0x5a708
  constant Onsuspend (line 247) | Onsuspend           Atom = 0x5bb09
  constant Ontimeupdate (line 248) | Ontimeupdate        Atom = 0xdb0c
  constant Ontoggle (line 249) | Ontoggle            Atom = 0x5c408
  constant Onunload (line 250) | Onunload            Atom = 0x5cc08
  constant Onvolumechange (line 251) | Onvolumechange      Atom = 0x5d40e
  constant Onwaiting (line 252) | Onwaiting           Atom = 0x5e209
  constant Open (line 253) | Open                Atom = 0x3cf04
  constant Optgroup (line 254) | Optgroup            Atom = 0xf608
  constant Optimum (line 255) | Optimum             Atom = 0x5eb07
  constant Option (line 256) | Option              Atom = 0x60006
  constant Output (line 257) | Output              Atom = 0x49c06
  constant P (line 258) | P                   Atom = 0xc01
  constant Param (line 259) | Param               Atom = 0xc05
  constant Pattern (line 260) | Pattern             Atom = 0x5107
  constant Ping (line 261) | Ping                Atom = 0x7704
  constant Placeholder (line 262) | Placeholder         Atom = 0xc30b
  constant Plaintext (line 263) | Plaintext           Atom = 0xfd09
  constant Poster (line 264) | Poster              Atom = 0x15706
  constant Pre (line 265) | Pre                 Atom = 0x25e03
  constant Preload (line 266) | Preload             Atom = 0x25e07
  constant Progress (line 267) | Progress            Atom = 0x52c08
  constant Prompt (line 268) | Prompt              Atom = 0x5fa06
  constant Public (line 269) | Public              Atom = 0x41e06
  constant Q (line 270) | Q                   Atom = 0x13101
  constant Radiogroup (line 271) | Radiogroup          Atom = 0x30a
  constant Readonly (line 272) | Readonly            Atom = 0x2fb08
  constant Rel (line 273) | Rel                 Atom = 0x25f03
  constant Required (line 274) | Required            Atom = 0x1d008
  constant Reversed (line 275) | Reversed            Atom = 0x5a08
  constant Rows (line 276) | Rows                Atom = 0x9204
  constant Rowspan (line 277) | Rowspan             Atom = 0x9207
  constant Rp (line 278) | Rp                  Atom = 0x1c602
  constant Rt (line 279) | Rt                  Atom = 0x13f02
  constant Ruby (line 280) | Ruby                Atom = 0xaf04
  constant S (line 281) | S                   Atom = 0x2c01
  constant Samp (line 282) | Samp                Atom = 0x4e04
  constant Sandbox (line 283) | Sandbox             Atom = 0xbb07
  constant Scope (line 284) | Scope               Atom = 0x2bd05
  constant Scoped (line 285) | Scoped              Atom = 0x2bd06
  constant Script (line 286) | Script              Atom = 0x3d406
  constant Seamless (line 287) | Seamless            Atom = 0x31c08
  constant Section (line 288) | Section             Atom = 0x4e207
  constant Select (line 289) | Select              Atom = 0x57a06
  constant Selected (line 290) | Selected            Atom = 0x57a08
  constant Shape (line 291) | Shape               Atom = 0x4f905
  constant Size (line 292) | Size                Atom = 0x55504
  constant Sizes (line 293) | Sizes               Atom = 0x55505
  constant Small (line 294) | Small               Atom = 0x18f05
  constant Sortable (line 295) | Sortable            Atom = 0x58d08
  constant Sorted (line 296) | Sorted              Atom = 0x19906
  constant Source (line 297) | Source              Atom = 0x1aa06
  constant Spacer (line 298) | Spacer              Atom = 0x2db06
  constant Span (line 299) | Span                Atom = 0x9504
  constant Spellcheck (line 300) | Spellcheck          Atom = 0x3230a
  constant Src (line 301) | Src                 Atom = 0x3c303
  constant Srcdoc (line 302) | Srcdoc              Atom = 0x3c306
  constant Srclang (line 303) | Srclang             Atom = 0x41107
  constant Start (line 304) | Start               Atom = 0x38605
  constant Step (line 305) | Step                Atom = 0x5f704
  constant Strike (line 306) | Strike              Atom = 0x53306
  constant Strong (line 307) | Strong              Atom = 0x55906
  constant Style (line 308) | Style               Atom = 0x61105
  constant Sub (line 309) | Sub                 Atom = 0x5a903
  constant Summary (line 310) | Summary             Atom = 0x61607
  constant Sup (line 311) | Sup                 Atom = 0x61d03
  constant Svg (line 312) | Svg                 Atom = 0x62003
  constant System (line 313) | System              Atom = 0x62306
  constant Tabindex (line 314) | Tabindex            Atom = 0x46308
  constant Table (line 315) | Table               Atom = 0x42d05
  constant Target (line 316) | Target              Atom = 0x24b06
  constant Tbody (line 317) | Tbody               Atom = 0x2e05
  constant Td (line 318) | Td                  Atom = 0x4702
  constant Template (line 319) | Template            Atom = 0x62608
  constant Textarea (line 320) | Textarea            Atom = 0x2f608
  constant Tfoot (line 321) | Tfoot               Atom = 0x8c05
  constant Th (line 322) | Th                  Atom = 0x22e02
  constant Thead (line 323) | Thead               Atom = 0x2d405
  constant Time (line 324) | Time                Atom = 0xdd04
  constant Title (line 325) | Title               Atom = 0xa105
  constant Tr (line 326) | Tr                  Atom = 0x10502
  constant Track (line 327) | Track               Atom = 0x10505
  constant Translate (line 328) | Translate           Atom = 0x14009
  constant Tt (line 329) | Tt                  Atom = 0x5302
  constant Type (line 330) | Type                Atom = 0x21404
  constant Typemustmatch (line 331) | Typemustmatch       Atom = 0x2140d
  constant U (line 332) | U                   Atom = 0xb01
  constant Ul (line 333) | Ul                  Atom = 0x8a02
  constant Usemap (line 334) | Usemap              Atom = 0x51106
  constant Value (line 335) | Value               Atom = 0x4005
  constant Var (line 336) | Var                 Atom = 0x11503
  constant Video (line 337) | Video               Atom = 0x28105
  constant Wbr (line 338) | Wbr                 Atom = 0x12103
  constant Width (line 339) | Width               Atom = 0x50705
  constant Wrap (line 340) | Wrap                Atom = 0x58704
  constant Xmp (line 341) | Xmp                 Atom = 0xc103
  constant hash0 (line 344) | hash0 = 0xc17da63e
  constant maxAtomLen (line 346) | maxAtomLen = 19
  constant atomText (line 687) | atomText = "abbradiogrouparamalignmarkbdialogaccept-charsetbodyaccesskey" +

FILE: vendor/golang.org/x/net/html/const.go
  function isSpecialElement (line 94) | func isSpecialElement(element *Node) bool {

FILE: vendor/golang.org/x/net/html/doctype.go
  function parseDoctype (line 16) | func parseDoctype(s string) (n *Node, quirks bool) {

FILE: vendor/golang.org/x/net/html/entity.go
  constant longestEntityWithoutSemicolon (line 8) | longestEntityWithoutSemicolon = 6

FILE: vendor/golang.org/x/net/html/escape.go
  function unescapeEntity (line 57) | func unescapeEntity(b []byte, dst, src int, attribute bool) (dst1, src1 ...
  function unescape (line 167) | func unescape(b []byte, attribute bool) []byte {
  function lower (line 187) | func lower(b []byte) []byte {
  constant escapedChars (line 196) | escapedChars = "&'<>\"\r"
  function escape (line 198) | func escape(w writer, s string) error {
  function EscapeString (line 237) | func EscapeString(s string) string {
  function UnescapeString (line 251) | func UnescapeString(s string) string {

FILE: vendor/golang.org/x/net/html/foreign.go
  function adjustAttributeNames (line 11) | func adjustAttributeNames(aa []Attribute, nameMap map[string]string) {
  function adjustForeignAttributes (line 19) | func adjustForeignAttributes(aa []Attribute) {
  function htmlIntegrationPoint (line 34) | func htmlIntegrationPoint(n *Node) bool {
  function mathMLTextIntegrationPoint (line 59) | func mathMLTextIntegrationPoint(n *Node) bool {

FILE: vendor/golang.org/x/net/html/node.go
  type NodeType (line 12) | type NodeType
  constant ErrorNode (line 15) | ErrorNode NodeType = iota
  constant TextNode (line 16) | TextNode
  constant DocumentNode (line 17) | DocumentNode
  constant ElementNode (line 18) | ElementNode
  constant CommentNode (line 19) | CommentNode
  constant DoctypeNode (line 20) | DoctypeNode
  constant scopeMarkerNode (line 21) | scopeMarkerNode
  type Node (line 38) | type Node struct
    method InsertBefore (line 53) | func (n *Node) InsertBefore(newChild, oldChild *Node) {
    method AppendChild (line 81) | func (n *Node) AppendChild(c *Node) {
    method RemoveChild (line 100) | func (n *Node) RemoveChild(c *Node) {
    method clone (line 135) | func (n *Node) clone() *Node {
  function reparentChildren (line 122) | func reparentChildren(dst, src *Node) {
  type nodeStack (line 147) | type nodeStack
    method pop (line 150) | func (s *nodeStack) pop() *Node {
    method top (line 158) | func (s *nodeStack) top() *Node {
    method index (line 167) | func (s *nodeStack) index(n *Node) int {
    method insert (line 177) | func (s *nodeStack) insert(i int, n *Node) {
    method remove (line 184) | func (s *nodeStack) remove(n *Node) {

FILE: vendor/golang.org/x/net/html/parse.go
  type parser (line 18) | type parser struct
    method top (line 52) | func (p *parser) top() *Node {
    method popUntil (line 97) | func (p *parser) popUntil(s scope, matchTags ...a.Atom) bool {
    method indexOfElementInScope (line 108) | func (p *parser) indexOfElementInScope(s scope, matchTags ...a.Atom) i...
    method elementInScope (line 154) | func (p *parser) elementInScope(s scope, matchTags ...a.Atom) bool {
    method clearStackToContext (line 160) | func (p *parser) clearStackToContext(s scope) {
    method generateImpliedEndTags (line 188) | func (p *parser) generateImpliedEndTags(exceptions ...string) {
    method addChild (line 212) | func (p *parser) addChild(n *Node) {
    method shouldFosterParent (line 226) | func (p *parser) shouldFosterParent() bool {
    method fosterParent (line 238) | func (p *parser) fosterParent(n *Node) {
    method addText (line 273) | func (p *parser) addText(text string) {
    method addElement (line 298) | func (p *parser) addElement() {
    method addFormattingElement (line 308) | func (p *parser) addFormattingElement() {
    method clearActiveFormattingElements (line 355) | func (p *parser) clearActiveFormattingElements() {
    method reconstructActiveFormattingElements (line 365) | func (p *parser) reconstructActiveFormattingElements() {
    method acknowledgeSelfClosingTag (line 394) | func (p *parser) acknowledgeSelfClosingTag() {
    method setOriginalIM (line 407) | func (p *parser) setOriginalIM() {
    method resetInsertionMode (line 415) | func (p *parser) resetInsertionMode() {
    method inBodyEndTagFormatting (line 1038) | func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom) {
    method inBodyEndTagOther (line 1165) | func (p *parser) inBodyEndTagOther(tagAtom a.Atom) {
    method inForeignContent (line 1928) | func (p *parser) inForeignContent() bool {
    method parseImpliedToken (line 1958) | func (p *parser) parseImpliedToken(t TokenType, dataAtom a.Atom, data ...
    method parseCurrentToken (line 1972) | func (p *parser) parseCurrentToken() {
    method parse (line 1993) | func (p *parser) parse() error {
  type scope (line 68) | type scope
  constant defaultScope (line 71) | defaultScope scope = iota
  constant listItemScope (line 72) | listItemScope
  constant buttonScope (line 73) | buttonScope
  constant tableScope (line 74) | tableScope
  constant tableRowScope (line 75) | tableRowScope
  constant tableBodyScope (line 76) | tableBodyScope
  constant selectScope (line 77) | selectScope
  type insertionMode (line 402) | type insertionMode
  constant whitespace (line 453) | whitespace = " \t\r\n\f"
  function initialIM (line 456) | func initialIM(p *parser) bool {
  function beforeHTMLIM (line 483) | func beforeHTMLIM(p *parser) bool {
  function beforeHeadIM (line 521) | func beforeHeadIM(p *parser) bool {
  function inHeadIM (line 564) | func inHeadIM(p *parser) bool {
  function afterHeadIM (line 626) | func afterHeadIM(p *parser) bool {
  function copyAttributes (line 684) | func copyAttributes(dst *Node, src Token) {
  function inBodyIM (line 701) | func inBodyIM(p *parser) bool {
  function textIM (line 1178) | func textIM(p *parser) bool {
  function inTableIM (line 1207) | func inTableIM(p *parser) bool {
  function inCaptionIM (line 1313) | func inCaptionIM(p *parser) bool {
  function inColumnGroupIM (line 1359) | func inColumnGroupIM(p *parser) bool {
  function inTableBodyIM (line 1412) | func inTableBodyIM(p *parser) bool {
  function inRowIM (line 1464) | func inRowIM(p *parser) bool {
  function inCellIM (line 1515) | func inCellIM(p *parser) bool {
  function inSelectIM (line 1564) | func inSelectIM(p *parser) bool {
  function inSelectInTableIM (line 1636) | func inSelectInTableIM(p *parser) bool {
  function afterBodyIM (line 1654) | func afterBodyIM(p *parser) bool {
  function inFramesetIM (line 1692) | func inFramesetIM(p *parser) bool {
  function afterFramesetIM (line 1742) | func afterFramesetIM(p *parser) bool {
  function afterAfterBodyIM (line 1781) | func afterAfterBodyIM(p *parser) bool {
  function afterAfterFramesetIM (line 1810) | func afterAfterFramesetIM(p *parser) bool {
  constant whitespaceOrNUL (line 1845) | whitespaceOrNUL = whitespace + "\x00"
  function parseForeignContent (line 1848) | func parseForeignContent(p *parser) bool {
  function Parse (line 2016) | func Parse(r io.Reader) (*Node, error) {
  function ParseFragment (line 2036) | func ParseFragment(r io.Reader, context *Node) ([]*Node, error) {

FILE: vendor/golang.org/x/net/html/render.go
  type writer (line 15) | type writer interface
  function Render (line 45) | func Render(w io.Writer, n *Node) error {
  function render (line 60) | func render(w writer, n *Node) error {
  function render1 (line 68) | func render1(w writer, n *Node) error {
  function writeQuoted (line 235) | func writeQuoted(w writer, s string) error {

FILE: vendor/golang.org/x/net/html/token.go
  type TokenType (line 18) | type TokenType
    method String (line 41) | func (t TokenType) String() string {
  constant ErrorToken (line 22) | ErrorToken TokenType = iota
  constant TextToken (line 24) | TextToken
  constant StartTagToken (line 26) | StartTagToken
  constant EndTagToken (line 28) | EndTagToken
  constant SelfClosingTagToken (line 30) | SelfClosingTagToken
  constant CommentToken (line 32) | CommentToken
  constant DoctypeToken (line 34) | DoctypeToken
  type Attribute (line 67) | type Attribute struct
  type Token (line 76) | type Token struct
    method tagString (line 84) | func (t Token) tagString() string {
    method String (line 100) | func (t Token) String() string {
  type span (line 122) | type span struct
  type Tokenizer (line 127) | type Tokenizer struct
    method AllowCDATA (line 188) | func (z *Tokenizer) AllowCDATA(allowCDATA bool) {
    method NextIsNotRawText (line 216) | func (z *Tokenizer) NextIsNotRawText() {
    method Err (line 222) | func (z *Tokenizer) Err() error {
    method readByte (line 234) | func (z *Tokenizer) readByte() byte {
    method Buffered (line 290) | func (z *Tokenizer) Buffered() []byte {
    method skipWhiteSpace (line 308) | func (z *Tokenizer) skipWhiteSpace() {
    method readRawOrRCDATA (line 329) | func (z *Tokenizer) readRawOrRCDATA() {
    method readRawEndTag (line 366) | func (z *Tokenizer) readRawEndTag() bool {
    method readScript (line 393) | func (z *Tokenizer) readScript() {
    method readComment (line 600) | func (z *Tokenizer) readComment() {
    method readUntilCloseAngle (line 645) | func (z *Tokenizer) readUntilCloseAngle() {
    method readMarkupDeclaration (line 663) | func (z *Tokenizer) readMarkupDeclaration() TokenType {
    method readDoctype (line 692) | func (z *Tokenizer) readDoctype() bool {
    method readCDATA (line 717) | func (z *Tokenizer) readCDATA() bool {
    method startTagIn (line 756) | func (z *Tokenizer) startTagIn(ss ...string) bool {
    method readStartTag (line 778) | func (z *Tokenizer) readStartTag() TokenType {
    method readTag (line 816) | func (z *Tokenizer) readTag(saveAttr bool) {
    method readTagName (line 845) | func (z *Tokenizer) readTagName() {
    method readTagAttrKey (line 867) | func (z *Tokenizer) readTagAttrKey() {
    method readTagAttrVal (line 888) | func (z *Tokenizer) readTagAttrVal() {
    method Next (line 950) | func (z *Tokenizer) Next() TokenType {
    method Raw (line 1070) | func (z *Tokenizer) Raw() []byte {
    method Text (line 1113) | func (z *Tokenizer) Text() []byte {
    method TagName (line 1134) | func (z *Tokenizer) TagName() (name []byte, hasAttr bool) {
    method TagAttr (line 1150) | func (z *Tokenizer) TagAttr() (key, val []byte, moreAttr bool) {
    method Token (line 1166) | func (z *Tokenizer) Token() Token {
    method SetMaxBuf (line 1189) | func (z *Tokenizer) SetMaxBuf(n int) {
  function readAtLeastOneByte (line 297) | func readAtLeastOneByte(r io.Reader, b []byte) (int, error) {
  function convertNewlines (line 1076) | func convertNewlines(s []byte) []byte {
  function NewTokenizer (line 1195) | func NewTokenizer(r io.Reader) *Tokenizer {
  function NewTokenizerFragment (line 1207) | func NewTokenizerFragment(r io.Reader, contextTag string) *Tokenizer {

FILE: vendor/golang.org/x/net/publicsuffix/gen.go
  constant nodesBitsChildren (line 41) | nodesBitsChildren   = 9
  constant nodesBitsICANN (line 42) | nodesBitsICANN      = 1
  constant nodesBitsTextOffset (line 43) | nodesBitsTextOffset = 15
  constant nodesBitsTextLength (line 44) | nodesBitsTextLength = 6
  constant childrenBitsWildcard (line 47) | childrenBitsWildcard = 1
  constant childrenBitsNodeType (line 48) | childrenBitsNodeType = 2
  constant childrenBitsHi (line 49) | childrenBitsHi       = 14
  constant childrenBitsLo (line 50) | childrenBitsLo       = 14
  function max (line 61) | func max(a, b int) int {
  function u32max (line 68) | func u32max(a, b uint32) uint32 {
  constant nodeTypeNormal (line 76) | nodeTypeNormal     = 0
  constant nodeTypeException (line 77) | nodeTypeException  = 1
  constant nodeTypeParentOnly (line 78) | nodeTypeParentOnly = 2
  constant numNodeType (line 79) | numNodeType        = 3
  function nodeTypeStr (line 82) | func nodeTypeStr(n int) string {
  function main (line 114) | func main() {
  function main1 (line 121) | func main1() error {
  function printTest (line 247) | func printTest(w io.Writer, n *node) error {
  function printReal (line 261) | func printReal(w io.Writer, n *node) error {
  type node (line 389) | type node struct
    method walk (line 404) | func (n *node) walk(w io.Writer, f func(w1 io.Writer, n1 *node) error)...
    method child (line 418) | func (n *node) child(label string) *node {
  type byLabel (line 434) | type byLabel
    method Len (line 436) | func (b byLabel) Len() int           { return len(b) }
    method Swap (line 437) | func (b byLabel) Swap(i, j int)      { b[i], b[j] = b[j], b[i] }
    method Less (line 438) | func (b byLabel) Less(i, j int) bool { return b[i].label < b[j].label }
  function assignIndexes (line 455) | func assignIndexes(w io.Writer, n *node) error {
  function printNode (line 500) | func printNode(w io.Writer, n *node) error {
  function printNodeLabel (line 519) | func printNodeLabel(w io.Writer, n *node) error {
  function icannStr (line 526) | func icannStr(icann bool) string {
  function wildcardStr (line 533) | func wildcardStr(wildcard bool) string {
  function combineText (line 543) | func combineText(labelsList []string) string {
  type byLength (line 556) | type byLength
    method Len (line 558) | func (s byLength) Len() int           { return len(s) }
    method Swap (line 559) | func (s byLength) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
    method Less (line 560) | func (s byLength) Less(i, j int) bool { return len(s[i]) < len(s[j]) }
  function removeSubstrings (line 564) | func removeSubstrings(input []string) []string {
  function crush (line 590) | func crush(ss []string) string {
  function mergeLabel (line 616) | func mergeLabel(ss []string, i, prefixLen int, prefixes prefixMap) {
  type prefixMap (line 647) | type prefixMap
  function makePrefixMap (line 650) | func makePrefixMap(ss []string, prefixLen int) prefixMap {

FILE: vendor/golang.org/x/net/publicsuffix/list.go
  type list (line 23) | type list struct
    method PublicSuffix (line 25) | func (list) PublicSuffix(domain string) string {
    method String (line 30) | func (list) String() string {
  function PublicSuffix (line 45) | func PublicSuffix(domain string) (publicSuffix string, icann bool) {
  constant notFound (line 92) | notFound uint32 = 1<<32 - 1
  function find (line 97) | func find(label string, lo, hi uint32) uint32 {
  function nodeLabel (line 113) | func nodeLabel(i uint32) string {
  function EffectiveTLDPlusOne (line 123) | func EffectiveTLDPlusOne(domain string) (string, error) {

FILE: vendor/golang.org/x/net/publicsuffix/table.go
  constant version (line 5) | version = "publicsuffix.org's public_suffix_list.dat, git revision bade6...
  constant nodesBitsChildren (line 8) | nodesBitsChildren   = 9
  constant nodesBitsICANN (line 9) | nodesBitsICANN      = 1
  constant nodesBitsTextOffset (line 10) | nodesBitsTextOffset = 15
  constant nodesBitsTextLength (line 11) | nodesBitsTextLength = 6
  constant childrenBitsWildcard (line 13) | childrenBitsWildcard = 1
  constant childrenBitsNodeType (line 14) | childrenBitsNodeType = 2
  constant childrenBitsHi (line 15) | childrenBitsHi       = 14
  constant childrenBitsLo (line 16) | childrenBitsLo       = 14
  constant nodeTypeNormal (line 20) | nodeTypeNormal     = 0
  constant nodeTypeException (line 21) | nodeTypeException  = 1
  constant nodeTypeParentOnly (line 22) | nodeTypeParentOnly = 2
  constant numTLD (line 26) | numTLD = 1545
  constant text (line 29) | text = "bievatmallorcadaquesanfranciscotlandupontarioceanographiquebifuk" +

FILE: vendor/gopkg.in/yaml.v1/apic.go
  function yaml_insert_token (line 8) | func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token...
  function yaml_parser_initialize (line 28) | func yaml_parser_initialize(parser *yaml_parser_t) bool {
  function yaml_parser_delete (line 37) | func yaml_parser_delete(parser *yaml_parser_t) {
  function yaml_string_read_handler (line 42) | func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n i...
  function yaml_file_read_handler (line 52) | func yaml_file_read_handler(parser *yaml_parser_t, buffer []byte) (n int...
  function yaml_parser_set_input_string (line 57) | func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) {
  function yaml_parser_set_input_file (line 67) | func yaml_parser_set_input_file(parser *yaml_parser_t, file *os.File) {
  function yaml_parser_set_encoding (line 76) | func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encod...
  function yaml_emitter_initialize (line 84) | func yaml_emitter_initialize(emitter *yaml_emitter_t) bool {
  function yaml_emitter_delete (line 95) | func yaml_emitter_delete(emitter *yaml_emitter_t) {
  function yaml_string_write_handler (line 100) | func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) e...
  function yaml_file_write_handler (line 106) | func yaml_file_write_handler(emitter *yaml_emitter_t, buffer []byte) err...
  function yaml_emitter_set_output_string (line 112) | func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buff...
  function yaml_emitter_set_output_file (line 121) | func yaml_emitter_set_output_file(emitter *yaml_emitter_t, file io.Write...
  function yaml_emitter_set_encoding (line 130) | func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_en...
  function yaml_emitter_set_canonical (line 138) | func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) {
  function yaml_emitter_set_indent (line 143) | func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) {
  function yaml_emitter_set_width (line 151) | func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) {
  function yaml_emitter_set_unicode (line 159) | func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) {
  function yaml_emitter_set_break (line 164) | func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_bre...
  function yaml_stream_start_event_initialize (line 255) | func yaml_stream_start_event_initialize(event *yaml_event_t, encoding ya...
  function yaml_stream_end_event_initialize (line 264) | func yaml_stream_end_event_initialize(event *yaml_event_t) bool {
  function yaml_document_start_event_initialize (line 272) | func yaml_document_start_event_initialize(event *yaml_event_t, version_d...
  function yaml_document_end_event_initialize (line 284) | func yaml_document_end_event_initialize(event *yaml_event_t, implicit bo...
  function yaml_scalar_event_initialize (line 317) | func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, valu...
  function yaml_sequence_start_event_initialize (line 331) | func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, t...
  function yaml_sequence_end_event_initialize (line 343) | func yaml_sequence_end_event_initialize(event *yaml_event_t) bool {
  function yaml_mapping_start_event_initialize (line 351) | func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, ta...
  function yaml_mapping_end_event_initialize (line 363) | func yaml_mapping_end_event_initialize(event *yaml_event_t) bool {
  function yaml_event_delete (line 371) | func yaml_event_delete(event *yaml_event_t) {

FILE: vendor/gopkg.in/yaml.v1/decode.go
  constant documentNode (line 12) | documentNode = 1 << iota
  constant mappingNode (line 13) | mappingNode
  constant sequenceNode (line 14) | sequenceNode
  constant scalarNode (line 15) | scalarNode
  constant aliasNode (line 16) | aliasNode
  type node (line 19) | type node struct
  type parser (line 32) | type parser struct
    method destroy (line 58) | func (p *parser) destroy() {
    method skip (line 65) | func (p *parser) skip() {
    method fail (line 77) | func (p *parser) fail() {
    method anchor (line 97) | func (p *parser) anchor(n *node, anchor []byte) {
    method parse (line 103) | func (p *parser) parse() *node {
    method node (line 124) | func (p *parser) node(kind int) *node {
    method document (line 132) | func (p *parser) document() *node {
    method alias (line 145) | func (p *parser) alias() *node {
    method scalar (line 152) | func (p *parser) scalar() *node {
    method sequence (line 162) | func (p *parser) sequence() *node {
    method mapping (line 173) | func (p *parser) mapping() *node {
  function newParser (line 38) | func newParser(b []byte) *parser {
  type decoder (line 187) | type decoder struct
    method setter (line 214) | func (d *decoder) setter(tag string, out *reflect.Value, good *bool) (...
    method unmarshal (line 252) | func (d *decoder) unmarshal(n *node, out reflect.Value) (good bool) {
    method document (line 270) | func (d *decoder) document(n *node, out reflect.Value) (good bool) {
    method alias (line 279) | func (d *decoder) alias(n *node, out reflect.Value) (good bool) {
    method scalar (line 303) | func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
    method sequence (line 427) | func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
    method mapping (line 456) | func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
    method mappingStruct (line 505) | func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
    method merge (line 534) | func (d *decoder) merge(n *node, out reflect.Value) {
  function newDecoder (line 192) | func newDecoder() *decoder {
  function resetMap (line 295) | func resetMap(out reflect.Value) {
  function settableValueOf (line 420) | func settableValueOf(i interface{}) reflect.Value {
  function isMerge (line 564) | func isMerge(n *node) bool {

FILE: vendor/gopkg.in/yaml.v1/emitterc.go
  function flush (line 8) | func flush(emitter *yaml_emitter_t) bool {
  function put (line 16) | func put(emitter *yaml_emitter_t, value byte) bool {
  function put_break (line 27) | func put_break(emitter *yaml_emitter_t) bool {
  function write (line 51) | func write(emitter *yaml_emitter_t, s []byte, i *int) bool {
  function write_all (line 79) | func write_all(emitter *yaml_emitter_t, s []byte) bool {
  function write_break (line 89) | func write_break(emitter *yaml_emitter_t, s []byte, i *int) bool {
  function yaml_emitter_set_emitter_error (line 106) | func yaml_emitter_set_emitter_error(emitter *yaml_emitter_t, problem str...
  function yaml_emitter_emit (line 113) | func yaml_emitter_emit(emitter *yaml_emitter_t, event *yaml_event_t) bool {
  function yaml_emitter_need_more_events (line 136) | func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool {
  function yaml_emitter_append_tag_directive (line 173) | func yaml_emitter_append_tag_directive(emitter *yaml_emitter_t, value *y...
  function yaml_emitter_increase_indent (line 196) | func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentl...
  function yaml_emitter_state_machine (line 211) | func yaml_emitter_state_machine(emitter *yaml_emitter_t, event *yaml_eve...
  function yaml_emitter_emit_stream_start (line 272) | func yaml_emitter_emit_stream_start(emitter *yaml_emitter_t, event *yaml...
  function yaml_emitter_emit_document_start (line 311) | func yaml_emitter_emit_document_start(emitter *yaml_emitter_t, event *ya...
  function yaml_emitter_emit_document_content (line 425) | func yaml_emitter_emit_document_content(emitter *yaml_emitter_t, event *...
  function yaml_emitter_emit_document_end (line 431) | func yaml_emitter_emit_document_end(emitter *yaml_emitter_t, event *yaml...
  function yaml_emitter_emit_flow_sequence_item (line 456) | func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event...
  function yaml_emitter_emit_flow_mapping_key (line 504) | func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *...
  function yaml_emitter_emit_flow_mapping_value (line 558) | func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event...
  function yaml_emitter_emit_block_sequence_item (line 578) | func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, even...
  function yaml_emitter_emit_block_mapping_key (line 602) | func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event ...
  function yaml_emitter_emit_block_mapping_value (line 630) | func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, even...
  function yaml_emitter_emit_node (line 648) | func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t,
  function yaml_emitter_emit_alias (line 673) | func yaml_emitter_emit_alias(emitter *yaml_emitter_t, event *yaml_event_...
  function yaml_emitter_emit_scalar (line 683) | func yaml_emitter_emit_scalar(emitter *yaml_emitter_t, event *yaml_event...
  function yaml_emitter_emit_sequence_start (line 707) | func yaml_emitter_emit_sequence_start(emitter *yaml_emitter_t, event *ya...
  function yaml_emitter_emit_mapping_start (line 724) | func yaml_emitter_emit_mapping_start(emitter *yaml_emitter_t, event *yam...
  function yaml_emitter_check_empty_document (line 741) | func yaml_emitter_check_empty_document(emitter *yaml_emitter_t) bool {
  function yaml_emitter_check_empty_sequence (line 746) | func yaml_emitter_check_empty_sequence(emitter *yaml_emitter_t) bool {
  function yaml_emitter_check_empty_mapping (line 755) | func yaml_emitter_check_empty_mapping(emitter *yaml_emitter_t) bool {
  function yaml_emitter_check_simple_key (line 764) | func yaml_emitter_check_simple_key(emitter *yaml_emitter_t) bool {
  function yaml_emitter_select_scalar_style (line 798) | func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *ya...
  function yaml_emitter_process_anchor (line 847) | func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool {
  function yaml_emitter_process_tag (line 862) | func yaml_emitter_process_tag(emitter *yaml_emitter_t) bool {
  function yaml_emitter_process_scalar (line 891) | func yaml_emitter_process_scalar(emitter *yaml_emitter_t) bool {
  function yaml_emitter_analyze_version_directive (line 912) | func yaml_emitter_analyze_version_directive(emitter *yaml_emitter_t, ver...
  function yaml_emitter_analyze_tag_directive (line 920) | func yaml_emitter_analyze_tag_directive(emitter *yaml_emitter_t, tag_dir...
  function yaml_emitter_analyze_anchor (line 944) | func yaml_emitter_analyze_anchor(emitter *yaml_emitter_t, anchor []byte,...
  function yaml_emitter_analyze_tag (line 967) | func yaml_emitter_analyze_tag(emitter *yaml_emitter_t, tag []byte) bool {
  function yaml_emitter_analyze_scalar (line 984) | func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) ...
  function yaml_emitter_analyze_event (line 1133) | func yaml_emitter_analyze_event(emitter *yaml_emitter_t, event *yaml_eve...
  function yaml_emitter_write_bom (line 1189) | func yaml_emitter_write_bom(emitter *yaml_emitter_t) bool {
  function yaml_emitter_write_indent (line 1201) | func yaml_emitter_write_indent(emitter *yaml_emitter_t) bool {
  function yaml_emitter_write_indicator (line 1221) | func yaml_emitter_write_indicator(emitter *yaml_emitter_t, indicator []b...
  function yaml_emitter_write_anchor (line 1236) | func yaml_emitter_write_anchor(emitter *yaml_emitter_t, value []byte) bo...
  function yaml_emitter_write_tag_handle (line 1245) | func yaml_emitter_write_tag_handle(emitter *yaml_emitter_t, value []byte...
  function yaml_emitter_write_tag_content (line 1259) | func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byt...
  function yaml_emitter_write_plain_scalar (line 1313) | func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []by...
  function yaml_emitter_write_single_quoted_scalar (line 1370) | func yaml_emitter_write_single_quoted_scalar(emitter *yaml_emitter_t, va...
  function yaml_emitter_write_double_quoted_scalar (line 1429) | func yaml_emitter_write_double_quoted_scalar(emitter *yaml_emitter_t, va...
  function yaml_emitter_write_block_scalar_hints (line 1550) | func yaml_emitter_write_block_scalar_hints(emitter *yaml_emitter_t, valu...
  function yaml_emitter_write_literal_scalar (line 1592) | func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []...
  function yaml_emitter_write_folded_scalar (line 1629) | func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []b...

FILE: vendor/gopkg.in/yaml.v1/encode.go
  type encoder (line 12) | type encoder struct
    method finish (line 30) | func (e *encoder) finish() {
    method destroy (line 38) | func (e *encoder) destroy() {
    method emit (line 42) | func (e *encoder) emit() {
    method must (line 49) | func (e *encoder) must(ok bool) {
    method marshal (line 59) | func (e *encoder) marshal(tag string, in reflect.Value) {
    method mapv (line 112) | func (e *encoder) mapv(tag string, in reflect.Value) {
    method structv (line 123) | func (e *encoder) structv(tag string, in reflect.Value) {
    method mappingv (line 146) | func (e *encoder) mappingv(tag string, f func()) {
    method slicev (line 160) | func (e *encoder) slicev(tag string, in reflect.Value) {
    method stringv (line 199) | func (e *encoder) stringv(tag string, in reflect.Value) {
    method boolv (line 223) | func (e *encoder) boolv(tag string, in reflect.Value) {
    method intv (line 233) | func (e *encoder) intv(tag string, in reflect.Value) {
    method uintv (line 238) | func (e *encoder) uintv(tag string, in reflect.Value) {
    method floatv (line 243) | func (e *encoder) floatv(tag string, in reflect.Value) {
    method nilv (line 257) | func (e *encoder) nilv() {
    method emitScalar (line 261) | func (e *encoder) emitScalar(value, anchor, tag string, style yaml_sca...
  function newEncoder (line 19) | func newEncoder() (e *encoder) {
  function isBase60Float (line 182) | func isBase60Float(s string) (result bool) {

FILE: vendor/gopkg.in/yaml.v1/parserc.go
  function peek_token (line 46) | func peek_token(parser *yaml_parser_t) *yaml_token_t {
  function skip_token (line 54) | func skip_token(parser *yaml_parser_t) {
  function yaml_parser_parse (line 62) | func yaml_parser_parse(parser *yaml_parser_t, event *yaml_event_t) bool {
  function yaml_parser_set_parser_error (line 76) | func yaml_parser_set_parser_error(parser *yaml_parser_t, problem string,...
  function yaml_parser_set_parser_error_context (line 83) | func yaml_parser_set_parser_error_context(parser *yaml_parser_t, context...
  function yaml_parser_state_machine (line 93) | func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_...
  function yaml_parser_parse_stream_start (line 175) | func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_e...
  function yaml_parser_parse_document_start (line 199) | func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml...
  function yaml_parser_parse_document_content (line 283) | func yaml_parser_parse_document_content(parser *yaml_parser_t, event *ya...
  function yaml_parser_parse_document_end (line 306) | func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_e...
  function yaml_parser_parse_node (line 360) | func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, ...
  function yaml_parser_parse_block_sequence_entry (line 580) | func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event...
  function yaml_parser_parse_indentless_sequence_entry (line 632) | func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, ...
  function yaml_parser_parse_block_mapping_key (line 676) | func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *y...
  function yaml_parser_parse_block_mapping_value (line 734) | func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event ...
  function yaml_parser_parse_flow_sequence_entry (line 771) | func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event ...
  function yaml_parser_parse_flow_sequence_entry_mapping_key (line 834) | func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_pars...
  function yaml_parser_parse_flow_sequence_entry_mapping_value (line 855) | func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_pa...
  function yaml_parser_parse_flow_sequence_entry_mapping_end (line 879) | func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_pars...
  function yaml_parser_parse_flow_mapping_key (line 905) | func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *ya...
  function yaml_parser_parse_flow_mapping_value (line 971) | func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *...
  function yaml_parser_process_empty_scalar (line 996) | func yaml_parser_process_empty_scalar(parser *yaml_parser_t, event *yaml...
  function yaml_parser_process_directives (line 1014) | func yaml_parser_process_directives(parser *yaml_parser_t,
  function yaml_parser_append_tag_directive (line 1076) | func yaml_parser_append_tag_directive(parser *yaml_parser_t, value yaml_...

FILE: vendor/gopkg.in/yaml.v1/readerc.go
  function yaml_parser_set_reader_error (line 8) | func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string,...
  constant bom_UTF8 (line 18) | bom_UTF8    = "\xef\xbb\xbf"
  constant bom_UTF16LE (line 19) | bom_UTF16LE = "\xff\xfe"
  constant bom_UTF16BE (line 20) | bom_UTF16BE = "\xfe\xff"
  function yaml_parser_determine_encoding (line 25) | func yaml_parser_determine_encoding(parser *yaml_parser_t) bool {
  function yaml_parser_update_raw_buffer (line 56) | func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool {
  function yaml_parser_update_buffer (line 91) | func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool {

FILE: vendor/gopkg.in/yaml.v1/resolve.go
  type resolveMapItem (line 14) | type resolveMapItem struct
  function init (line 22) | func init() {
  constant longTagPrefix (line 61) | longTagPrefix = "tag:yaml.org,2002:"
  function shortTag (line 63) | func shortTag(tag string) string {
  function longTag (line 71) | func longTag(tag string) string {
  function resolvableTag (line 78) | func resolvableTag(tag string) bool {
  function resolve (line 86) | func resolve(tag string, in string) (rtag string, out interface{}) {
  function encodeBase64 (line 169) | func encodeBase64(s string) string {

FILE: vendor/gopkg.in/yaml.v1/scannerc.go
  function cache (line 485) | func cache(parser *yaml_parser_t, length int) bool {
  function skip (line 491) | func skip(parser *yaml_parser_t) {
  function skip_line (line 498) | func skip_line(parser *yaml_parser_t) {
  function read (line 515) | func read(parser *yaml_parser_t, s []byte) []byte {
  function read_line (line 538) | func read_line(parser *yaml_parser_t, s []byte) []byte {
  function yaml_parser_scan (line 571) | func yaml_parser_scan(parser *yaml_parser_t, token *yaml_token_t) bool {
  function yaml_parser_set_scanner_error (line 600) | func yaml_parser_set_scanner_error(parser *yaml_parser_t, context string...
  function yaml_parser_set_scanner_tag_error (line 609) | func yaml_parser_set_scanner_tag_error(parser *yaml_parser_t, directive ...
  function trace (line 617) | func trace(args ...interface{}) func() {
  function yaml_parser_fetch_more_tokens (line 626) | func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool {
  function yaml_parser_fetch_next_token (line 665) | func yaml_parser_fetch_next_token(parser *yaml_parser_t) bool {
  function yaml_parser_stale_simple_keys (line 842) | func yaml_parser_stale_simple_keys(parser *yaml_parser_t) bool {
  function yaml_parser_save_simple_key (line 867) | func yaml_parser_save_simple_key(parser *yaml_parser_t) bool {
  function yaml_parser_remove_simple_key (line 900) | func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool {
  function yaml_parser_increase_flow_level (line 916) | func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool {
  function yaml_parser_decrease_flow_level (line 926) | func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool {
  function yaml_parser_roll_indent (line 937) | func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, ...
  function yaml_parser_unroll_indent (line 966) | func yaml_parser_unroll_indent(parser *yaml_parser_t, column int) bool {
  function yaml_parser_fetch_stream_start (line 990) | func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool {
  function yaml_parser_fetch_stream_end (line 1016) | func yaml_parser_fetch_stream_end(parser *yaml_parser_t) bool {
  function yaml_parser_fetch_directive (line 1047) | func yaml_parser_fetch_directive(parser *yaml_parser_t) bool {
  function yaml_parser_fetch_document_indicator (line 1071) | func yaml_parser_fetch_document_indicator(parser *yaml_parser_t, typ yam...
  function yaml_parser_fetch_flow_collection_start (line 1105) | func yaml_parser_fetch_flow_collection_start(parser *yaml_parser_t, typ ...
  function yaml_parser_fetch_flow_collection_end (line 1136) | func yaml_parser_fetch_flow_collection_end(parser *yaml_parser_t, typ ya...
  function yaml_parser_fetch_flow_entry (line 1168) | func yaml_parser_fetch_flow_entry(parser *yaml_parser_t) bool {
  function yaml_parser_fetch_block_entry (line 1193) | func yaml_parser_fetch_block_entry(parser *yaml_parser_t) bool {
  function yaml_parser_fetch_key (line 1235) | func yaml_parser_fetch_key(parser *yaml_parser_t) bool {
  function yaml_parser_fetch_value (line 1274) | func yaml_parser_fetch_value(parser *yaml_parser_t) bool {
  function yaml_parser_fetch_anchor (line 1339) | func yaml_parser_fetch_anchor(parser *yaml_parser_t, typ yaml_token_type...
  function yaml_parser_fetch_tag (line 1358) | func yaml_parser_fetch_tag(parser *yaml_parser_t) bool {
  function yaml_parser_fetch_block_scalar (line 1377) | func yaml_parser_fetch_block_scalar(parser *yaml_parser_t, literal bool)...
  function yaml_parser_fetch_flow_scalar (line 1396) | func yaml_parser_fetch_flow_scalar(parser *yaml_parser_t, single bool) b...
  function yaml_parser_fetch_plain_scalar (line 1415) | func yaml_parser_fetch_plain_scalar(parser *yaml_parser_t) bool {
  function yaml_parser_scan_to_next_token (line 1434) | func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool {
  function yaml_parser_scan_directive (line 1499) | func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token...
  function yaml_parser_scan_directive_name (line 1600) | func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark y...
  function yaml_parser_scan_version_directive_value (line 1636) | func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, sta...
  constant max_number_length (line 1668) | max_number_length = 2
  function yaml_parser_scan_version_directive_number (line 1677) | func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, st...
  function yaml_parser_scan_tag_directive_value (line 1713) | func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_m...
  function yaml_parser_scan_anchor (line 1771) | func yaml_parser_scan_anchor(parser *yaml_parser_t, token *yaml_token_t,...
  function yaml_parser_scan_tag (line 1829) | func yaml_parser_scan_tag(parser *yaml_parser_t, token *yaml_token_t) bo...
  function yaml_parser_scan_tag_handle (line 1914) | func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, ...
  function yaml_parser_scan_tag_uri (line 1959) | func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, hea...
  function yaml_parser_scan_uri_escapes (line 2016) | func yaml_parser_scan_uri_escapes(parser *yaml_parser_t, directive bool,...
  function yaml_parser_scan_block_scalar (line 2062) | func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_to...
  function yaml_parser_scan_block_scalar_breaks (line 2250) | func yaml_parser_scan_block_scalar_breaks(parser *yaml_parser_t, indent ...
  function yaml_parser_scan_flow_scalar (line 2304) | func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_tok...
  function yaml_parser_scan_plain_scalar (line 2560) | func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_to...

FILE: vendor/gopkg.in/yaml.v1/sorter.go
  type keyList (line 8) | type keyList
    method Len (line 10) | func (l keyList) Len() int      { return len(l) }
    method Swap (line 11) | func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
    method Less (line 12) | func (l keyList) Less(i, j int) bool {
  function keyFloat (line 73) | func keyFloat(v reflect.Value) (f float64, ok bool) {
  function numLess (line 92) | func numLess(a, b reflect.Value) bool {

FILE: vendor/gopkg.in/yaml.v1/writerc.go
  function yaml_emitter_set_writer_error (line 4) | func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem stri...
  function yaml_emitter_flush (line 11) | func yaml_emitter_flush(emitter *yaml_emitter_t) bool {

FILE: vendor/gopkg.in/yaml.v1/yaml.go
  type yamlError (line 17) | type yamlError
  function fail (line 19) | func fail(msg string) {
  function handleErr (line 23) | func handleErr(err *error) {
  type Setter (line 38) | type Setter interface
  type Getter (line 44) | type Getter interface
  function Unmarshal (line 84) | func Unmarshal(in []byte, out interface{}) (err error) {
  function Marshal (line 139) | func Marshal(in interface{}) (out []byte, err error) {
  type structInfo (line 156) | type structInfo struct
  type fieldInfo (line 165) | type fieldInfo struct
  function getStructInfo (line 178) | func getStructInfo(st reflect.Type) (*structInfo, error) {
  function isZero (line 283) | func isZero(v reflect.Value) bool {

FILE: vendor/gopkg.in/yaml.v1/yamlh.go
  type yaml_version_directive_t (line 8) | type yaml_version_directive_t struct
  type yaml_tag_directive_t (line 14) | type yaml_tag_directive_t struct
  type yaml_encoding_t (line 19) | type yaml_encoding_t
  constant yaml_ANY_ENCODING (line 24) | yaml_ANY_ENCODING yaml_encoding_t = iota
  constant yaml_UTF8_ENCODING (line 26) | yaml_UTF8_ENCODING
  constant yaml_UTF16LE_ENCODING (line 27) | yaml_UTF16LE_ENCODING
  constant yaml_UTF16BE_ENCODING (line 28) | yaml_UTF16BE_ENCODING
  type yaml_break_t (line 31) | type yaml_break_t
  constant yaml_ANY_BREAK (line 36) | yaml_ANY_BREAK yaml_break_t = iota
  constant yaml_CR_BREAK (line 38) | yaml_CR_BREAK
  constant yaml_LN_BREAK (line 39) | yaml_LN_BREAK
  constant yaml_CRLN_BREAK (line 40) | yaml_CRLN_BREAK
  type yaml_error_type_t (line 43) | type yaml_error_type_t
  constant yaml_NO_ERROR (line 48) | yaml_NO_ERROR yaml_error_type_t = iota
  constant yaml_MEMORY_ERROR (line 50) | yaml_MEMORY_ERROR
  constant yaml_READER_ERROR (line 51) | yaml_READER_ERROR
  constant yaml_SCANNER_ERROR (line 52) | yaml_SCANNER_ERROR
  constant yaml_PARSER_ERROR (line 53) | yaml_PARSER_ERROR
  constant yaml_COMPOSER_ERROR (line 54) | yaml_COMPOSER_ERROR
  constant yaml_WRITER_ERROR (line 55) | yaml_WRITER_ERROR
  constant yaml_EMITTER_ERROR (line 56) | yaml_EMITTER_ERROR
  type yaml_mark_t (line 60) | type yaml_mark_t struct
  type yaml_style_t (line 68) | type yaml_style_t
  type yaml_scalar_style_t (line 70) | type yaml_scalar_style_t
  constant yaml_ANY_SCALAR_STYLE (line 75) | yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = iota
  constant yaml_PLAIN_SCALAR_STYLE (line 77) | yaml_PLAIN_SCALAR_STYLE
  constant yaml_SINGLE_QUOTED_SCALAR_STYLE (line 78) | yaml_SINGLE_QUOTED_SCALAR_STYLE
  constant yaml_DOUBLE_QUOTED_SCALAR_STYLE (line 79) | yaml_DOUBLE_QUOTED_SCALAR_STYLE
  constant yaml_LITERAL_SCALAR_STYLE (line 80) | yaml_LITERAL_SCALAR_STYLE
  constant yaml_FOLDED_SCALAR_STYLE (line 81) | yaml_FOLDED_SCALAR_STYLE
  type yaml_sequence_style_t (line 84) | type yaml_sequence_style_t
  constant yaml_ANY_SEQUENCE_STYLE (line 89) | yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota
  constant yaml_BLOCK_SEQUENCE_STYLE (line 91) | yaml_BLOCK_SEQUENCE_STYLE
  constant yaml_FLOW_SEQUENCE_STYLE (line 92) | yaml_FLOW_SEQUENCE_STYLE
  type yaml_mapping_style_t (line 95) | type yaml_mapping_style_t
  constant yaml_ANY_MAPPING_STYLE (line 100) | yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota
  constant yaml_BLOCK_MAPPING_STYLE (line 102) | yaml_BLOCK_MAPPING_STYLE
  constant yaml_FLOW_MAPPING_STYLE (line 103) | yaml_FLOW_MAPPING_STYLE
  type yaml_token_type_t (line 108) | type yaml_token_type_t
    method String (line 143) | func (tt yaml_token_type_t) String() string {
  constant yaml_NO_TOKEN (line 113) | yaml_NO_TOKEN yaml_token_type_t = iota
  constant yaml_STREAM_START_TOKEN (line 115) | yaml_STREAM_START_TOKEN
  constant yaml_STREAM_END_TOKEN (line 116) | yaml_STREAM_END_TOKEN
  constant yaml_VERSION_DIRECTIVE_TOKEN (line 118) | yaml_VERSION_DIRECTIVE_TOKEN
  constant yaml_TAG_DIRECTIVE_TOKEN (line 119) | yaml_TAG_DIRECTIVE_TOKEN
  constant yaml_DOCUMENT_START_TOKEN (line 120) | yaml_DOCUMENT_START_TOKEN
  constant yaml_DOCUMENT_END_TOKEN (line 121) | yaml_DOCUMENT_END_TOKEN
  constant yaml_BLOCK_SEQUENCE_START_TOKEN (line 123) | yaml_BLOCK_SEQUENCE_START_TOKEN
  constant yaml_BLOCK_MAPPING_START_TOKEN (line 124) | yaml_BLOCK_MAPPING_START_TOKEN
  constant yaml_BLOCK_END_TOKEN (line 125) | yaml_BLOCK_END_TOKEN
  constant yaml_FLOW_SEQUENCE_START_TOKEN (line 127) | yaml_FLOW_SEQUENCE_START_TOKEN
  constant yaml_FLOW_SEQUENCE_END_TOKEN (line 128) | yaml_FLOW_SEQUENCE_END_TOKEN
  constant yaml_FLOW_MAPPING_START_TOKEN (line 129) | yaml_FLOW_MAPPING_START_TOKEN
  constant yaml_FLOW_MAPPING_END_TOKEN (line 130) | yaml_FLOW_MAPPING_END_TOKEN
  constant yaml_BLOCK_ENTRY_TOKEN (line 132) | yaml_BLOCK_ENTRY_TOKEN
  constant yaml_FLOW_ENTRY_TOKEN (line 133) | yaml_FLOW_ENTRY_TOKEN
  constant yaml_KEY_TOKEN (line 134) | yaml_KEY_TOKEN
  constant yaml_VALUE_TOKEN (line 135) | yaml_VALUE_TOKEN
  constant yaml_ALIAS_TOKEN (line 137) | yaml_ALIAS_TOKEN
  constant yaml_ANCHOR_TOKEN (line 138) | yaml_ANCHOR_TOKEN
  constant yaml_TAG_TOKEN (line 139) | yaml_TAG_TOKEN
  constant yaml_SCALAR_TOKEN (line 140) | yaml_SCALAR_TOKEN
  type yaml_token_t (line 194) | type yaml_token_t struct
  type yaml_event_type_t (line 223) | type yaml_event_type_t
  constant yaml_NO_EVENT (line 228) | yaml_NO_EVENT yaml_event_type_t = iota
  constant yaml_STREAM_START_EVENT (line 230) | yaml_STREAM_START_EVENT
  constant yaml_STREAM_END_EVENT (line 231) | yaml_STREAM_END_EVENT
  constant yaml_DOCUMENT_START_EVENT (line 232) | yaml_DOCUMENT_START_EVENT
  constant yaml_DOCUMENT_END_EVENT (line 233) | yaml_DOCUMENT_END_EVENT
  constant yaml_ALIAS_EVENT (line 234) | yaml_ALIAS_EVENT
  constant yaml_SCALAR_EVENT (line 235) | yaml_SCALAR_EVENT
  constant yaml_SEQUENCE_START_EVENT (line 236) | yaml_SEQUENCE_START_EVENT
  constant yaml_SEQUENCE_END_EVENT (line 237) | yaml_SEQUENCE_END_EVENT
  constant yaml_MAPPING_START_EVENT (line 238) | yaml_MAPPING_START_EVENT
  constant yaml_MAPPING_END_EVENT (line 239) | yaml_MAPPING_END_EVENT
  type yaml_event_t (line 243) | type yaml_event_t struct
    method scalar_style (line 280) | func (e *yaml_event_t) scalar_style() yaml_scalar_style_t     { return...
    method sequence_style (line 281) | func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return...
    method mapping_style (line 282) | func (e *yaml_event_t) mapping_style() yaml_mapping_style_t   { return...
  constant yaml_NULL_TAG (line 287) | yaml_NULL_TAG      = "tag:yaml.org,2002:null"
  constant yaml_BOOL_TAG (line 288) | yaml_BOOL_TAG      = "tag:yaml.org,2002:bool"
  constant yaml_STR_TAG (line 289) | yaml_STR_TAG       = "tag:yaml.org,2002:str"
  constant yaml_INT_TAG (line 290) | yaml_INT_TAG       = "tag:yaml.org,2002:int"
  constant yaml_FLOAT_TAG (line 291) | yaml_FLOAT_TAG     = "tag:yaml.org,2002:float"
  constant yaml_TIMESTAMP_TAG (line 292) | yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp"
  constant yaml_SEQ_TAG (line 294) | yaml_SEQ_TAG = "tag:yaml.org,2002:seq"
  constant yaml_MAP_TAG (line 295) | yaml_MAP_TAG = "tag:yaml.org,2002:map"
  constant yaml_BINARY_TAG (line 298) | yaml_BINARY_TAG = "tag:yaml.org,2002:binary"
  constant yaml_MERGE_TAG (line 299) | yaml_MERGE_TAG = "tag:yaml.org,2002:merge"
  constant yaml_DEFAULT_SCALAR_TAG (line 301) | yaml_DEFAULT_SCALAR_TAG   = yaml_STR_TAG
  constant yaml_DEFAULT_SEQUENCE_TAG (line 302) | yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG
  constant yaml_DEFAULT_MAPPING_TAG (line 303) | yaml_DEFAULT_MAPPING_TAG  = yaml_MAP_TAG
  type yaml_node_type_t (line 306) | type yaml_node_type_t
  constant yaml_NO_NODE (line 311) | yaml_NO_NODE yaml_node_type_t = iota
  constant yaml_SCALAR_NODE (line 313) | yaml_SCALAR_NODE
  constant yaml_SEQUENCE_NODE (line 314) | yaml_SEQUENCE_NODE
  constant yaml_MAPPING_NODE (line 315) | yaml_MAPPING_NODE
  type yaml_node_item_t (line 319) | type yaml_node_item_t
  type yaml_node_pair_t (line 322) | type yaml_node_pair_t struct
  type yaml_node_t (line 328) | type yaml_node_t struct
  type yaml_document_t (line 362) | type yaml_document_t struct
  type yaml_read_handler_t (line 397) | type yaml_read_handler_t
  type yaml_simple_key_t (line 400) | type yaml_simple_key_t struct
  type yaml_parser_state_t (line 408) | type yaml_parser_state_t
    method String (line 438) | func (ps yaml_parser_state_t) String() string {
  constant yaml_PARSE_STREAM_START_STATE (line 411) | yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota
  constant yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE (line 413) | yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE
  constant yaml_PARSE_DOCUMENT_START_STATE (line 414) | yaml_PARSE_DOCUMENT_START_STATE
  constant yaml_PARSE_DOCUMENT_CONTENT_STATE (line 415) | yaml_PARSE_DOCUMENT_CONTENT_STATE
  constant yaml_PARSE_DOCUMENT_END_STATE (line 416) | yaml_PARSE_DOCUMENT_END_STATE
  constant yaml_PARSE_BLOCK_NODE_STATE (line 417) | yaml_PARSE_BLOCK_NODE_STATE
  constant yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE (line 418) | yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE
  constant yaml_PARSE_FLOW_NODE_STATE (line 419) | yaml_PARSE_FLOW_NODE_STATE
  constant yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE (line 420) | yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE
  constant yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE (line 421) | yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE
  constant yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE (line 422) | yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE
  constant yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE (line 423) | yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE
  constant yaml_PARSE_BLOCK_MAPPING_KEY_STATE (line 424) | yaml_PARSE_BLOCK_MAPPING_KEY_STATE
  constant yaml_PARSE_BLOCK_MAPPING_VALUE_STATE (line 425) | yaml_PARSE_BLOCK_MAPPING_VALUE_STATE
  constant yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE (line 426) | yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE
  constant yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE (line 427) | yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE
  constant yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE (line 428) | yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE
  constant yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE (line 429) | yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE
  constant yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE (line 430) | yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE
  constant yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE (line 431) | yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE
  constant yaml_PARSE_FLOW_MAPPING_KEY_STATE (line 432) | yaml_PARSE_FLOW_MAPPING_KEY_STATE
  constant yaml_PARSE_FLOW_MAPPING_VALUE_STATE (line 433) | yaml_PARSE_FLOW_MAPPING_VALUE_STATE
  constant yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE (line 434) | yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE
  constant yaml_PARSE_END_STATE (line 435) | yaml_PARSE_END_STATE
  type yaml_alias_data_t (line 493) | type yaml_alias_data_t struct
  type yaml_parser_t (line 503) | type yaml_parser_t struct
  type yaml_write_handler_t (line 591) | type yaml_write_handler_t
  type yaml_emitter_state_t (line 593) | type yaml_emitter_state_t
  constant yaml_EMIT_STREAM_START_STATE (line 598) | yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota
  constant yaml_EMIT_FIRST_DOCUMENT_START_STATE (line 600) | yaml_EMIT_FIRST_DOCUMENT_START_STATE
  constant yaml_EMIT_DOCUMENT_START_STATE (line 601) | yaml_EMIT_DOCUMENT_START_STATE
  constant yaml_EMIT_DOCUMENT_CONTENT_STATE (line 602) | yaml_EMIT_DOCUMENT_CONTENT_STATE
  constant yaml_EMIT_DOCUMENT_END_STATE (line 603) | yaml_EMIT_DOCUMENT_END_STATE
  constant yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE (line 604) | yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE
  constant yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE (line 605) | yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE
  constant yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE (line 606) | yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE
  constant yaml_EMIT_FLOW_MAPPING_KEY_STATE (line 607) | yaml_EMIT_FLOW_MAPPING_KEY_STATE
  constant yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE (line 608) | yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE
  constant yaml_EMIT_FLOW_MAPPING_VALUE_STATE (line 609) | yaml_EMIT_FLOW_MAPPING_VALUE_STATE
  constant yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE (line 610) | yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE
  constant yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE (line 611) | yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE
  constant yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE (line 612) | yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE
  constant yaml_EMIT_BLOCK_MAPPING_KEY_STATE (line 613) | yaml_EMIT_BLOCK_MAPPING_KEY_STATE
  constant yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE (line 614) | yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE
  constant yaml_EMIT_BLOCK_MAPPING_VALUE_STATE (line 615) | yaml_EMIT_BLOCK_MAPPING_VALUE_STATE
  constant yaml_EMIT_END_STATE (line 616) | yaml_EMIT_END_STATE
  type yaml_emitter_t (line 623) | type yaml_emitter_t struct

FILE: vendor/gopkg.in/yaml.v1/yamlprivateh.go
  constant input_raw_buffer_size (line 5) | input_raw_buffer_size = 512
  constant input_buffer_size (line 9) | input_buffer_size = input_raw_buffer_size * 3
  constant output_buffer_size (line 12) | output_buffer_size = 128
  constant output_raw_buffer_size (line 16) | output_raw_buffer_size = (output_buffer_size*2 + 2)
  constant initial_stack_size (line 19) | initial_stack_size  = 16
  constant initial_queue_size (line 20) | initial_queue_size  = 16
  constant initial_string_size (line 21) | initial_string_size = 16
  function is_alpha (line 26) | func is_alpha(b []byte, i int) bool {
  function is_digit (line 31) | func is_digit(b []byte, i int) bool {
  function as_digit (line 36) | func as_digit(b []byte, i int) int {
  function is_hex (line 41) | func is_hex(b []byte, i int) bool {
  function as_hex (line 46) | func as_hex(b []byte, i int) int {
  function is_ascii (line 58) | func is_ascii(b []byte, i int) bool {
  function is_printable (line 63) | func is_printable(b []byte, i int) bool {
  function is_z (line 76) | func is_z(b []byte, i int) bool {
  function is_bom (line 81) | func is_bom(b []byte, i int) bool {
  function is_space (line 86) | func is_space(b []byte, i int) bool {
  function is_tab (line 91) | func is_tab(b []byte, i int) bool {
  function is_blank (line 96) | func is_blank(b []byte, i int) bool {
  function is_break (line 102) | func is_break(b []byte, i int) bool {
  function is_crlf (line 110) | func is_crlf(b []byte, i int) bool {
  function is_breakz (line 115) | func is_breakz(b []byte, i int) bool {
  function is_spacez (line 128) | func is_spacez(b []byte, i int) bool {
  function is_blankz (line 142) | func is_blankz(b []byte, i int) bool {
  function width (line 156) | func width(b byte) int {
Condensed preview — 97 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,494K chars).
[
  {
    "path": ".github/workflows/semgrep.yml",
    "chars": 586,
    "preview": "on:\n  pull_request: {}\n  workflow_dispatch: {}\n  push: \n    branches:\n      - main\n      - master\n  schedule:\n    - cron"
  },
  {
    "path": ".gitignore",
    "chars": 26,
    "preview": ".DS_Store\nbuilds/\ndebian/\n"
  },
  {
    "path": "Godeps/Godeps.json",
    "chars": 1873,
    "preview": "{\n\t\"ImportPath\": \"github.com/eagerio/stout\",\n\t\"GoVersion\": \"go1.6\",\n\t\"GodepVersion\": \"v63\",\n\t\"Packages\": [\n\t\t\"./...\"\n\t],"
  },
  {
    "path": "Godeps/Readme",
    "chars": 136,
    "preview": "This directory tree is generated automatically by godep.\n\nPlease do not edit.\n\nSee https://github.com/tools/godep for mo"
  },
  {
    "path": "LICENSE",
    "chars": 1062,
    "preview": "Copyright (c) 2014 Eager Platform Co.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of t"
  },
  {
    "path": "README.md",
    "chars": 13892,
    "preview": "# Stout\n\n#### [View the site →](http://stout.is/)\n\nStout is a deploy tool for static websites.  It takes a website and u"
  },
  {
    "path": "docs/getting-started.md",
    "chars": 3277,
    "preview": "### Setting Up Your Site\n\nIf you don't already have an S3-hosted site, start here.\n\nWe're going to create a basic site c"
  },
  {
    "path": "src/admin.go",
    "chars": 9179,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strings\"\n\n\t\"github.com/zackbloom/goamz/cloudfront\"\n\t\"github.com/zackblo"
  },
  {
    "path": "src/cli.go",
    "chars": 925,
    "preview": "package main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n)\n\nfunc printUsage() {\n\tfmt.Println(`Stout Static Deploy Tool\nSupports three comma"
  },
  {
    "path": "src/deploy.go",
    "chars": 13901,
    "preview": "package main\n\nimport (\n\t\"bytes\"\n\t\"compress/gzip\"\n\t\"crypto/md5\"\n\t\"encoding/base64\"\n\t\"fmt\"\n\t\"io\"\n\t\"math/big\"\n\t\"mime\"\n\t\"net"
  },
  {
    "path": "src/rollback.go",
    "chars": 1791,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"path/filepath\"\n\t\"sync\"\n\n\t\"github.com/zackbloom/goamz/s3\"\n)\n\nfunc Rollback(options"
  },
  {
    "path": "src/utils.go",
    "chars": 5472,
    "preview": "package main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"github.com/imda"
  },
  {
    "path": "utils/build.sh",
    "chars": 172,
    "preview": "GOOS=linux GOARCH=amd64 go build -o stout-linux src/* \nGOOS=darwin GOARCH=amd64 go build -o stout-osx src/* \nGOOS=window"
  },
  {
    "path": "utils/create_site.sh",
    "chars": 2961,
    "preview": "#set -e\n\nexport HOST=$1\nexport DEPLOY_USER=${HOST}_deploy\n\naws s3 mb s3://$HOST --region us-east-1\n\naws s3 website s3://"
  },
  {
    "path": "utils/release.sh",
    "chars": 1016,
    "preview": "set -e\n\n# Install jq with brew install jq\n\nRELEASE=$1\n\ngit tag $RELEASE\ngit push origin master --tags\n\nUPLOAD_URL=$(curl"
  },
  {
    "path": "utils/xc.sh",
    "chars": 40,
    "preview": "goxc -tasks-=downloads-page -d=./builds\n"
  },
  {
    "path": "vendor/github.com/cenk/backoff/.gitignore",
    "chars": 252,
    "preview": "# Compiled Object files, Static and Dynamic libs (Shared Objects)\n*.o\n*.a\n*.so\n\n# Folders\n_obj\n_test\n\n# Architecture spe"
  },
  {
    "path": "vendor/github.com/cenk/backoff/.travis.yml",
    "chars": 187,
    "preview": "language: go\ngo:\n  - 1.3.3\n  - tip\nbefore_install:\n  - go get github.com/mattn/goveralls\n  - go get golang.org/x/tools/c"
  },
  {
    "path": "vendor/github.com/cenk/backoff/LICENSE",
    "chars": 1076,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2014 Cenk Altı\n\nPermission is hereby granted, free of charge, to any person obtaini"
  },
  {
    "path": "vendor/github.com/cenk/backoff/README.md",
    "chars": 3403,
    "preview": "# Exponential Backoff [![GoDoc][godoc image]][godoc] [![Build Status][travis image]][travis] [![Coverage Status][coveral"
  },
  {
    "path": "vendor/github.com/cenk/backoff/backoff.go",
    "chars": 1874,
    "preview": "// Package backoff implements backoff algorithms for retrying operations.\n//\n// Also has a Retry() helper for retrying o"
  },
  {
    "path": "vendor/github.com/cenk/backoff/exponential.go",
    "chars": 5506,
    "preview": "package backoff\n\nimport (\n\t\"math/rand\"\n\t\"time\"\n)\n\n/*\nExponentialBackOff is a backoff implementation that increases the b"
  },
  {
    "path": "vendor/github.com/cenk/backoff/retry.go",
    "chars": 1274,
    "preview": "package backoff\n\nimport \"time\"\n\n// An Operation is executing by Retry() or RetryNotify().\n// The operation will be retri"
  },
  {
    "path": "vendor/github.com/cenk/backoff/ticker.go",
    "chars": 1602,
    "preview": "package backoff\n\nimport (\n\t\"runtime\"\n\t\"sync\"\n\t\"time\"\n)\n\n// Ticker holds a channel that delivers `ticks' of a clock at ti"
  },
  {
    "path": "vendor/github.com/imdario/mergo/.travis.yml",
    "chars": 32,
    "preview": "language: go\ninstall: go get -t\n"
  },
  {
    "path": "vendor/github.com/imdario/mergo/LICENSE",
    "chars": 1534,
    "preview": "Copyright (c) 2013 Dario Castañé. All rights reserved.\nCopyright (c) 2012 The Go Authors. All rights reserved.\n\nRedistri"
  },
  {
    "path": "vendor/github.com/imdario/mergo/README.md",
    "chars": 4887,
    "preview": "# Mergo\n\nA helper to merge structs and maps in Golang. Useful for configuration default values, avoiding messy if-statem"
  },
  {
    "path": "vendor/github.com/imdario/mergo/doc.go",
    "chars": 976,
    "preview": "// Copyright 2013 Dario Castañé. All rights reserved.\n// Copyright 2009 The Go Authors. All rights reserved.\n// Use of t"
  },
  {
    "path": "vendor/github.com/imdario/mergo/map.go",
    "chars": 4762,
    "preview": "// Copyright 2014 Dario Castañé. All rights reserved.\n// Copyright 2009 The Go Authors. All rights reserved.\n// Use of t"
  },
  {
    "path": "vendor/github.com/imdario/mergo/merge.go",
    "chars": 3463,
    "preview": "// Copyright 2013 Dario Castañé. All rights reserved.\n// Copyright 2009 The Go Authors. All rights reserved.\n// Use of t"
  },
  {
    "path": "vendor/github.com/imdario/mergo/mergo.go",
    "chars": 2711,
    "preview": "// Copyright 2013 Dario Castañé. All rights reserved.\n// Copyright 2009 The Go Authors. All rights reserved.\n// Use of t"
  },
  {
    "path": "vendor/github.com/mitchellh/go-homedir/LICENSE",
    "chars": 1085,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2013 Mitchell Hashimoto\n\nPermission is hereby granted, free of charge, to any perso"
  },
  {
    "path": "vendor/github.com/mitchellh/go-homedir/README.md",
    "chars": 681,
    "preview": "# go-homedir\n\nThis is a Go library for detecting the user's home directory without\nthe use of cgo, so the library can be"
  },
  {
    "path": "vendor/github.com/mitchellh/go-homedir/homedir.go",
    "chars": 2900,
    "preview": "package homedir\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n"
  },
  {
    "path": "vendor/github.com/wsxiaoys/terminal/LICENSE",
    "chars": 1475,
    "preview": "Copyright (c) 2013 Meng Zhang. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\n"
  },
  {
    "path": "vendor/github.com/wsxiaoys/terminal/color/color.go",
    "chars": 4880,
    "preview": "// The colors package provide a simple way to bring colorful characters to terminal interface.\n//\n// This example will o"
  },
  {
    "path": "vendor/github.com/zackbloom/go-ini/.gitignore",
    "chars": 273,
    "preview": "# Compiled Object files, Static and Dynamic libs (Shared Objects)\n*.o\n*.a\n*.so\n\n# Folders\n_obj\n_test\n\n# Architecture spe"
  },
  {
    "path": "vendor/github.com/zackbloom/go-ini/README.md",
    "chars": 2936,
    "preview": "go-ini\n======\n\nINI file decoder for Go lang.  Idea is to have an unmarshaller similar to JSON - specify parts of the fil"
  },
  {
    "path": "vendor/github.com/zackbloom/go-ini/decode.go",
    "chars": 12276,
    "preview": "// Decode INI files with a syntax similar to JSON decoding\npackage ini\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"io/iou"
  },
  {
    "path": "vendor/github.com/zackbloom/go-ini/stack.go",
    "chars": 876,
    "preview": "package ini\n\n// NewStack returns a new stack.\nfunc NewStack() *Stack {\n\treturn &Stack{}\n}\n\n// Stack is a basic LIFO stac"
  },
  {
    "path": "vendor/github.com/zackbloom/goamz/LICENSE",
    "chars": 8747,
    "preview": "This software is licensed under the LGPLv3, included below.\n\nAs a special exception to the GNU Lesser General Public Lic"
  },
  {
    "path": "vendor/github.com/zackbloom/goamz/aws/attempt.go",
    "chars": 1716,
    "preview": "package aws\n\nimport (\n\t\"time\"\n)\n\n// AttemptStrategy represents a strategy for waiting for an action\n// to complete succe"
  },
  {
    "path": "vendor/github.com/zackbloom/goamz/aws/aws.go",
    "chars": 15616,
    "preview": "//\n// goamz - Go packages to interact with the Amazon Web Services.\n//\n//   https://wiki.ubuntu.com/goamz\n//\n// Copyrigh"
  },
  {
    "path": "vendor/github.com/zackbloom/goamz/aws/client.go",
    "chars": 3029,
    "preview": "package aws\n\nimport (\n\t\"math\"\n\t\"net\"\n\t\"net/http\"\n\t\"time\"\n)\n\ntype RetryableFunc func(*http.Request, *http.Response, error"
  },
  {
    "path": "vendor/github.com/zackbloom/goamz/aws/regions.go",
    "chars": 7764,
    "preview": "package aws\n\nvar USGovWest = Region{\n\t\"us-gov-west-1\",\n\t\"https://ec2.us-gov-west-1.amazonaws.com\",\n\t\"https://s3-fips-us-"
  },
  {
    "path": "vendor/github.com/zackbloom/goamz/aws/retry.go",
    "chars": 4449,
    "preview": "package aws\n\nimport (\n\t\"math/rand\"\n\t\"net\"\n\t\"net/http\"\n\t\"time\"\n)\n\nconst (\n\tmaxDelay             = 20 * time.Second\n\tdefau"
  },
  {
    "path": "vendor/github.com/zackbloom/goamz/aws/sign.go",
    "chars": 12089,
    "preview": "package aws\n\nimport (\n\t\"bytes\"\n\t\"crypto/hmac\"\n\t\"crypto/sha256\"\n\t\"encoding/base64\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"net/http\"\n\t\"net/"
  },
  {
    "path": "vendor/github.com/zackbloom/goamz/cloudfront/cloudfront.go",
    "chars": 16134,
    "preview": "package cloudfront\n\nimport (\n\t\"bytes\"\n\t\"crypto\"\n\t\"crypto/rsa\"\n\t\"crypto/sha1\"\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"encod"
  },
  {
    "path": "vendor/github.com/zackbloom/goamz/iam/iam.go",
    "chars": 10784,
    "preview": "// The iam package provides types and functions for interaction with the AWS\n// Identity and Access Management (IAM) ser"
  },
  {
    "path": "vendor/github.com/zackbloom/goamz/iam/sign.go",
    "chars": 1024,
    "preview": "package iam\n\nimport (\n\t\"crypto/hmac\"\n\t\"crypto/sha256\"\n\t\"encoding/base64\"\n\t\"github.com/zackbloom/goamz/aws\"\n\t\"sort\"\n\t\"str"
  },
  {
    "path": "vendor/github.com/zackbloom/goamz/route53/route53.go",
    "chars": 11808,
    "preview": "package route53\n\nimport (\n\t\"bytes\"\n\t\"encoding/xml\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strconv\"\n\n\t\"github.com/zackbloo"
  },
  {
    "path": "vendor/github.com/zackbloom/goamz/s3/lifecycle.go",
    "chars": 5496,
    "preview": "package s3\n\nimport (\n\t\"crypto/md5\"\n\t\"encoding/base64\"\n\t\"encoding/xml\"\n\t\"net/url\"\n\t\"strconv\"\n\t\"time\"\n)\n\n// Implements an "
  },
  {
    "path": "vendor/github.com/zackbloom/goamz/s3/multi.go",
    "chars": 12787,
    "preview": "package s3\n\nimport (\n\t\"bytes\"\n\t\"crypto/md5\"\n\t\"encoding/base64\"\n\t\"encoding/hex\"\n\t\"encoding/xml\"\n\t\"errors\"\n\t\"io\"\n\t\"net/url"
  },
  {
    "path": "vendor/github.com/zackbloom/goamz/s3/s3.go",
    "chars": 34410,
    "preview": "//\n// goamz - Go packages to interact with the Amazon Web Services.\n//\n//   https://wiki.ubuntu.com/goamz\n//\n// Copyrigh"
  },
  {
    "path": "vendor/github.com/zackbloom/goamz/s3/sign.go",
    "chars": 3098,
    "preview": "package s3\n\nimport (\n\t\"crypto/hmac\"\n\t\"crypto/sha1\"\n\t\"encoding/base64\"\n\t\"github.com/zackbloom/goamz/aws\"\n\t\"log\"\n\t\"sort\"\n\t"
  },
  {
    "path": "vendor/golang.org/x/crypto/LICENSE",
    "chars": 1479,
    "preview": "Copyright (c) 2009 The Go Authors. All rights reserved.\n\nRedistribution and use in source and binary forms, with or with"
  },
  {
    "path": "vendor/golang.org/x/crypto/PATENTS",
    "chars": 1303,
    "preview": "Additional IP Rights Grant (Patents)\n\n\"This implementation\" means the copyrightable works distributed by\nGoogle as part "
  },
  {
    "path": "vendor/golang.org/x/crypto/ssh/terminal/terminal.go",
    "chars": 20992,
    "preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/golang.org/x/crypto/ssh/terminal/util.go",
    "chars": 3980,
    "preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go",
    "chars": 332,
    "preview": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/golang.org/x/crypto/ssh/terminal/util_linux.go",
    "chars": 457,
    "preview": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go",
    "chars": 2028,
    "preview": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/golang.org/x/crypto/ssh/terminal/util_windows.go",
    "chars": 4430,
    "preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/golang.org/x/net/LICENSE",
    "chars": 1479,
    "preview": "Copyright (c) 2009 The Go Authors. All rights reserved.\n\nRedistribution and use in source and binary forms, with or with"
  },
  {
    "path": "vendor/golang.org/x/net/PATENTS",
    "chars": 1303,
    "preview": "Additional IP Rights Grant (Patents)\n\n\"This implementation\" means the copyrightable works distributed by\nGoogle as part "
  },
  {
    "path": "vendor/golang.org/x/net/html/atom/atom.go",
    "chars": 2282,
    "preview": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/golang.org/x/net/html/atom/gen.go",
    "chars": 10410,
    "preview": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/golang.org/x/net/html/atom/table.go",
    "chars": 23166,
    "preview": "// generated by go run gen.go; DO NOT EDIT\n\npackage atom\n\nconst (\n\tA                   Atom = 0x1\n\tAbbr                A"
  },
  {
    "path": "vendor/golang.org/x/net/html/const.go",
    "chars": 2334,
    "preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/golang.org/x/net/html/doc.go",
    "chars": 3356,
    "preview": "// Copyright 2010 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/golang.org/x/net/html/doctype.go",
    "chars": 4925,
    "preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/golang.org/x/net/html/entity.go",
    "chars": 100055,
    "preview": "// Copyright 2010 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/golang.org/x/net/html/escape.go",
    "chars": 6052,
    "preview": "// Copyright 2010 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/golang.org/x/net/html/foreign.go",
    "chars": 6913,
    "preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/golang.org/x/net/html/node.go",
    "chars": 4835,
    "preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/golang.org/x/net/html/parse.go",
    "chars": 49266,
    "preview": "// Copyright 2010 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/golang.org/x/net/html/render.go",
    "chars": 7062,
    "preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/golang.org/x/net/html/token.go",
    "chars": 30249,
    "preview": "// Copyright 2010 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/golang.org/x/net/publicsuffix/gen.go",
    "chars": 19203,
    "preview": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/golang.org/x/net/publicsuffix/list.go",
    "chars": 3827,
    "preview": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/golang.org/x/net/publicsuffix/table.go",
    "chars": 540322,
    "preview": "// generated by go run gen.go; DO NOT EDIT\n\npackage publicsuffix\n\nconst version = \"publicsuffix.org's public_suffix_list"
  },
  {
    "path": "vendor/gopkg.in/yaml.v1/LICENSE",
    "chars": 8790,
    "preview": "\nCopyright (c) 2011-2014 - Canonical Inc.\n\nThis software is licensed under the LGPLv3, included below.\n\nAs a special exc"
  },
  {
    "path": "vendor/gopkg.in/yaml.v1/LICENSE.libyaml",
    "chars": 1313,
    "preview": "The following files were ported to Go from C files of libyaml, and thus\nare still covered by their original copyright an"
  },
  {
    "path": "vendor/gopkg.in/yaml.v1/README.md",
    "chars": 2566,
    "preview": "# YAML support for the Go language\n\nIntroduction\n------------\n\nThe yaml package enables Go programs to comfortably encod"
  },
  {
    "path": "vendor/gopkg.in/yaml.v1/apic.go",
    "chars": 21246,
    "preview": "package yaml\n\nimport (\n\t\"io\"\n\t\"os\"\n)\n\nfunc yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) {\n\t//f"
  },
  {
    "path": "vendor/gopkg.in/yaml.v1/decode.go",
    "chars": 12779,
    "preview": "package yaml\n\nimport (\n\t\"encoding/base64\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"time\"\n)\n\nconst (\n\tdocumentNode = 1 << iota\n\tmap"
  },
  {
    "path": "vendor/gopkg.in/yaml.v1/emitterc.go",
    "chars": 45308,
    "preview": "package yaml\n\nimport (\n\t\"bytes\"\n)\n\n// Flush the buffer if needed.\nfunc flush(emitter *yaml_emitter_t) bool {\n\tif emitter"
  },
  {
    "path": "vendor/gopkg.in/yaml.v1/encode.go",
    "chars": 6434,
    "preview": "package yaml\n\nimport (\n\t\"reflect\"\n\t\"regexp\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n)\n\ntype encoder struct {\n\temitter yaml"
  },
  {
    "path": "vendor/gopkg.in/yaml.v1/parserc.go",
    "chars": 34775,
    "preview": "package yaml\n\nimport (\n\t\"bytes\"\n)\n\n// The parser implements the following grammar:\n//\n// stream               ::= STREAM"
  },
  {
    "path": "vendor/gopkg.in/yaml.v1/readerc.go",
    "chars": 11893,
    "preview": "package yaml\n\nimport (\n\t\"io\"\n)\n\n// Set the reader error and return 0.\nfunc yaml_parser_set_reader_error(parser *yaml_par"
  },
  {
    "path": "vendor/gopkg.in/yaml.v1/resolve.go",
    "chars": 4770,
    "preview": "package yaml\n\nimport (\n\t\"encoding/base64\"\n\t\"fmt\"\n\t\"math\"\n\t\"strconv\"\n\t\"strings\"\n\t\"unicode/utf8\"\n)\n\n// TODO: merge, timest"
  },
  {
    "path": "vendor/gopkg.in/yaml.v1/scannerc.go",
    "chars": 77263,
    "preview": "package yaml\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n)\n\n// Introduction\n// ************\n//\n// The following notes assume that you are "
  },
  {
    "path": "vendor/gopkg.in/yaml.v1/sorter.go",
    "chars": 2476,
    "preview": "package yaml\n\nimport (\n\t\"reflect\"\n\t\"unicode\"\n)\n\ntype keyList []reflect.Value\n\nfunc (l keyList) Len() int      { return l"
  },
  {
    "path": "vendor/gopkg.in/yaml.v1/writerc.go",
    "chars": 2435,
    "preview": "package yaml\n\n// Set the writer error and return false.\nfunc yaml_emitter_set_writer_error(emitter *yaml_emitter_t, prob"
  },
  {
    "path": "vendor/gopkg.in/yaml.v1/yaml.go",
    "chars": 8662,
    "preview": "// Package yaml implements YAML support for the Go language.\n//\n// Source code and other details for the project are ava"
  },
  {
    "path": "vendor/gopkg.in/yaml.v1/yamlh.go",
    "chars": 25408,
    "preview": "package yaml\n\nimport (\n\t\"io\"\n)\n\n// The version directive data.\ntype yaml_version_directive_t struct {\n\tmajor int8 // The"
  },
  {
    "path": "vendor/gopkg.in/yaml.v1/yamlprivateh.go",
    "chars": 4961,
    "preview": "package yaml\n\nconst (\n\t// The size of the input raw buffer.\n\tinput_raw_buffer_size = 512\n\n\t// The size of the input buff"
  }
]

About this extraction

This page contains the full source code of the EagerIO/Stout GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 97 files (1.3 MB), approximately 498.2k tokens, and a symbol index with 1617 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!