浏览代码

Merge pull request #1793 from infosiftr/rfc2822

Convert "bashbrew" to Go and add a new RFC 2822 manifest file format
yosifkit 9 年之前
父节点
当前提交
feee857f79
共有 100 个文件被更改,包括 18717 次插入569 次删除
  1. 4 0
      .gitignore
  2. 18 2
      .travis.yml
  3. 25 2
      Dockerfile
  4. 43 16
      README.md
  5. 60 98
      bashbrew/README.md
  6. 4 425
      bashbrew/bashbrew.sh
  7. 0 1
      bashbrew/build.sh
  8. 0 9
      bashbrew/deprecated.sh
  9. 0 16
      bashbrew/git-set-mtimes
  10. 94 0
      bashbrew/go/src/bashbrew/cmd-build.go
  11. 70 0
      bashbrew/go/src/bashbrew/cmd-cat.go
  12. 105 0
      bashbrew/go/src/bashbrew/cmd-deps.go
  13. 37 0
      bashbrew/go/src/bashbrew/cmd-from.go
  14. 68 0
      bashbrew/go/src/bashbrew/cmd-list.go
  15. 40 0
      bashbrew/go/src/bashbrew/cmd-push.go
  16. 42 0
      bashbrew/go/src/bashbrew/cmd-tag.go
  17. 205 0
      bashbrew/go/src/bashbrew/config.go
  18. 187 0
      bashbrew/go/src/bashbrew/docker.go
  19. 146 0
      bashbrew/go/src/bashbrew/git.go
  20. 370 0
      bashbrew/go/src/bashbrew/main.go
  21. 151 0
      bashbrew/go/src/bashbrew/repo.go
  22. 141 0
      bashbrew/go/vendor/manifest
  23. 310 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/CHANGELOG.md
  24. 21 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/LICENSE
  25. 579 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/README.md
  26. 439 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/altsrc/flag.go
  27. 336 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/altsrc/flag_test.go
  28. 18 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/altsrc/helpers_test.go
  29. 21 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/altsrc/input_source_context.go
  30. 248 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/altsrc/map_input_source.go
  31. 313 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/altsrc/yaml_command_test.go
  32. 84 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/altsrc/yaml_file_loader.go
  33. 498 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/app.go
  34. 1454 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/app_test.go
  35. 16 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/appveyor.yml
  36. 14 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/autocomplete/bash_autocomplete
  37. 5 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/autocomplete/zsh_autocomplete
  38. 44 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/category.go
  39. 19 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/cli.go
  40. 279 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/command.go
  41. 101 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/command_test.go
  42. 446 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/context.go
  43. 256 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/context_test.go
  44. 92 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/errors.go
  45. 60 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/errors_test.go
  46. 659 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/flag.go
  47. 884 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/flag_test.go
  48. 28 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/funcs.go
  49. 266 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/help.go
  50. 202 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/help_test.go
  51. 28 0
      bashbrew/go/vendor/src/github.com/codegangsta/cli/helpers_test.go
  52. 191 0
      bashbrew/go/vendor/src/github.com/docker-library/go-dockerlibrary/LICENSE
  53. 67 0
      bashbrew/go/vendor/src/github.com/docker-library/go-dockerlibrary/manifest/example.go
  54. 67 0
      bashbrew/go/vendor/src/github.com/docker-library/go-dockerlibrary/manifest/fetch.go
  55. 77 0
      bashbrew/go/vendor/src/github.com/docker-library/go-dockerlibrary/manifest/line-based.go
  56. 24 0
      bashbrew/go/vendor/src/github.com/docker-library/go-dockerlibrary/manifest/parse.go
  57. 269 0
      bashbrew/go/vendor/src/github.com/docker-library/go-dockerlibrary/manifest/rfc2822.go
  58. 54 0
      bashbrew/go/vendor/src/github.com/docker-library/go-dockerlibrary/pkg/stripper/comments.go
  59. 99 0
      bashbrew/go/vendor/src/github.com/docker-library/go-dockerlibrary/pkg/templatelib/lib.go
  60. 526 0
      bashbrew/go/vendor/src/golang.org/x/crypto/cast5/cast5.go
  61. 106 0
      bashbrew/go/vendor/src/golang.org/x/crypto/cast5/cast5_test.go
  62. 219 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/armor/armor.go
  63. 95 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/armor/armor_test.go
  64. 160 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/armor/encode.go
  65. 59 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/canonical_text.go
  66. 52 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/canonical_text_test.go
  67. 376 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/clearsign/clearsign.go
  68. 210 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go
  69. 122 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/elgamal/elgamal.go
  70. 49 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go
  71. 72 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/errors/errors.go
  72. 633 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/keys.go
  73. 274 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/keys_test.go
  74. 123 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/compressed.go
  75. 41 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/compressed_test.go
  76. 91 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/config.go
  77. 199 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/encrypted_key.go
  78. 146 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go
  79. 89 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/literal.go
  80. 143 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/ocfb.go
  81. 46 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/ocfb_test.go
  82. 73 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/one_pass_signature.go
  83. 162 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/opaque.go
  84. 67 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/opaque_test.go
  85. 539 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/packet.go
  86. 255 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/packet_test.go
  87. 362 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/private_key.go
  88. 126 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/private_key_test.go
  89. 750 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/public_key.go
  90. 202 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/public_key_test.go
  91. 280 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/public_key_v3.go
  92. 82 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go
  93. 76 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/reader.go
  94. 706 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/signature.go
  95. 42 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/signature_test.go
  96. 146 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/signature_v3.go
  97. 92 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/signature_v3_test.go
  98. 155 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go
  99. 103 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go
  100. 290 0
      bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go

+ 4 - 0
.gitignore

@@ -1,3 +1,7 @@
 .git
+bashbrew/go/bin
+bashbrew/go/pkg
+bashbrew/go/vendor/bin
+bashbrew/go/vendor/pkg
 bashbrew/logs
 bashbrew/src

+ 18 - 2
.travis.yml

@@ -1,11 +1,27 @@
-language: bash
+language: go
+go: 1.6.2
 
 # allow for use of Docker-based workers
 sudo: false
 
+install:
+    - |
+        GB_VERSION=$(awk '$1 == "ENV" && $2 == "GB_VERSION" { print $3; exit }' Dockerfile)
+        firstGo="${GOPATH%%:*}"
+        mkdir -p "$firstGo/src/github.com/constabulary"
+        (
+            cd "$firstGo/src/github.com/constabulary"
+            wget -qO- "https://github.com/constabulary/gb/archive/v${GB_VERSION}.tar.gz" \
+                | tar -xz
+            mv gb-* gb
+            cd gb
+            go install -v ./...
+        )
+
 before_script:
     - env | sort
+    - ( cd bashbrew/go && gb build )
+    - export PATH="$PWD/bashbrew/go/bin:$PATH"
 
-# --no-build because we has no Docker in Travis :)
 script:
     - ./bashbrew/travis.sh

+ 25 - 2
Dockerfile

@@ -1,12 +1,35 @@
 FROM docker:1.9-git
 
+# add "edge" since Alpine 3.3 only has Go 1.5 and we need 1.6+
+RUN sed -ri -e 'p; s!^!@edge !; s!v[0-9.]+!edge!' /etc/apk/repositories
+
 RUN apk add --update \
 		bash \
+		go@edge \
 	&& rm -rf /var/cache/apk/*
 
+ENV GOPATH /go
+ENV PATH $GOPATH/bin:$PATH
+
+ENV GB_VERSION 0.4.1
+RUN set -x \
+	&& mkdir -p /go/src/github.com/constabulary \
+	&& cd /go/src/github.com/constabulary \
+	&& wget -qO- "https://github.com/constabulary/gb/archive/v${GB_VERSION}.tar.gz" \
+		| tar -xz \
+	&& mv gb-* gb \
+	&& cd gb \
+	&& go install -v ./...
+
 ENV DIR /usr/src/official-images
+ENV PATH $DIR/bashbrew/go/bin:$PATH
+
+ENV BASHBREW_LIBRARY $DIR/library
+ENV BASHBREW_CACHE /bashbrew-cache
+
 WORKDIR $DIR
 COPY . $DIR
-RUN ln -s "$(readlink -f bashbrew/bashbrew.sh)" /usr/local/bin/bashbrew
 
-VOLUME $DIR/bashbrew/logs $DIR/bashbrew/src
+RUN cd bashbrew/go && gb build
+
+VOLUME $BASHBREW_CACHE

+ 43 - 16
README.md

@@ -201,9 +201,9 @@ The `Dockerfile` should be written to help mitigate man-in-the-middle attacks du
 
 ##### Runtime Configuration
 
-By default, Docker containers are executed with reduced privileges: whitelisted Linux capabilities, Control Groups, and a default Seccomp profile (1.10+ w/ host support).  Software running in a container may require additional privileges in order to function correctly, and there are a number of command line options to customize container execution. See [`docker run` Reference](https://docs.docker.com/engine/reference/run/) and [Seccomp for Docker](https://docs.docker.com/engine/security/seccomp/) for reference.
+By default, Docker containers are executed with reduced privileges: whitelisted Linux capabilities, Control Groups, and a default Seccomp profile (1.10+ w/ host support). Software running in a container may require additional privileges in order to function correctly, and there are a number of command line options to customize container execution. See [`docker run` Reference](https://docs.docker.com/engine/reference/run/) and [Seccomp for Docker](https://docs.docker.com/engine/security/seccomp/) for reference.
 
-Official Repositories that require additional privileges should specify the minimal set of command line options for the software to function, and may still be rejected if this introduces significant portability or security issues.  In general, `--privileged` is not allowed, but a combination of `--cap-add` and `--device` options may be acceptable.  Additionally, `--volume` can be tricky as there are many host filesystem locations that introduce portability/security issues (i.e. X11 socket).
+Official Repositories that require additional privileges should specify the minimal set of command line options for the software to function, and may still be rejected if this introduces significant portability or security issues. In general, `--privileged` is not allowed, but a combination of `--cap-add` and `--device` options may be acceptable. Additionally, `--volume` can be tricky as there are many host filesystem locations that introduce portability/security issues (i.e. X11 socket).
 
 ### Commitment
 
@@ -223,7 +223,44 @@ The filename of a definition file will determine the name of the image repositor
 
 ### Instruction format
 
-	<docker-tag>: <git-url>@<git-commit-id>
+The manifest file format is officially based on [RFC 2822](https://www.ietf.org/rfc/rfc2822.txt), and as such should be familiar to folks who are already familiar with the "headers" of many popular internet protocols/formats such as HTTP or email.
+
+	Maintainers: John Smith <[email protected]> (@example-jsmith),
+	             Anne Smith <[email protected]> (@example-asmith)
+	
+	Tags: 4.1.1, 4.1, 4, latest
+	GitRepo: https://github.com/docker-library/wordpress.git
+	GitCommit: bbef6075afa043cbfe791b8de185105065c02c01
+	
+	Tags: 2.6.17, 2.6
+	GitRepo: https://github.com/docker-library/redis.git
+	GitCommit: 062335e0a8d20cab2041f25dfff2fbaf58544471
+	Directory: 2.6
+	
+	Tags: 13.2, harlequin
+	GitRepo: https://github.com/openSUSE/docker-containers-build.git
+	GitFetch: refs/heads/openSUSE-13.1
+	GitCommit: 0d21bc58cd26da2a0a59588affc506b977d6a846
+	Directory: docker
+	Constraints: !aufs
+
+Bashbrew will fetch code out of the Git repository (`GitRepo`) at the commit specified (`GitCommit`). If the commit referenced is not available by fetching `master` of the associated `GitRepo`, it becomes necessary to supply a value for `GitFetch` in order to tell Bashbrew what ref to fetch in order to get the commit necessary.
+
+The built image will be tagged as `<manifest-filename>:<tag>` (ie, `library/golang` with a `Tags` value of `1.6, 1, latest` will create tags of `golang:1.6`, `golang:1`, and `golang:latest`).
+
+Optionally, if `Directory` is present, Bashbrew will look for the `Dockerfile` inside the specified subdirectory instead of at the root (and `Directory` will be used as the ["context" for the build](https://docs.docker.com/reference/builder/) instead of the top-level of the repository).
+
+#### Deprecated format
+
+This is the older, now-deprecated format for library manifest files. Its usage is discouraged (although it is still supported).
+
+	# maintainer: Your Name <[email protected]> (@github.name)
+	
+	# maintainer: John Smith <[email protected]> (@example-jsmith)
+	# maintainer: Anne Smith <[email protected]> (@example-asmith)
+	
+	
+	<Tag>: <GitRepo>@<GitCommit>
 	
 	4.1.1: git://github.com/docker-library/wordpress@bbef6075afa043cbfe791b8de185105065c02c01
 	4.1: git://github.com/docker-library/wordpress@bbef6075afa043cbfe791b8de185105065c02c01
@@ -231,7 +268,7 @@ The filename of a definition file will determine the name of the image repositor
 	latest: git://github.com/docker-library/wordpress@bbef6075afa043cbfe791b8de185105065c02c01
 	
 	
-	<docker-tag>: <git-url>@<git-commit-id> <dockerfile-dir>
+	<Tag>: <GitRepo>@<GitCommit> <Directory>
 	
 	2.6.17: git://github.com/docker-library/redis@062335e0a8d20cab2041f25dfff2fbaf58544471 2.6
 	2.6: git://github.com/docker-library/redis@062335e0a8d20cab2041f25dfff2fbaf58544471 2.6
@@ -243,34 +280,24 @@ The filename of a definition file will determine the name of the image repositor
 	
 	experimental: git://github.com/tianon/dockerfiles@90d86ad63c4a06b7d04d14ad830381b876183b3c debian/experimental
 
-Bashbrew will fetch code out of the Git repository at the commit specified here. The generated image will be tagged as `<manifest-filename>:<docker-tag>`.
-
-Using Git tags instead of explicit Git commit references is supported, but heavily discouraged. For example, if a Git tag is changed on the referenced repository to point to another commit, **the image will not be rebuilt**. Instead, either create a new tag (or reference an exact commit) and submit a pull request.
-
-Optionally, if `<dockerfile-dir>` is present, Bashbrew will look for the `Dockerfile` inside the specified subdirectory instead of at the root (and `<dockerfile-dir>` will be used as the ["context" for the build](https://docs.docker.com/reference/builder/)).
+Using Git tags instead of explicit Git commit references is supported for the deprecated format only, but is heavily discouraged. For example, if a Git tag is changed on the referenced repository to point to another commit, **the image will not be rebuilt**. Instead, either create a new tag (or reference an exact commit) and submit a pull request.
 
 ### Creating a new repository
 
 -	Create a new file in the `library/` folder. Its name will be the name of your repository on the Hub.
 -	Add your tag definitions using the appropriate syntax (see above).
--	Add a line similar to the following to the top of the file:
-
-		# maintainer: Your Name <[email protected]> (@github.name)
-
 -	Create a pull request adding the file from your forked repository to this one. Please be sure to add details as to what your repository does.
 
 ### Adding a new tag in an existing repository (that you're the maintainer of)
 
 -	Add your tag definition using the instruction format documented above.
 -	Create a pull request from your Git repository to this one. Please be sure to add details about what's new, if possible.
--	In the pull request comments, feel free to prod the repository's maintainers (found in the relevant `MAINTAINERS` file) using GitHub's @-mentions.
 
 ### Change to a tag in an existing repository (that you're the maintainer of)
 
 -	Update the relevant tag definition using the instruction format documented above.
 -	Create a pull request from your Git repository to this one. Please be sure to add details about what's changed, if possible.
--	In the pull request comments, feel free to prod the repository's maintainers (found in the relevant `MAINTAINERS` file) using GitHub's @-mentions.
 
 ## Bashbrew
 
-Bashbrew is a set of bash scripts for cloning, building, tagging, and pushing the Docker official images. See [`README.md` in the `bashbrew/` subfolder](bashbrew/README.md) for more information.
+Bashbrew (`bashbrew`) is a tool for cloning, building, tagging, and pushing the Docker official images. See [`README.md` in the `bashbrew/` subfolder](bashbrew/README.md) for more information.

+ 60 - 98
bashbrew/README.md

@@ -1,120 +1,82 @@
-# Bashbrew
-
-The recommended way to use `bashbrew.sh` is to install a symlink in your `PATH` somewhere as `bashbrew`, for example `~/bin/bashbrew -> /path/to/official-images/bashbrew/bashbrew.sh` (assuming `~/bin` is in `PATH`).
+# Bashbrew (`bashbrew`)
 
 ```console
 $ bashbrew --help
-
-usage: bashbrew [build|push|list] [options] [repo[:tag] ...]
-   ie: bashbrew build --all
-       bashbrew push debian ubuntu:12.04
-       bashbrew list --namespaces='_' debian:7 hello-world
-
-This script processes the specified Docker images using the corresponding
-repository manifest files.
-
-common options:
-  --all              Build all repositories specified in library
-  --docker="docker"
-                     Use a custom Docker binary
-  --retries="4"
-                     How many times to try again if the build/push fails before
-                     considering it a lost cause (always attempts a minimum of
-                     one time, but maximum of one plus this number)
-  --help, -h, -?     Print this help message
-  --library="/home/tianon/docker/stackbrew/library"
-                     Where to find repository manifest files
-  --logs="/home/tianon/docker/stackbrew/bashbrew/logs"
-                     Where to store the build logs
-  --namespaces="_"
-                     Space separated list of image namespaces to act upon
-                     
-                     Note that "_" is a special case here for the unprefixed
-                     namespace (ie, "debian" vs "library/debian"), and as such
-                     will be implicitly ignored by the "push" subcommand
-                     
-                     Also note that "build" will always tag to the unprefixed
-                     namespace because it is necessary to do so for dependent
-                     images to use FROM correctly (think "onbuild" variants that
-                     are "FROM base-image:some-version")
-  --uniq
-                     Only process the first tag of identical images
-                     This is not recommended for build or push
-                     i.e. process python:2.7, but not python:2
-
-build options:
-  --no-build         Don't build, print what would build
-  --no-clone         Don't pull/clone Git repositories
-  --src="/home/tianon/docker/stackbrew/bashbrew/src"
-                     Where to store cloned Git repositories (GOPATH style)
-
-push options:
-  --no-push          Don't push, print what would push
+NAME:
+   bashbrew - canonical build tool for the official images
+
+USAGE:
+   bashbrew [global options] command [command options] [arguments...]
+
+COMMANDS:
+     list   list repo:tag combinations for a given repo
+     build  build (and tag) repo:tag combinations for a given repo
+     tag    tag repo:tag into a namespace (especially for pushing)
+     push   push namespace/repo:tag (see also "tag")
+
+   plumbing:
+     children  print the repos built FROM a given repo or repo:tag
+     parents   print the repos this repo or repo:tag is FROM
+     cat       print manifest contents for repo or repo:tag
+     from      print FROM for repo:tag
+
+GLOBAL OPTIONS:
+   --debug                  enable more output (esp. all "docker build" output instead of only output on failure) [$BASHBREW_DEBUG]
+   --no-sort                do not apply any sorting, even via --build-order
+   --constraint value       build constraints (see Constraints in Manifest2822Entry)
+   --exclusive-constraints  skip entries which do not have Constraints
+   --config value           where default "flags" configuration can be overridden more persistently (default: "/home/tianon/.config/bashbrew") [$BASHBREW_CONFIG]
+   --library value          where the bodies are buried (default: "/home/tianon/docker/official-images/library") [$BASHBREW_LIBRARY]
+   --cache value            where the git wizardry is stashed (default: "/home/tianon/.cache/bashbrew") [$BASHBREW_CACHE]
+   --help, -h, -?           show help
 
 ```
 
-## Subcommands
-
-### `bashbrew build`
+## Building
 
-This script reads the library files for the images specified and then clones the required Git repositories into the specified `--src` directory. If the Git repository already exists, the script verifies that the Git ref specified in the library file exists and does `git fetch` as necessary.
+Bashbrew itself is built using `gb` ([github.com/constabulary/gb](https://github.com/constabulary/gb)).
 
-The next step in the script is to build each image specified. All the `image:tag` combinations are placed into a queue. The processing order is determined by the order of items passed in on the command line (or alphabetical if `--all` is used). When a whole image, like `debian`, is specified the `image:tag` combinations are added to the queue in the order that they appear in the library file. For each `image:tag` to be processed, the system checks out the specified commit and sets mtimes (see [`git-set-mtimes`](#git-set-mtimes)) of all files in the Git repository to take advantage of Docker caching. If the `image:tag` is `FROM` another image that is later in the queue, it is deferred to the end of the queue.
+Once in the `go` subdirectory, `gb build` should produce `go/bin/bashbrew`, ready for use.
 
-After the image is built, the final step of the script is to tag the image into each of the given `--namespaces`.
+## Usage
 
-The `--no-clone` option skips the `git clone` step and will cause the script to fail on the build step if the Git repository does not exist or is missing the required Git refs.
+In general, `bashbrew build some-repo` or `bashbrew build ./some-file` should be sufficient for using the tool at a surface level, especially for testing. For more complex usage, please see the built-in help (`bashbrew --help`, `bashbrew build --help`, etc).
 
-The `--no-build` option skips all the building, including setting the mtimes.
+## Configuration
 
-**WARNING:** setting `--src` so that it uses a local working copy of your Git directory for a specified build will delete untracked and uncommitted changes, and will disable `gc.auto`. It is not recommended to symlink in your working directories for use during build.
+The default "flags" configuration is in `~/.config/bashbrew/flags`, but the base path can be overridden with `--config` or `BASHBREW_CONFIG` (technically, the full path to the `flags` configuration file is `${BASHBREW_CONFIG:-${XDG_CONFIG_HOME:-$HOME/.config}/bashbrew}/flags`).
 
-### `bashbrew push`
+To set a default namespace for specific commands only:
 
-This script takes advantage of `docker login` and does a `docker push` on each `image:tag` specified for the given `--namespaces`. The script will warn if a given `namespace/image:tag` does not exist.
-
-The `--no-push` option prints out the `docker push` instructions that would have been executed.
+```
+Commands: tag, push
+Namespace: officialstaging
+```
 
-### `bashbrew list`
+To set a default namespace for all commands:
 
-Takes the same arguments as `bashbrew build` and `bashbrew push`, but prints a list of image names and quits.
+```
+Namespace: jsmith
+```
 
-For example:
+A more complex example:
 
-```console
-$ # count the number of tags in the official library
-$ bashbrew list --all | wc -l
-802
-$ # count the number of _unique_ tags in the official library
-$ bashbrew list --all --uniq | wc -l
-296
-
-$ # pull all officially supported tags of "debian"
-$ bashbrew list debian | xargs -n1 --verbose docker pull
-...
-
-$ # list all unique supported tags of "python"
-$ bashbrew list --uniq python
-python:2.7.10
-python:2.7.10-onbuild
-python:2.7.10-slim
-python:2.7.10-wheezy
-python:3.2.6
-python:3.2.6-onbuild
-python:3.2.6-slim
-python:3.2.6-wheezy
-python:3.3.6
-python:3.3.6-onbuild
-python:3.3.6-slim
-python:3.3.6-wheezy
-python:3.4.3
-python:3.4.3-onbuild
-python:3.4.3-slim
-python:3.4.3-wheezy
 ```
+# comments are allowed anywhere (and are ignored)
+Library: /mnt/docker/official-images/library
+Cache: /mnt/docker/bashbrew-cache
+Constraints: aufs, docker-1.9, tianon
+ExclusiveConstraints: true
 
-## Helper Scripts
+# namespace just "tag" and "push" (not "build")
+Commands: tag, push
+Namespace: tianon
 
-### `git-set-mtimes`
+Commands: list
+ApplyConstraints: true
+
+Commands: tag
+Debug: true
+```
 
-Since Docker caching of layers is based upon the mtimes of files and folders, this script sets each file's mtime to the time of the commit that most recently modified it and sets each directory's mtime to be the most recent mtime of any file or folder contained within it. This gives a deterministic time for all files and folders in the Git repository.
+In this example, `bashbrew tag` will get both `Namespace` and `Debug` applied.

+ 4 - 425
bashbrew/bashbrew.sh

@@ -1,433 +1,12 @@
 #!/bin/bash
 set -e
 
-# make sure we can GTFO
-trap 'echo >&2 Ctrl+C captured, exiting; exit 1' SIGINT
-
 dir="$(dirname "$(readlink -f "$BASH_SOURCE")")"
 
-library="$(dirname "$dir")/library"
-src="$dir/src"
-logs="$dir/logs"
-namespaces='_'
-docker='docker'
-retries='4'
-
-self="$(basename "$0")"
-
-usage() {
-	cat <<-EOUSAGE
-		
-		usage: $self [build|push|list] [options] [repo[:tag] ...]
-		   ie: $self build --all
-		       $self push debian ubuntu:12.04
-		       $self list --namespaces='_' debian:7 hello-world
-		
-		This script processes the specified Docker images using the corresponding
-		repository manifest files.
-		
-		common options:
-		  --all              Build all repositories specified in library
-		  --docker="$docker"
-		                     Use a custom Docker binary
-		  --retries="$retries"
-		                     How many times to try again if the build/push fails before
-		                     considering it a lost cause (always attempts a minimum of
-		                     one time, but maximum of one plus this number)
-		  --help, -h, -?     Print this help message
-		  --library="$library"
-		                     Where to find repository manifest files
-		  --logs="$logs"
-		                     Where to store the build logs
-		  --namespaces="$namespaces"
-		                     Space separated list of image namespaces to act upon
-		                     
-		                     Note that "_" is a special case here for the unprefixed
-		                     namespace (ie, "debian" vs "library/debian"), and as such
-		                     will be implicitly ignored by the "push" subcommand
-		                     
-		                     Also note that "build" will always tag to the unprefixed
-		                     namespace because it is necessary to do so for dependent
-		                     images to use FROM correctly (think "onbuild" variants that
-		                     are "FROM base-image:some-version")
-		  --uniq
-		                     Only process the first tag of identical images
-		                     This is not recommended for build or push
-		                     i.e. process python:2.7, but not python:2
-		
-		build options:
-		  --no-build         Don't build, print what would build
-		  --no-clone         Don't pull/clone Git repositories
-		  --src="$src"
-		                     Where to store cloned Git repositories (GOPATH style)
-		
-		push options:
-		  --no-push          Don't push, print what would push
-		
-	EOUSAGE
-}
-
-# arg handling
-opts="$(getopt -o 'h?' --long 'all,docker:,help,library:,logs:,namespaces:,no-build,no-clone,no-push,retries:,src:,uniq' -- "$@" || { usage >&2 && false; })"
-eval set -- "$opts"
-
-doClone=1
-doBuild=1
-doPush=1
-buildAll=
-onlyUniq=
-while true; do
-	flag="$1"
-	shift
-	case "$flag" in
-		--all) buildAll=1 ;;
-		--docker) docker="$1" && shift ;;
-		--help|-h|'-?') usage && exit 0 ;;
-		--library) library="$1" && shift ;;
-		--logs) logs="$1" && shift ;;
-		--namespaces) namespaces="$1" && shift ;;
-		--no-build) doBuild= ;;
-		--no-clone) doClone= ;;
-		--no-push) doPush= ;;
-		--retries) retries="$1" && (( retries++ )) && shift ;;
-		--src) src="$1" && shift ;;
-		--uniq) onlyUniq=1 ;;
-		--) break ;;
-		*)
-			{
-				echo "error: unknown flag: $flag"
-				usage
-			} >&2
-			exit 1
-			;;
-	esac
-done
-
-if [ ! -d "$library" ]; then
-	echo >&2 "error: library directory '$library' does not exist"
-	exit 1
-fi
-library="$(readlink -f "$library")"
-mkdir -p "$src" "$logs"
-src="$(readlink -f "$src")"
-logs="$(readlink -f "$logs")"
-
-# which subcommand
-subcommand="$1"
-shift || { usage >&2 && exit 1; }
-case "$subcommand" in
-	build|push|list) ;;
-	*)
-		{
-			echo "error: unknown subcommand: $1"
-			usage
-		} >&2
-		exit 1
-		;;
-esac
-
-repos=()
-if [ "$buildAll" ]; then
-	repos=( "$library"/* )
+if ! command -v gb &> /dev/null; then
+	( set -x && go get github.com/constabulary/gb/... )
 fi
-repos+=( "$@" )
-
-repos=( "${repos[@]%/}" )
-
-if [ "${#repos[@]}" -eq 0 ]; then
-	{
-		echo 'error: no repos specified'
-		usage
-	} >&2
-	exit 1
-fi
-
-# globals for handling the repo queue and repo info parsed from library
-queue=()
-declare -A repoGitRepo=()
-declare -A repoGitRef=()
-declare -A repoGitDir=()
-declare -A repoUniq=()
-
-logDir="$logs/$subcommand-$(date +'%Y-%m-%d--%H-%M-%S')"
-mkdir -p "$logDir"
-
-latestLogDir="$logs/latest" # this gets shiny symlinks to the latest buildlog for each repo we've seen since the creation of the logs dir
-mkdir -p "$latestLogDir"
-
-didFail=
-
-# gather all the `repo:tag` combos to build
-for repoTag in "${repos[@]}"; do
-	repo="${repoTag%%:*}"
-	tag="${repoTag#*:}"
-	[ "$repo" != "$tag" ] || tag=
-	
-	if [ "$repo" = 'http' -o "$repo" = 'https' ] && [[ "$tag" == //* ]]; then
-		# IT'S A URL!
-		repoUrl="$repo:${tag%:*}"
-		repo="$(basename "$repoUrl")"
-		if [ "${tag##*:}" != "$tag" ]; then
-			tag="${tag##*:}"
-		else
-			tag=
-		fi
-		repoTag="${repo}${tag:+:$tag}"
-		
-		echo "$repoTag ($repoUrl)" >> "$logDir/repos.txt"
-		
-		cmd=( curl -sSL --compressed "$repoUrl" )
-	else
-		if [ -f "$repo" ]; then
-			repoFile="$repo"
-			repo="$(basename "$repoFile")"
-			repoTag="${repo}${tag:+:$tag}"
-		else
-			repoFile="$library/$repo"
-		fi
-		
-		if [ ! -f "$repoFile" ]; then
-			echo >&2 "error: '$repoFile' does not exist!"
-			didFail=1
-			continue
-		fi
-		
-		repoFile="$(readlink -f "$repoFile")"
-		echo "$repoTag ($repoFile)" >> "$logDir/repos.txt"
-		
-		cmd=( cat "$repoFile" )
-	fi
-	
-	if [ "${repoGitRepo[$repoTag]}" ]; then
-		if [ "$onlyUniq" ]; then
-			uniqLine="${repoGitRepo[$repoTag]}@${repoGitRef[$repoTag]} ${repoGitDir[$repoTag]}"
-			if [ -z "${repoUniq[$uniqLine]}" ]; then
-				queue+=( "$repoTag" )
-				repoUniq[$uniqLine]=$repoTag
-			fi
-		else
-			queue+=( "$repoTag" )
-		fi
-		continue
-	fi
-	
-	if ! manifest="$("${cmd[@]}")"; then
-		echo >&2 "error: failed to fetch $repoTag (${cmd[*]})"
-		exit 1
-	fi
-	
-	# parse the repo manifest file
-	IFS=$'\n'
-	repoTagLines=( $(echo "$manifest" | grep -vE '^#|^\s*$') )
-	unset IFS
-	
-	tags=()
-	for line in "${repoTagLines[@]}"; do
-		tag="$(echo "$line" | awk -F ': +' '{ print $1 }')"
-		for parsedRepoTag in "${tags[@]}"; do
-			if [ "$repo:$tag" = "$parsedRepoTag" ]; then
-				echo >&2 "error: tag '$tag' is duplicated in '${cmd[@]}'"
-				exit 1
-			fi
-		done
-		
-		repoDir="$(echo "$line" | awk -F ': +' '{ print $2 }')"
-		
-		gitUrl="${repoDir%%@*}"
-		commitDir="${repoDir#*@}"
-		gitRef="${commitDir%% *}"
-		gitDir="${commitDir#* }"
-		if [ "$gitDir" = "$commitDir" ]; then
-			gitDir=
-		fi
-		
-		gitRepo="${gitUrl#*://}"
-		gitRepo="${gitRepo%/}"
-		gitRepo="${gitRepo%.git}"
-		gitRepo="${gitRepo%/}"
-		gitRepo="$src/$gitRepo"
-		
-		if [ "$subcommand" = 'build' ]; then
-			if [ -z "$doClone" ]; then
-				if [ "$doBuild" -a ! -d "$gitRepo" ]; then
-					echo >&2 "error: directory not found: $gitRepo"
-					exit 1
-				fi
-			else
-				if [ ! -d "$gitRepo" ]; then
-					mkdir -p "$(dirname "$gitRepo")"
-					echo "Cloning $repo ($gitUrl) ..."
-					git clone -q "$gitUrl" "$gitRepo"
-				else
-					# if we don't have the "ref" specified, "git fetch" in the hopes that we get it
-					if ! ( cd "$gitRepo" && git rev-parse --verify "${gitRef}^{commit}" &> /dev/null ); then
-						echo "Fetching $repo ($gitUrl) ..."
-						( cd "$gitRepo" && git fetch -q --all && git fetch -q --tags )
-					fi
-				fi
-				
-				# disable any automatic garbage collection too, just to help make sure we keep our dangling commit objects
-				( cd "$gitRepo" && git config gc.auto 0 )
-			fi
-		fi
-		
-		repoGitRepo[$repo:$tag]="$gitRepo"
-		repoGitRef[$repo:$tag]="$gitRef"
-		repoGitDir[$repo:$tag]="$gitDir"
-		tags+=( "$repo:$tag" )
-	done
-	
-	if [ "$repo" != "$repoTag" ]; then
-		tags=( "$repoTag" )
-	fi
-	
-	if [ "$onlyUniq" ]; then
-		for rt in "${tags[@]}"; do
-			uniqLine="${repoGitRepo[$rt]}@${repoGitRef[$rt]} ${repoGitDir[$rt]}"
-			if [ -z "${repoUniq[$uniqLine]}" ]; then
-				queue+=( "$rt" )
-				repoUniq[$uniqLine]=$rt
-			fi
-		done
-	else
-		# add all tags we just parsed
-		queue+=( "${tags[@]}" )
-	fi
-done
-
-# usage: gitCheckout "$gitRepo" "$gitRef" "$gitDir"
-gitCheckout() {
-	[ "$1" -a "$2" ] || return 1 # "$3" is allowed to be the empty string
-	(
-		set -x
-		cd "$1"
-		git reset -q HEAD
-		git checkout -q -- .
-		git clean -dfxq
-		git checkout -q "$2" --
-		cd "$1/$3"
-		"$dir/git-set-mtimes"
-	)
-	return 0
-}
 
-set -- "${queue[@]}"
-while [ "$#" -gt 0 ]; do
-	repoTag="$1"
-	gitRepo="${repoGitRepo[$repoTag]}"
-	gitRef="${repoGitRef[$repoTag]}"
-	gitDir="${repoGitDir[$repoTag]}"
-	shift
-	if [ -z "$gitRepo" ]; then
-		echo >&2 'Unknown repo:tag:' "$repoTag"
-		didFail=1
-		continue
-	fi
-	
-	thisLog="$logDir/$subcommand-$repoTag.log"
-	touch "$thisLog"
-	thisLogSymlink="$latestLogDir/$(basename "$thisLog")"
-	ln -sf "$thisLog" "$thisLogSymlink"
-	
-	case "$subcommand" in
-		build)
-			echo "Processing $repoTag ..."
-			
-			if ! ( cd "$gitRepo" && git rev-parse --verify "${gitRef}^{commit}" &> /dev/null ); then
-				echo "- failed; invalid ref: $gitRef"
-				didFail=1
-				continue
-			fi
-			
-			dockerfilePath="$gitDir/Dockerfile"
-			dockerfilePath="${dockerfilePath#/}" # strip leading "/" (for when gitDir is '') because "git show" doesn't like it
-			
-			if ! dockerfile="$(cd "$gitRepo" && git show "$gitRef":"$dockerfilePath")"; then
-				echo "- failed; missing '$dockerfilePath' at '$gitRef' ?"
-				didFail=1
-				continue
-			fi
-			
-			IFS=$'\n'
-			froms=( $(echo "$dockerfile" | awk 'toupper($1) == "FROM" { print $2 ~ /:/ ? $2 : $2":latest" }') )
-			unset IFS
-			
-			for from in "${froms[@]}"; do
-				for queuedRepoTag in "$@"; do
-					if [ "$from" = "$queuedRepoTag" ]; then
-						# a "FROM" in this image is being built later in our queue, so let's bail on this image for now and come back later
-						echo "- deferred; FROM $from"
-						set -- "$@" "$repoTag"
-						continue 3
-					fi
-				done
-			done
-			
-			if [ "$doBuild" ]; then
-				if ! gitCheckout "$gitRepo" "$gitRef" "$gitDir" &>> "$thisLog"; then
-					echo "- failed 'git checkout'; see $thisLog"
-					didFail=1
-					continue
-				fi
-				
-				tries="$retries"
-				while ! ( set -x && "$docker" build -t "$repoTag" "$gitRepo/$gitDir" ) &>> "$thisLog"; do
-					(( tries-- )) || true
-					if [ $tries -le 0 ]; then
-						echo >&2 "- failed 'docker build'; see $thisLog"
-						didFail=1
-						continue 2
-					fi
-				done
-				
-				for namespace in $namespaces; do
-					if [ "$namespace" = '_' ]; then
-						# images FROM other images is explicitly supported
-						continue
-					fi
-					if ! ( set -x && "$docker" tag -f "$repoTag" "$namespace/$repoTag" ) &>> "$thisLog"; then
-						echo "- failed 'docker tag'; see $thisLog"
-						didFail=1
-						continue
-					fi
-				done
-			fi
-			;;
-		list)
-			for namespace in $namespaces; do
-				if [ "$namespace" = '_' ]; then
-					echo "$repoTag"
-				else
-					echo "$namespace/$repoTag"
-				fi
-			done
-			;;
-		push)
-			for namespace in $namespaces; do
-				if [ "$namespace" = '_' ]; then
-					# can't "docker push debian"; skip this namespace
-					continue
-				fi
-				if [ "$doPush" ]; then
-					echo "Pushing $namespace/$repoTag..."
-					tries="$retries"
-					while ! ( set -x && "$docker" push "$namespace/$repoTag" < /dev/null ) &>> "$thisLog"; do
-						(( tries-- )) || true
-						if [ $tries -le 0 ]; then
-							echo >&2 "- $namespace/$repoTag failed to push; see $thisLog"
-							continue 2
-						fi
-					done
-				else
-					echo "$docker push" "$namespace/$repoTag"
-				fi
-			done
-			;;
-	esac
-	
-	if [ ! -s "$thisLog" ]; then
-		rm "$thisLog" "$thisLogSymlink"
-	fi
-done
+( cd "$dir/go" && gb build > /dev/null )
 
-[ -z "$didFail" ]
+exec "$dir/go/bin/bashbrew" "$@"

+ 0 - 1
bashbrew/build.sh

@@ -1 +0,0 @@
-deprecated.sh

+ 0 - 9
bashbrew/deprecated.sh

@@ -1,9 +0,0 @@
-#!/bin/bash
-set -e
-
-dir="$(dirname "$(readlink -f "$BASH_SOURCE")")"
-cmd="$(basename "$0" '.sh')"
-
-echo >&2 "warning: '$0' is deprecated, and '$dir/bashbrew.sh $cmd' should be used directly instead"
-
-exec "$dir/bashbrew.sh" "$cmd" "$@"

+ 0 - 16
bashbrew/git-set-mtimes

@@ -1,16 +0,0 @@
-#!/bin/bash
-set -e
-
-IFS=$'\n'
-files=( $({ git ls-files | xargs -n1 dirname | sort -u && git ls-files; } | sort -r) )
-unset IFS
-
-for f in "${files[@]}"; do
-	if [ ! -e "$f" ]; then
-		# don't try touching files that don't exist
-		continue
-	fi
-	stamp="$(git --no-pager log -1 --format='format:%ai' -- "$f")"
-	touchFormat="$(date --date="$stamp" +'%Y%m%d%H%M.%S')"
-	touch --no-dereference -t "$touchFormat" "$f"
-done

+ 94 - 0
bashbrew/go/src/bashbrew/cmd-build.go

@@ -0,0 +1,94 @@
+package main
+
+import (
+	"fmt"
+
+	"github.com/codegangsta/cli"
+)
+
+func cmdBuild(c *cli.Context) error {
+	repos, err := repos(c.Bool("all"), c.Args()...)
+	if err != nil {
+		return cli.NewMultiError(fmt.Errorf(`failed gathering repo list`), err)
+	}
+
+	repos, err = sortRepos(repos)
+	if err != nil {
+		return cli.NewMultiError(fmt.Errorf(`failed sorting repo list`, err))
+	}
+
+	uniq := c.Bool("uniq")
+	namespace := c.String("namespace")
+	pullMissing := c.Bool("pull-missing")
+
+	for _, repo := range repos {
+		r, err := fetch(repo)
+		if err != nil {
+			return cli.NewMultiError(fmt.Errorf(`failed fetching repo %q`, repo), err)
+		}
+
+		entries, err := r.SortedEntries()
+		if err != nil {
+			return cli.NewMultiError(fmt.Errorf(`failed sorting entries list for %q`, repo), err)
+		}
+
+		for _, entry := range entries {
+			if r.SkipConstraints(entry) {
+				continue
+			}
+
+			from, err := r.DockerFrom(&entry)
+			if err != nil {
+				return cli.NewMultiError(fmt.Errorf(`failed fetching/scraping FROM for %q (tags %q)`, r.RepoName, entry.TagsString()), err)
+			}
+
+			if pullMissing && from != "scratch" {
+				_, err := dockerInspect("{{.Id}}", from)
+				if err != nil {
+					fmt.Printf("Pulling %s (%s)\n", from, r.Identifier())
+					dockerPull(from)
+				}
+			}
+
+			cacheHash, err := r.dockerCacheHash(&entry)
+			if err != nil {
+				return cli.NewMultiError(fmt.Errorf(`failed calculating "cache hash" for %q (tags %q)`, r.RepoName, entry.TagsString()), err)
+			}
+
+			cacheTag := "bashbrew/cache:" + cacheHash
+
+			// check whether we've already built this artifact
+			_, err = dockerInspect("{{.Id}}", cacheTag)
+			if err != nil {
+				fmt.Printf("Building %s (%s)\n", cacheTag, r.Identifier())
+
+				commit, err := r.fetchGitRepo(&entry)
+				if err != nil {
+					return cli.NewMultiError(fmt.Errorf(`failed fetching git repo for %q (tags %q)`, r.RepoName, entry.TagsString()), err)
+				}
+
+				archive, err := gitArchive(commit, entry.Directory)
+				if err != nil {
+					return cli.NewMultiError(fmt.Errorf(`failed generating git archive for %q (tags %q)`, r.RepoName, entry.TagsString()), err)
+				}
+				defer archive.Close()
+
+				err = dockerBuild(cacheTag, archive)
+				if err != nil {
+					return cli.NewMultiError(fmt.Errorf(`failed building %q (tags %q)`, r.RepoName, entry.TagsString()), err)
+				}
+			}
+
+			for _, tag := range r.Tags(namespace, uniq, entry) {
+				fmt.Printf("Tagging %s\n", tag)
+
+				err := dockerTag(cacheTag, tag)
+				if err != nil {
+					return cli.NewMultiError(fmt.Errorf(`failed tagging %q as %q`, cacheTag, tag), err)
+				}
+			}
+		}
+	}
+
+	return nil
+}

+ 70 - 0
bashbrew/go/src/bashbrew/cmd-cat.go

@@ -0,0 +1,70 @@
+package main
+
+import (
+	"bytes"
+	"fmt"
+	"io/ioutil"
+	"strings"
+	"text/template"
+
+	"github.com/codegangsta/cli"
+	"github.com/docker-library/go-dockerlibrary/pkg/templatelib"
+)
+
+var DefaultCatFormat = `
+{{- if i }}{{ "\n\n" }}{{ end -}}
+{{- .TagName | ternary (.Manifest.GetTag .TagName) .Manifest -}}
+`
+
+func cmdCat(c *cli.Context) error {
+	repos, err := repos(c.Bool("all"), c.Args()...)
+	if err != nil {
+		return cli.NewMultiError(fmt.Errorf(`failed gathering repo list`), err)
+	}
+
+	format := c.String("format")
+	formatFile := c.String("format-file")
+
+	templateName := "--format"
+	tmplMultiErr := fmt.Errorf(`failed parsing --format %q`, format)
+	if formatFile != "" {
+		b, err := ioutil.ReadFile(formatFile)
+		if err != nil {
+			return cli.NewMultiError(fmt.Errorf(`failed reading --format-file %q`, formatFile), err)
+		}
+		templateName = formatFile
+		tmplMultiErr = fmt.Errorf(`failed parsing --format-file %q`, formatFile)
+		format = string(b)
+	}
+
+	var i int
+	tmpl, err := template.New(templateName).Funcs(templatelib.FuncMap).Funcs(template.FuncMap{
+		"i": func() int {
+			return i
+		},
+	}).Parse(format)
+	if err != nil {
+		return cli.NewMultiError(tmplMultiErr, err)
+	}
+
+	var repo string
+	for i, repo = range repos {
+		r, err := fetch(repo)
+		if err != nil {
+			return cli.NewMultiError(fmt.Errorf(`failed fetching repo %q`, repo), err)
+		}
+
+		buf := &bytes.Buffer{}
+		err = tmpl.ExecuteTemplate(buf, templateName, r)
+		if err != nil {
+			return cli.NewMultiError(fmt.Errorf(`failed executing template`), err)
+		}
+		out := buf.String()
+		fmt.Print(out)
+		if !strings.HasSuffix(out, "\n") {
+			fmt.Println()
+		}
+	}
+
+	return nil
+}

+ 105 - 0
bashbrew/go/src/bashbrew/cmd-deps.go

@@ -0,0 +1,105 @@
+package main
+
+import (
+	"fmt"
+
+	"github.com/codegangsta/cli"
+	"pault.ag/go/topsort"
+)
+
+func cmdOffspring(c *cli.Context) error {
+	return cmdFamily(false, c)
+}
+
+func cmdParents(c *cli.Context) error {
+	return cmdFamily(true, c)
+}
+
+func cmdFamily(parents bool, c *cli.Context) error {
+	depsRepos, err := repos(c.Bool("all"), c.Args()...)
+	if err != nil {
+		return cli.NewMultiError(fmt.Errorf(`failed gathering repo list`), err)
+	}
+
+	uniq := c.Bool("uniq")
+	applyConstraints := c.Bool("apply-constraints")
+
+	allRepos, err := repos(true)
+	if err != nil {
+		return cli.NewMultiError(fmt.Errorf(`failed gathering ALL repos list`), err)
+	}
+
+	// create network (all repos)
+	network := topsort.NewNetwork()
+
+	// add nodes
+	for _, repo := range allRepos {
+		r, err := fetch(repo)
+		if err != nil {
+			return cli.NewMultiError(fmt.Errorf(`failed fetching repo %q`, repo), err)
+		}
+
+		for _, entry := range r.Entries() {
+			for _, tag := range r.Tags("", false, entry) {
+				network.AddNode(tag, entry)
+			}
+		}
+	}
+
+	// add edges
+	for _, repo := range allRepos {
+		r, err := fetch(repo)
+		if err != nil {
+			return cli.NewMultiError(fmt.Errorf(`failed fetching repo %q`, repo), err)
+		}
+		for _, entry := range r.Entries() {
+			from, err := r.DockerFrom(&entry)
+			if err != nil {
+				return cli.NewMultiError(fmt.Errorf(`failed fetching/scraping FROM for %q (tags %q)`, r.RepoName, entry.TagsString()), err)
+			}
+			for _, tag := range r.Tags("", false, entry) {
+				network.AddEdge(from, tag)
+			}
+		}
+	}
+
+	// now the real work
+	seen := map[*topsort.Node]bool{}
+	for _, repo := range depsRepos {
+		r, err := fetch(repo)
+		if err != nil {
+			return cli.NewMultiError(fmt.Errorf(`failed fetching repo %q`, repo), err)
+		}
+
+		for _, entry := range r.Entries() {
+			if applyConstraints && r.SkipConstraints(entry) {
+				continue
+			}
+
+			for _, tag := range r.Tags("", uniq, entry) {
+				nodes := []*topsort.Node{}
+				if parents {
+					nodes = append(nodes, network.Get(tag).InboundEdges...)
+				} else {
+					nodes = append(nodes, network.Get(tag).OutboundEdges...)
+				}
+				for len(nodes) > 0 {
+					node := nodes[0]
+					nodes = nodes[1:]
+					if seen[node] {
+						continue
+					}
+					seen[node] = true
+					fmt.Printf("%s\n", node.Name)
+					if parents {
+						nodes = append(nodes, node.InboundEdges...)
+					} else {
+						nodes = append(nodes, node.OutboundEdges...)
+					}
+				}
+			}
+		}
+	}
+
+	return nil
+}

+ 37 - 0
bashbrew/go/src/bashbrew/cmd-from.go

@@ -0,0 +1,37 @@
+package main
+
+import (
+	"fmt"
+
+	"github.com/codegangsta/cli"
+)
+
+func cmdFrom(c *cli.Context) error {
+	repos, err := repos(c.Bool("all"), c.Args()...)
+	if err != nil {
+		return cli.NewMultiError(fmt.Errorf(`failed gathering repo list`), err)
+	}
+
+	uniq := c.Bool("uniq")
+	namespace := ""
+
+	for _, repo := range repos {
+		r, err := fetch(repo)
+		if err != nil {
+			return cli.NewMultiError(fmt.Errorf(`failed fetching repo %q`, repo), err)
+		}
+
+		for _, entry := range r.Entries() {
+			from, err := r.DockerFrom(&entry)
+			if err != nil {
+				return cli.NewMultiError(fmt.Errorf(`failed fetching/scraping FROM for %q (tags %q)`, r.RepoName, entry.TagsString()), err)
+			}
+
+			for _, tag := range r.Tags(namespace, uniq, entry) {
+				fmt.Printf("%s: %s\n", tag, from)
+			}
+		}
+	}
+
+	return nil
+}

+ 68 - 0
bashbrew/go/src/bashbrew/cmd-list.go

@@ -0,0 +1,68 @@
+package main
+
+import (
+	"fmt"
+
+	"github.com/codegangsta/cli"
+	"github.com/docker-library/go-dockerlibrary/manifest"
+)
+
+func cmdList(c *cli.Context) error {
+	repos, err := repos(c.Bool("all"), c.Args()...)
+	if err != nil {
+		return cli.NewMultiError(fmt.Errorf(`failed gathering repo list`), err)
+	}
+
+	buildOrder := c.Bool("build-order")
+	if buildOrder {
+		repos, err = sortRepos(repos)
+		if err != nil {
+			return cli.NewMultiError(fmt.Errorf(`failed sorting repo list`), err)
+		}
+	}
+
+	uniq := c.Bool("uniq")
+	namespace := ""
+	applyConstraints := c.Bool("apply-constraints")
+	onlyRepos := c.Bool("repos")
+
+	for _, repo := range repos {
+		r, err := fetch(repo)
+		if err != nil {
+			return cli.NewMultiError(fmt.Errorf(`failed fetching repo %q`, repo), err)
+		}
+
+		if onlyRepos {
+			if r.TagEntry == nil {
+				fmt.Printf("%s\n", r.RepoName)
+			} else {
+				for _, tag := range r.Tags(namespace, uniq, *r.TagEntry) {
+					fmt.Printf("%s\n", tag)
+				}
+			}
+			continue
+		}
+
+		var entries []manifest.Manifest2822Entry
+		if buildOrder {
+			entries, err = r.SortedEntries()
+			if err != nil {
+				return cli.NewMultiError(fmt.Errorf(`failed sorting entries list for %q`, repo), err)
+			}
+		} else {
+			entries = r.Entries()
+		}
+
+		for _, entry := range entries {
+			if applyConstraints && r.SkipConstraints(entry) {
+				continue
+			}
+
+			for _, tag := range r.Tags(namespace, uniq, entry) {
+				fmt.Printf("%s\n", tag)
+			}
+		}
+	}
+
+	return nil
+}

+ 40 - 0
bashbrew/go/src/bashbrew/cmd-push.go

@@ -0,0 +1,40 @@
+package main
+
+import (
+	"fmt"
+
+	"github.com/codegangsta/cli"
+)
+
+func cmdPush(c *cli.Context) error {
+	repos, err := repos(c.Bool("all"), c.Args()...)
+	if err != nil {
+		return cli.NewMultiError(fmt.Errorf(`failed gathering repo list`), err)
+	}
+
+	uniq := c.Bool("uniq")
+	namespace := c.String("namespace")
+
+	if namespace == "" {
+		return fmt.Errorf(`"--namespace" is a required flag for "tag"`)
+	}
+
+	for _, repo := range repos {
+		r, err := fetch(repo)
+		if err != nil {
+			return cli.NewMultiError(fmt.Errorf(`failed fetching repo %q`, repo), err)
+		}
+
+		for _, entry := range r.Entries() {
+			for _, tag := range r.Tags(namespace, uniq, entry) {
+				fmt.Printf("Pushing %s\n", tag)
+				err = dockerPush(tag)
+				if err != nil {
+					return cli.NewMultiError(fmt.Errorf(`failed pushing %q`, tag), err)
+				}
+			}
+		}
+	}
+
+	return nil
+}

+ 42 - 0
bashbrew/go/src/bashbrew/cmd-tag.go

@@ -0,0 +1,42 @@
+package main
+
+import (
+	"fmt"
+	"path"
+
+	"github.com/codegangsta/cli"
+)
+
+func cmdTag(c *cli.Context) error {
+	repos, err := repos(c.Bool("all"), c.Args()...)
+	if err != nil {
+		return cli.NewMultiError(fmt.Errorf(`failed gathering repo list`), err)
+	}
+
+	uniq := c.Bool("uniq")
+	namespace := c.String("namespace")
+
+	if namespace == "" {
+		return fmt.Errorf(`"--namespace" is a required flag for "tag"`)
+	}
+
+	for _, repo := range repos {
+		r, err := fetch(repo)
+		if err != nil {
+			return cli.NewMultiError(fmt.Errorf(`failed fetching repo %q`, repo), err)
+		}
+
+		for _, entry := range r.Entries() {
+			for _, tag := range r.Tags("", uniq, entry) {
+				namespacedTag := path.Join(namespace, tag)
+				fmt.Printf("Tagging %s\n", namespacedTag)
+				err = dockerTag(tag, namespacedTag)
+				if err != nil {
+					return cli.NewMultiError(fmt.Errorf(`failed tagging %q as %q`, tag, namespacedTag), err)
+				}
+			}
+		}
+	}
+
+	return nil
+}

+ 205 - 0
bashbrew/go/src/bashbrew/config.go

@@ -0,0 +1,205 @@
+package main
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io"
+	"os"
+
+	"github.com/codegangsta/cli"
+	"github.com/docker-library/go-dockerlibrary/pkg/stripper"
+	"pault.ag/go/debian/control"
+)
+
+type FlagsConfigEntry struct {
+	control.Paragraph
+
+	Commands []string `delim:"," strip:"\n\r\t "`
+
+	Library    string
+	Cache      string
+	Debug      string
+	Unique     string
+	Namespace  string
+	BuildOrder string
+
+	Constraints          []string `delim:"," strip:"\n\r\t "`
+	ExclusiveConstraints string
+	ApplyConstraints     string
+}
+
+type FlagsConfig map[string]FlagsConfigEntry
+
+func (dst *FlagsConfigEntry) Apply(src FlagsConfigEntry) {
+	if src.Library != "" {
+		dst.Library = src.Library
+	}
+	if src.Cache != "" {
+		dst.Cache = src.Cache
+	}
+	if src.Debug != "" {
+		dst.Debug = src.Debug
+	}
+	if src.Unique != "" {
+		dst.Unique = src.Unique
+	}
+	if src.Namespace != "" {
+		dst.Namespace = src.Namespace
+	}
+	if len(src.Constraints) > 0 {
+		dst.Constraints = src.Constraints[:]
+	}
+	if src.ExclusiveConstraints != "" {
+		dst.ExclusiveConstraints = src.ExclusiveConstraints
+	}
+	if src.ApplyConstraints != "" {
+		dst.ApplyConstraints = src.ApplyConstraints
+	}
+}
+
+func (config FlagsConfigEntry) Vars() map[string]map[string]interface{} {
+	return map[string]map[string]interface{}{
+		"global": {
+			"library": config.Library,
+			"cache":   config.Cache,
+			"debug":   config.Debug,
+
+			"constraint":            config.Constraints,
+			"exclusive-constraints": config.ExclusiveConstraints,
+		},
+
+		"local": {
+			"uniq":        config.Unique,
+			"namespace":   config.Namespace,
+			"build-order": config.BuildOrder,
+
+			"apply-constraints": config.ApplyConstraints,
+		},
+	}
+}
+
+func (config FlagsConfig) ApplyTo(cmd string, c *cli.Context) error {
+	entry := config[""]
+	if cmd != "" {
+		entry.Apply(config[cmd])
+	}
+	vars := entry.Vars()
+	if cmd == "" {
+		vars["local"] = vars["global"]
+		vars["global"] = nil
+	}
+	for key, val := range vars["global"] {
+		if !c.GlobalIsSet(key) {
+			switch val.(type) {
+			case string:
+				strVal := val.(string)
+				if strVal == "" {
+					continue
+				}
+				c.GlobalSet(key, strVal)
+			case []string:
+				strSlice := val.([]string)
+				if len(strSlice) == 0 {
+					continue
+				}
+				for _, valBit := range strSlice {
+					c.GlobalSet(key, valBit)
+				}
+			default:
+				return fmt.Errorf(`unknown value type %T (%s: %+v)`, val, key, val)
+			}
+		}
+	}
+	for key, val := range vars["local"] {
+		if !c.IsSet(key) {
+			switch val.(type) {
+			case string:
+				strVal := val.(string)
+				if strVal == "" {
+					continue
+				}
+				c.Set(key, strVal)
+			case []string:
+				strSlice := val.([]string)
+				if len(strSlice) == 0 {
+					continue
+				}
+				for _, valBit := range strSlice {
+					c.Set(key, valBit)
+				}
+			default:
+				return fmt.Errorf(`unknown value type %T (%s: %+v)`, val, key, val)
+			}
+		}
+	}
+	return nil
+}
+
+func (ce FlagsConfigEntry) String() string {
+	buf := &bytes.Buffer{}
+	e, err := control.NewEncoder(buf)
+	if err == nil {
+		err = e.Encode(&ce)
+		if err == nil {
+			return buf.String()
+		}
+	}
+	return ""
+}
+
+func NewFlagsConfig() *FlagsConfig {
+	return &FlagsConfig{}
+}
+
+func ParseFlagsConfigFile(file string) (*FlagsConfig, error) {
+	config := NewFlagsConfig()
+	return config, config.ParseFile(file)
+}
+
+func ParseFlagsConfig(in io.Reader) (*FlagsConfig, error) {
+	config := NewFlagsConfig()
+	return config, config.Parse(in)
+}
+
+func (c *FlagsConfig) ParseFile(file string) error {
+	f, err := os.Open(file)
+	if err != nil {
+		return err
+	}
+	defer f.Close()
+	return c.Parse(f)
+}
+
+func (c *FlagsConfig) Parse(readerIn io.Reader) error {
+	reader := stripper.NewCommentStripper(readerIn)
+
+	decoder, err := control.NewDecoder(bufio.NewReader(reader), nil)
+	if err != nil {
+		return err
+	}
+
+	for {
+		entry := FlagsConfigEntry{}
+
+		err := decoder.Decode(&entry)
+		if err == io.EOF {
+			break
+		}
+		if err != nil {
+			return err
+		}
+
+		if len(entry.Commands) == 0 {
+			entry.Commands = []string{""}
+		}
+
+		for _, command := range entry.Commands {
+			targetEntry := (*c)[command]
+			targetEntry.Apply(entry)
+			(*c)[command] = targetEntry
+		}
+	}
+
+	return nil
+}

+ 187 - 0
bashbrew/go/src/bashbrew/docker.go

@@ -0,0 +1,187 @@
+package main
+
+import (
+	"bufio"
+	"bytes"
+	"crypto/sha256"
+	"encoding/hex"
+	"fmt"
+	"io"
+	"os"
+	"os/exec"
+	"path"
+	"strings"
+
+	"github.com/codegangsta/cli"
+	"github.com/docker-library/go-dockerlibrary/manifest"
+)
+
+var dockerFromCache = map[string]string{}
+
+func (r Repo) DockerFrom(entry *manifest.Manifest2822Entry) (string, error) {
+	commit, err := r.fetchGitRepo(entry)
+	if err != nil {
+		return "", err
+	}
+
+	dockerfileFile := path.Join(entry.Directory, "Dockerfile")
+
+	cacheKey := strings.Join([]string{
+		commit,
+		dockerfileFile,
+	}, "\n")
+	if from, ok := dockerFromCache[cacheKey]; ok {
+		return from, nil
+	}
+
+	dockerfile, err := gitShow(commit, dockerfileFile)
+	defer dockerfile.Close()
+	if err != nil {
+		return "", err
+	}
+
+	from, err := dockerfileFrom(dockerfile)
+	if err != nil {
+		return "", err
+	}
+
+	// make sure to add ":latest" if it's implied
+	from = latestizeRepoTag(from)
+
+	dockerFromCache[cacheKey] = from
+	return from, nil
+}
+
+func dockerfileFrom(dockerfile io.Reader) (string, error) {
+	scanner := bufio.NewScanner(dockerfile)
+	for scanner.Scan() {
+		line := strings.TrimSpace(scanner.Text())
+		if line == "" {
+			// ignore blank lines
+			continue
+		}
+		if line[0] == '#' {
+			// ignore comments
+			continue
+		}
+		fields := strings.Fields(line)
+		if len(fields) < 1 {
+			continue
+		}
+		if strings.ToUpper(fields[0]) == "FROM" {
+			return fields[1], nil
+		}
+	}
+	if err := scanner.Err(); err != nil {
+		return "", err
+	}
+	return "", nil
+}
+
+func (r Repo) dockerCacheHash(entry *manifest.Manifest2822Entry) (string, error) {
+	uniqueBits, err := r.dockerBuildUniqueBits(entry)
+	if err != nil {
+		return "", err
+	}
+	uniqueString := strings.Join(uniqueBits, "\n")
+	b := sha256.Sum256([]byte(uniqueString))
+	return hex.EncodeToString(b[:]), nil
+}
+
+func dockerInspect(format string, args ...string) (string, error) {
+	args = append([]string{"inspect", "-f", format}, args...)
+	out, err := exec.Command("docker", args...).Output()
+	if err != nil {
+		if ee, ok := err.(*exec.ExitError); ok {
+			return "", fmt.Errorf("%v\ncommand: docker inspect -f %q %q\n%s", ee, format, args, string(ee.Stderr))
+		}
+	}
+	return string(out), nil
+}
+
+var dockerFromIdCache = map[string]string{
+	"scratch": "scratch",
+}
+
+func (r Repo) dockerBuildUniqueBits(entry *manifest.Manifest2822Entry) ([]string, error) {
+	from, err := r.DockerFrom(entry)
+	if err != nil {
+		return nil, err
+	}
+	fromId, ok := dockerFromIdCache[from]
+	if !ok {
+		var err error
+		fromId, err = dockerInspect("{{.Id}}", from)
+		if err != nil {
+			return nil, err
+		}
+		dockerFromIdCache[from] = fromId
+	}
+	return []string{
+		entry.GitRepo,
+		entry.GitCommit,
+		entry.Directory,
+		fromId,
+	}, nil
+}
+
+func dockerBuild(tag string, context io.Reader) error {
+	args := []string{"build", "-t", tag, "--rm", "--force-rm"}
+	args = append(args, "-")
+	cmd := exec.Command("docker", args...)
+	cmd.Stdin = context
+	if debugFlag {
+		cmd.Stdout = os.Stdout
+		cmd.Stderr = os.Stderr
+		fmt.Printf("$ docker %q\n", args)
+		return cmd.Run()
+	} else {
+		buf := &bytes.Buffer{}
+		cmd.Stdout = buf
+		cmd.Stderr = buf
+		err := cmd.Run()
+		if err != nil {
+			err = cli.NewMultiError(err, fmt.Errorf(`docker build %q output:%s`, args, "\n"+buf.String()))
+		}
+		return err
+	}
+}
+
+func dockerTag(tag1 string, tag2 string) error {
+	if debugFlag {
+		fmt.Printf("$ docker tag %q %q\n", tag1, tag2)
+	}
+	_, err := exec.Command("docker", "tag", "-f", tag1, tag2).Output()
+	if err != nil {
+		if ee, ok := err.(*exec.ExitError); ok {
+			return fmt.Errorf("%v\ncommand: docker tag -f %q %q\n%s", ee, tag1, tag2, string(ee.Stderr))
+		}
+	}
+	return err
+}
+
+func dockerPush(tag string) error {
+	if debugFlag {
+		fmt.Printf("$ docker push %q\n", tag)
+	}
+	_, err := exec.Command("docker", "push", tag).Output()
+	if err != nil {
+		if ee, ok := err.(*exec.ExitError); ok {
+			return fmt.Errorf("%v\ncommand: docker push %q\n%s", ee, tag, string(ee.Stderr))
+		}
+	}
+	return err
+}
+
+func dockerPull(tag string) error {
+	if debugFlag {
+		fmt.Printf("$ docker pull %q\n", tag)
+	}
+	_, err := exec.Command("docker", "pull", tag).Output()
+	if err != nil {
+		if ee, ok := err.(*exec.ExitError); ok {
+			return fmt.Errorf("%v\ncommand: docker pull %q\n%s", ee, tag, string(ee.Stderr))
+		}
+	}
+	return err
+}

+ 146 - 0
bashbrew/go/src/bashbrew/git.go

@@ -0,0 +1,146 @@
+package main
+
+import (
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path"
+	"path/filepath"
+	"strings"
+
+	"github.com/docker-library/go-dockerlibrary/manifest"
+)
+
+func gitCache() string {
+	return filepath.Join(defaultCache, "git")
+}
+
+func gitCommand(args ...string) *exec.Cmd {
+	cmd := exec.Command("git", args...)
+	cmd.Dir = gitCache()
+	return cmd
+}
+
+func git(args ...string) ([]byte, error) {
+	out, err := gitCommand(args...).Output()
+	if err != nil {
+		if ee, ok := err.(*exec.ExitError); ok {
+			return nil, fmt.Errorf("%v\ncommand: git %q\n%s", ee, args, string(ee.Stderr))
+		}
+	}
+	return out, err
+}
+
+func ensureGitInit() error {
+	err := os.MkdirAll(gitCache(), os.ModePerm)
+	if err != nil {
+		return err
+	}
+	git("init", "--quiet", "--bare", ".") // ignore errors -- just make sure the repo exists
+	git("config", "gc.auto", "0")         // ensure garbage collection is disabled so we keep dangling commits
+	return nil
+}
+
+func getGitCommit(commit string) (string, error) {
+	out, err := git("rev-parse", commit+"^{commit}")
+	if err != nil {
+		return "", err
+	}
+	return strings.TrimSpace(string(out)), nil
+}
+
+func gitStream(args ...string) (io.ReadCloser, error) {
+	cmd := gitCommand(args...)
+	out, err := cmd.StdoutPipe()
+	if err != nil {
+		return nil, err
+	}
+	if err := cmd.Start(); err != nil {
+		out.Close()
+		return nil, err
+	}
+	go cmd.Wait() // make sure we get cleaned up, eventually
+	return out, nil
+}
+
+func gitArchive(commit string, dir string) (io.ReadCloser, error) {
+	dir = path.Clean(dir)
+	if dir == "." {
+		dir = ""
+	} else {
+		dir += "/"
+	}
+	return gitStream("archive", "--format=tar", commit+":"+dir)
+}
+
+func gitShow(commit string, file string) (io.ReadCloser, error) {
+	return gitStream("show", commit+":"+path.Clean(file))
+}
+
+var gitRepoCache = map[string]string{}
+
+func (r Repo) fetchGitRepo(entry *manifest.Manifest2822Entry) (string, error) {
+	cacheKey := strings.Join([]string{
+		entry.GitRepo,
+		entry.GitFetch,
+		entry.GitCommit,
+	}, "\n")
+	if commit, ok := gitRepoCache[cacheKey]; ok {
+		entry.GitCommit = commit
+		return commit, nil
+	}
+
+	err := ensureGitInit()
+	if err != nil {
+		return "", err
+	}
+
+	if manifest.GitCommitRegex.MatchString(entry.GitCommit) {
+		commit, err := getGitCommit(entry.GitCommit)
+		if err == nil {
+			gitRepoCache[cacheKey] = commit
+			entry.GitCommit = commit
+			return commit, nil
+		}
+	}
+
+	fetchString := entry.GitFetch + ":"
+	if entry.GitFetch == manifest.DefaultLineBasedFetch {
+		// backwards compat (see manifest/line-based.go in go-dockerlibrary)
+		refBase := "refs/remotes"
+		refBaseDir := filepath.Join(gitCache(), refBase)
+		err := os.MkdirAll(refBaseDir, os.ModePerm)
+		if err != nil {
+			return "", err
+		}
+		tempRefDir, err := ioutil.TempDir(refBaseDir, "temp")
+		if err != nil {
+			return "", err
+		}
+		defer os.RemoveAll(tempRefDir)
+		tempRef := path.Join(refBase, filepath.Base(tempRefDir))
+		fetchString += tempRef + "/*"
+		// we create a temporary remote dir so that we can clean it up completely afterwards
+	}
+
+	_, err = git("fetch", "--quiet", "--no-tags", entry.GitRepo, fetchString)
+	if err != nil {
+		return "", err
+	}
+
+	commit, err := getGitCommit(entry.GitCommit)
+	if err != nil {
+		return "", err
+	}
+
+	_, err = git("tag", "--force", r.RepoName+"/"+entry.Tags[0], commit)
+	if err != nil {
+		return "", err
+	}
+
+	gitRepoCache[cacheKey] = commit
+	entry.GitCommit = commit
+	return commit, nil
+}

+ 370 - 0
bashbrew/go/src/bashbrew/main.go

@@ -0,0 +1,370 @@
+package main
+
+import (
+	"fmt"
+	"os"
+	"path/filepath"
+	"sort"
+	"strings"
+
+	"github.com/codegangsta/cli"
+	"pault.ag/go/topsort"
+)
+
+var (
+	configPath  string
+	flagsConfig *FlagsConfig
+
+	defaultLibrary string
+	defaultCache   string
+
+	constraints          []string
+	exclusiveConstraints bool
+
+	debugFlag  = false
+	noSortFlag = false
+)
+
+func initDefaultConfigPath() string {
+	xdgConfig := os.Getenv("XDG_CONFIG_HOME")
+	if xdgConfig == "" {
+		xdgConfig = filepath.Join(os.Getenv("HOME"), ".config")
+	}
+	return filepath.Join(xdgConfig, "bashbrew")
+}
+
+func initDefaultCachePath() string {
+	xdgCache := os.Getenv("XDG_CACHE_HOME")
+	if xdgCache == "" {
+		xdgCache = filepath.Join(os.Getenv("HOME"), ".cache")
+	}
+	return filepath.Join(xdgCache, "bashbrew")
+}
+
+func repos(all bool, args ...string) ([]string, error) {
+	ret := []string{}
+
+	if all {
+		dir, err := os.Open(defaultLibrary)
+		if err != nil {
+			return nil, err
+		}
+		names, err := dir.Readdirnames(-1)
+		dir.Close()
+		if err != nil {
+			return nil, err
+		}
+		sort.Strings(names)
+		for _, name := range names {
+			ret = append(ret, filepath.Join(defaultLibrary, name))
+		}
+	}
+
+	ret = append(ret, args...)
+
+	if len(ret) < 1 {
+		return nil, fmt.Errorf(`need at least one repo (either explicitly or via "--all")`)
+	}
+
+	return ret, nil
+}
+
+func sortRepos(repos []string) ([]string, error) {
+	if noSortFlag || len(repos) <= 1 {
+		return repos, nil
+	}
+
+	network := topsort.NewNetwork()
+
+	rs := []*Repo{}
+	for _, repo := range repos {
+		r, err := fetch(repo)
+		if err != nil {
+			return nil, err
+		}
+		rs = append(rs, r)
+		network.AddNode(r.Identifier(), repo)
+		network.AddNode(r.RepoName, repo)
+	}
+
+	for _, r := range rs {
+		for _, entry := range r.Entries() {
+			from, err := r.DockerFrom(&entry)
+			if err != nil {
+				return nil, err
+			}
+			if i := strings.IndexRune(from, ':'); i >= 0 {
+				// we want "repo -> repo" relations, no tags
+				from = from[:i]
+			}
+			if from == r.RepoName {
+				// "a:a -> a:b" is OK (ignore that here -- see Repo.SortedEntries for that)
+				continue
+			}
+			// TODO somehow reconcile/avoid "a:a -> b:b, b:b -> a:c" (which will exhibit here as cyclic)
+			network.AddEdgeIfExists(from, r.Identifier())
+			network.AddEdgeIfExists(from, r.RepoName)
+		}
+	}
+
+	nodes, err := network.Sort()
+	if err != nil {
+		return nil, err
+	}
+
+	ret := []string{}
+	seen := map[string]bool{}
+	for _, node := range nodes {
+		repo := node.Value.(string)
+		if seen[repo] {
+			continue
+		}
+		seen[repo] = true
+		ret = append(ret, repo)
+	}
+
+	return ret, nil
+}
+
+func main() {
+	app := cli.NewApp()
+	app.Name = "bashbrew"
+	app.Usage = "canonical build tool for the official images"
+	app.Version = "dev"
+	app.HideVersion = true
+	app.EnableBashCompletion = true
+
+	// TODO add "Description" to app and commands (for longer-form description of their functionality)
+
+	cli.VersionFlag.Name = "version" // remove "-v" from VersionFlag
+	cli.HelpFlag.Name = "help, h, ?" // add "-?" to HelpFlag
+	app.Flags = []cli.Flag{
+		cli.BoolFlag{
+			Name:   "debug",
+			EnvVar: "BASHBREW_DEBUG",
+			Usage:  `enable more output (esp. all "docker build" output instead of only output on failure)`,
+		},
+		cli.BoolFlag{
+			Name:  "no-sort",
+			Usage: "do not apply any sorting, even via --build-order",
+		},
+
+		cli.StringSliceFlag{
+			Name:  "constraint",
+			Usage: "build constraints (see Constraints in Manifest2822Entry)",
+		},
+		cli.BoolFlag{
+			Name:  "exclusive-constraints",
+			Usage: "skip entries which do not have Constraints",
+		},
+
+		cli.StringFlag{
+			Name:   "config",
+			Value:  initDefaultConfigPath(),
+			EnvVar: "BASHBREW_CONFIG",
+			Usage:  `where default "flags" configuration can be overridden more persistently`,
+		},
+		cli.StringFlag{
+			Name:   "library",
+			Value:  filepath.Join(os.Getenv("HOME"), "docker", "official-images", "library"),
+			EnvVar: "BASHBREW_LIBRARY",
+			Usage:  "where the bodies are buried",
+		},
+		cli.StringFlag{
+			Name:   "cache",
+			Value:  initDefaultCachePath(),
+			EnvVar: "BASHBREW_CACHE",
+			Usage:  "where the git wizardry is stashed",
+		},
+	}
+
+	app.Before = func(c *cli.Context) error {
+		var err error
+
+		configPath, err = filepath.Abs(c.String("config"))
+		if err != nil {
+			return err
+		}
+
+		flagsConfig, err = ParseFlagsConfigFile(filepath.Join(configPath, "flags"))
+		if err != nil && !os.IsNotExist(err) {
+			return err
+		}
+
+		return nil
+	}
+
+	subcommandBeforeFactory := func(cmd string) cli.BeforeFunc {
+		return func(c *cli.Context) error {
+			err := flagsConfig.ApplyTo(cmd, c)
+			if err != nil {
+				return err
+			}
+
+			debugFlag = c.GlobalBool("debug")
+			noSortFlag = c.GlobalBool("no-sort")
+
+			constraints = c.GlobalStringSlice("constraint")
+			exclusiveConstraints = c.GlobalBool("exclusive-constraints")
+
+			defaultLibrary, err = filepath.Abs(c.GlobalString("library"))
+			if err != nil {
+				return err
+			}
+			defaultCache, err = filepath.Abs(c.GlobalString("cache"))
+			if err != nil {
+				return err
+			}
+
+			return nil
+		}
+	}
+
+	// define a few useful flags so their usage, etc can be consistent
+	commonFlags := map[string]cli.Flag{
+		"all": cli.BoolFlag{
+			Name:  "all",
+			Usage: "act upon all repos listed in --library",
+		},
+		"uniq": cli.BoolFlag{
+			Name:  "uniq, unique",
+			Usage: "only act upon the first tag of each entry",
+		},
+		"namespace": cli.StringFlag{
+			Name:  "namespace",
+			Usage: "a repo namespace to act upon/in",
+		},
+	}
+
+	app.Commands = []cli.Command{
+		{
+			Name:    "list",
+			Aliases: []string{"ls"},
+			Usage:   "list repo:tag combinations for a given repo",
+			Flags: []cli.Flag{
+				commonFlags["all"],
+				commonFlags["uniq"],
+				cli.BoolFlag{
+					Name:  "build-order",
+					Usage: "sort by the order repos would need to build (topsort)",
+				},
+				cli.BoolFlag{
+					Name:  "apply-constraints",
+					Usage: "apply Constraints as if repos were building",
+				},
+				cli.BoolFlag{
+					Name:  "repos",
+					Usage: `list only repos, not repo:tag (unless "repo:tag" is explicitly specified)`,
+				},
+			},
+			Before: subcommandBeforeFactory("list"),
+			Action: cmdList,
+		},
+		{
+			Name:  "build",
+			Usage: "build (and tag) repo:tag combinations for a given repo",
+			Flags: []cli.Flag{
+				commonFlags["all"],
+				commonFlags["uniq"],
+				commonFlags["namespace"],
+				cli.BoolFlag{
+					// TODO consider switching this to be a StringFlag with values of "always", "missing", "never" (default never)
+					Name:  "pull-missing",
+					Usage: "pull missing FROM tags while building",
+				},
+			},
+			Before: subcommandBeforeFactory("build"),
+			Action: cmdBuild,
+		},
+		{
+			Name:  "tag",
+			Usage: "tag repo:tag into a namespace (especially for pushing)",
+			Flags: []cli.Flag{
+				commonFlags["all"],
+				commonFlags["uniq"],
+				commonFlags["namespace"],
+			},
+			Before: subcommandBeforeFactory("tag"),
+			Action: cmdTag,
+		},
+		{
+			Name:  "push",
+			Usage: `push namespace/repo:tag (see also "tag")`,
+			Flags: []cli.Flag{
+				commonFlags["all"],
+				commonFlags["uniq"],
+				commonFlags["namespace"],
+			},
+			Before: subcommandBeforeFactory("push"),
+			Action: cmdPush,
+		},
+
+		{
+			Name: "children",
+			Aliases: []string{
+				"offspring",
+				"descendants",
+				"progeny",
+			},
+			Usage:  `print the repos built FROM a given repo or repo:tag`,
+			Flags:  []cli.Flag{},
+			Before: subcommandBeforeFactory("children"),
+			Action: cmdOffspring,
+
+			Category: "plumbing",
+		},
+		{
+			Name: "parents",
+			Aliases: []string{
+				"ancestors",
+				"progenitors",
+			},
+			Usage:  `print the repos this repo or repo:tag is FROM`,
+			Flags:  []cli.Flag{},
+			Before: subcommandBeforeFactory("parents"),
+			Action: cmdParents,
+
+			Category: "plumbing",
+		},
+		{
+			Name:  "cat",
+			Usage: "print manifest contents for repo or repo:tag",
+			Flags: []cli.Flag{
+				commonFlags["all"],
+				cli.StringFlag{
+					Name:  "format, f",
+					Usage: "change the `FORMAT` of the output",
+					Value: DefaultCatFormat,
+				},
+				cli.StringFlag{
+					Name:  "format-file, F",
+					Usage: "use the contents of `FILE` for \"--format\"",
+				},
+			},
+			Before: subcommandBeforeFactory("cat"),
+			Action: cmdCat,
+
+			Description: `see Go's "text/template" package (https://golang.org/pkg/text/template/) for details on the syntax expected in "--format"`,
+
+			Category: "plumbing",
+		},
+		{
+			Name:  "from",
+			Usage: "print FROM for repo:tag",
+			Flags: []cli.Flag{
+				commonFlags["all"],
+				commonFlags["uniq"],
+			},
+			Before: subcommandBeforeFactory("from"),
+			Action: cmdFrom,
+
+			Category: "plumbing",
+		},
+	}
+
+	err := app.Run(os.Args)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "error: %v\n", err)
+		os.Exit(1)
+	}
+}

+ 151 - 0
bashbrew/go/src/bashbrew/repo.go

@@ -0,0 +1,151 @@
+package main
+
+import (
+	"fmt"
+	"os"
+	"path"
+	"strings"
+
+	"github.com/docker-library/go-dockerlibrary/manifest"
+	"pault.ag/go/topsort"
+)
+
+func latestizeRepoTag(repoTag string) string {
+	if repoTag != "scratch" && strings.IndexRune(repoTag, ':') < 0 {
+		return repoTag + ":latest"
+	}
+	return repoTag
+}
+
+type Repo struct {
+	RepoName string
+	TagName  string
+	Manifest *manifest.Manifest2822
+	TagEntry *manifest.Manifest2822Entry
+}
+
+func (r Repo) Identifier() string {
+	if r.TagName != "" {
+		return r.RepoName + ":" + r.TagName
+	}
+	return r.RepoName
+}
+
+func (r Repo) SkipConstraints(entry manifest.Manifest2822Entry) bool {
+	repoTag := r.RepoName + ":" + entry.Tags[0]
+
+	if len(entry.Constraints) == 0 {
+		if exclusiveConstraints {
+			fmt.Fprintf(os.Stderr, "skipping %q (due to exclusive constraints)\n", repoTag)
+			return true
+		}
+		return false
+	}
+
+	for _, constraint := range constraints {
+		for _, eConstraint := range entry.Constraints {
+			not := false
+			if eConstraint[0] == '!' {
+				not = true
+				eConstraint = eConstraint[1:]
+			}
+			if constraint == eConstraint {
+				if not {
+					fmt.Fprintf(os.Stderr, "skipping %q (due to constraint %q)\n", repoTag, constraint)
+				}
+				return not
+			}
+		}
+	}
+
+	return true
+}
+
+func (r Repo) Entries() []manifest.Manifest2822Entry {
+	if r.TagName == "" {
+		return r.Manifest.Entries
+	} else {
+		return []manifest.Manifest2822Entry{*r.Manifest.GetTag(r.TagName)}
+	}
+}
+
+func (r Repo) SortedEntries() ([]manifest.Manifest2822Entry, error) {
+	entries := r.Entries()
+
+	if noSortFlag || len(entries) <= 1 {
+		return entries, nil
+	}
+
+	network := topsort.NewNetwork()
+
+	for i, entry := range entries {
+		for _, tag := range r.Tags("", false, entry) {
+			network.AddNode(tag, &entries[i])
+		}
+	}
+
+	for _, entry := range entries {
+		from, err := r.DockerFrom(&entry)
+		if err != nil {
+			return nil, err
+		}
+		for _, tag := range r.Tags("", false, entry) {
+			network.AddEdgeIfExists(from, tag)
+		}
+	}
+
+	nodes, err := network.Sort()
+	if err != nil {
+		return nil, err
+	}
+
+	seen := map[*manifest.Manifest2822Entry]bool{}
+	ret := []manifest.Manifest2822Entry{}
+	for _, node := range nodes {
+		entry := node.Value.(*manifest.Manifest2822Entry)
+		if seen[entry] {
+			// TODO somehow reconcile "a:a -> b:b, b:b -> a:c"
+			continue
+		}
+		ret = append(ret, *entry)
+		seen[entry] = true
+	}
+
+	return ret, nil
+}
+
+func (r Repo) Tags(namespace string, uniq bool, entry manifest.Manifest2822Entry) []string {
+	tagRepo := path.Join(namespace, r.RepoName)
+	ret := []string{}
+	for i, tag := range entry.Tags {
+		if uniq && i > 0 {
+			break
+		}
+		ret = append(ret, tagRepo+":"+tag)
+	}
+	return ret
+}
+
+var repoCache = map[string]*Repo{}
+
+func fetch(repo string) (*Repo, error) {
+	if r, ok := repoCache[repo]; ok {
+		return r, nil
+	}
+
+	repoName, tagName, man, err := manifest.Fetch(defaultLibrary, repo)
+	if err != nil {
+		return nil, err
+	}
+
+	r := &Repo{
+		RepoName: repoName,
+		TagName:  tagName,
+		Manifest: man,
+	}
+	if tagName != "" {
+		r.TagEntry = man.GetTag(tagName)
+	}
+	repoCache[repo] = r
+	return r, nil
+}

+ 141 - 0
bashbrew/go/vendor/manifest

@@ -0,0 +1,141 @@
+{
+	"version": 0,
+	"dependencies": [
+		{
+			"importpath": "github.com/codegangsta/cli",
+			"repository": "https://github.com/codegangsta/cli",
+			"revision": "01857ac33766ce0c93856370626f9799281c14f4",
+			"branch": "HEAD"
+		},
+		{
+			"importpath": "github.com/docker-library/go-dockerlibrary",
+			"repository": "https://github.com/docker-library/go-dockerlibrary",
+			"revision": "e9ae2802d93d05d3e8d58b83ede12701035a4c3f",
+			"branch": "master"
+		},
+		{
+			"importpath": "github.com/docker-library/go-dockerlibrary/manifest",
+			"repository": "https://github.com/docker-library/go-dockerlibrary",
+			"revision": "7d56be63f3f8ff42ef402595615fefc34f5bc393",
+			"branch": "master",
+			"path": "/manifest"
+		},
+		{
+			"importpath": "github.com/docker-library/go-dockerlibrary/pkg/stripper",
+			"repository": "https://github.com/docker-library/go-dockerlibrary",
+			"revision": "ea2a7991ce3e7e1ba50a635040fa0ee6bb967aeb",
+			"branch": "master",
+			"path": "/pkg/stripper"
+		},
+		{
+			"importpath": "github.com/docker-library/go-dockerlibrary/pkg/templatelib",
+			"repository": "https://github.com/docker-library/go-dockerlibrary",
+			"revision": "939e8fc63d2d9960bbe2450c7fbf007fbabfe3b6",
+			"branch": "master",
+			"path": "/pkg/templatelib"
+		},
+		{
+			"importpath": "golang.org/x/crypto/cast5",
+			"repository": "https://go.googlesource.com/crypto",
+			"revision": "5bcd134fee4dd1475da17714aac19c0aa0142e2f",
+			"branch": "master",
+			"path": "/cast5"
+		},
+		{
+			"importpath": "golang.org/x/crypto/openpgp",
+			"repository": "https://go.googlesource.com/crypto",
+			"revision": "5bcd134fee4dd1475da17714aac19c0aa0142e2f",
+			"branch": "master",
+			"path": "/openpgp"
+		},
+		{
+			"importpath": "golang.org/x/crypto/openpgp/armor",
+			"repository": "https://go.googlesource.com/crypto",
+			"revision": "5bcd134fee4dd1475da17714aac19c0aa0142e2f",
+			"branch": "master",
+			"path": "/openpgp/armor"
+		},
+		{
+			"importpath": "golang.org/x/crypto/openpgp/clearsign",
+			"repository": "https://go.googlesource.com/crypto",
+			"revision": "5bcd134fee4dd1475da17714aac19c0aa0142e2f",
+			"branch": "master",
+			"path": "/openpgp/clearsign"
+		},
+		{
+			"importpath": "golang.org/x/crypto/openpgp/elgamal",
+			"repository": "https://go.googlesource.com/crypto",
+			"revision": "5bcd134fee4dd1475da17714aac19c0aa0142e2f",
+			"branch": "master",
+			"path": "/openpgp/elgamal"
+		},
+		{
+			"importpath": "golang.org/x/crypto/openpgp/errors",
+			"repository": "https://go.googlesource.com/crypto",
+			"revision": "5bcd134fee4dd1475da17714aac19c0aa0142e2f",
+			"branch": "master",
+			"path": "/openpgp/errors"
+		},
+		{
+			"importpath": "golang.org/x/crypto/openpgp/packet",
+			"repository": "https://go.googlesource.com/crypto",
+			"revision": "5bcd134fee4dd1475da17714aac19c0aa0142e2f",
+			"branch": "master",
+			"path": "/openpgp/packet"
+		},
+		{
+			"importpath": "golang.org/x/crypto/openpgp/s2k",
+			"repository": "https://go.googlesource.com/crypto",
+			"revision": "5bcd134fee4dd1475da17714aac19c0aa0142e2f",
+			"branch": "master",
+			"path": "/openpgp/s2k"
+		},
+		{
+			"importpath": "gopkg.in/yaml.v2",
+			"repository": "https://gopkg.in/yaml.v2",
+			"revision": "a83829b6f1293c91addabc89d0571c246397bbf4",
+			"branch": "v2"
+		},
+		{
+			"importpath": "pault.ag/go/debian/control",
+			"repository": "https://github.com/paultag/go-debian",
+			"revision": "e7a23c7df0f545cdb75afbcc6d296bb93ce2786f",
+			"branch": "master",
+			"path": "/control"
+		},
+		{
+			"importpath": "pault.ag/go/debian/dependency",
+			"repository": "https://github.com/paultag/go-debian",
+			"revision": "e7a23c7df0f545cdb75afbcc6d296bb93ce2786f",
+			"branch": "master",
+			"path": "/dependency"
+		},
+		{
+			"importpath": "pault.ag/go/debian/internal",
+			"repository": "https://github.com/paultag/go-debian",
+			"revision": "e7a23c7df0f545cdb75afbcc6d296bb93ce2786f",
+			"branch": "master",
+			"path": "/internal"
+		},
+		{
+			"importpath": "pault.ag/go/debian/transput",
+			"repository": "https://github.com/paultag/go-debian",
+			"revision": "e7a23c7df0f545cdb75afbcc6d296bb93ce2786f",
+			"branch": "master",
+			"path": "/transput"
+		},
+		{
+			"importpath": "pault.ag/go/debian/version",
+			"repository": "https://github.com/paultag/go-debian",
+			"revision": "e7a23c7df0f545cdb75afbcc6d296bb93ce2786f",
+			"branch": "master",
+			"path": "/version"
+		},
+		{
+			"importpath": "pault.ag/go/topsort",
+			"repository": "https://github.com/paultag/go-topsort",
+			"revision": "f98d2ad46e1adcbf8fa59a95a3b5509a7da9c6b5",
+			"branch": "master"
+		}
+	]
+}

+ 310 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/CHANGELOG.md

@@ -0,0 +1,310 @@
+# Change Log
+
+**ATTN**: This project uses [semantic versioning](http://semver.org/).
+
+## [Unreleased]
+
+## [1.17.0] - 2016-05-09
+### Added
+- Pluggable flag-level help text rendering via `cli.DefaultFlagStringFunc`
+- `context.GlobalBoolT` was added as an analogue to `context.GlobalBool`
+- Support for hiding commands by setting `Hidden: true` -- this will hide the
+  commands in help output
+
+### Changed
+- `Float64Flag`, `IntFlag`, and `DurationFlag` default values are no longer
+  quoted in help text output.
+- All flag types now include `(default: {value})` strings following usage when a
+  default value can be (reasonably) detected.
+- `IntSliceFlag` and `StringSliceFlag` usage strings are now more consistent
+  with non-slice flag types
+- Apps now exit with a code of 3 if an unknown subcommand is specified
+  (previously they printed "No help topic for...", but still exited 0. This
+  makes it easier to script around apps built using `cli` since they can trust
+  that a 0 exit code indicated a successful execution.
+- cleanups based on [Go Report Card
+  feedback](https://goreportcard.com/report/github.com/codegangsta/cli)
+
+## [1.16.0] - 2016-05-02
+### Added
+- `Hidden` field on all flag struct types to omit from generated help text
+
+### Changed
+- `BashCompletionFlag` (`--enable-bash-completion`) is now omitted from
+generated help text via the `Hidden` field
+
+### Fixed
+- handling of error values in `HandleAction` and `HandleExitCoder`
+
+## [1.15.0] - 2016-04-30
+### Added
+- This file!
+- Support for placeholders in flag usage strings
+- `App.Metadata` map for arbitrary data/state management
+- `Set` and `GlobalSet` methods on `*cli.Context` for altering values after
+parsing.
+- Support for nested lookup of dot-delimited keys in structures loaded from
+YAML.
+
+### Changed
+- The `App.Action` and `Command.Action` now prefer a return signature of
+`func(*cli.Context) error`, as defined by `cli.ActionFunc`.  If a non-nil
+`error` is returned, there may be two outcomes:
+    - If the error fulfills `cli.ExitCoder`, then `os.Exit` will be called
+    automatically
+    - Else the error is bubbled up and returned from `App.Run`
+- Specifying an `Action` with the legacy return signature of
+`func(*cli.Context)` will produce a deprecation message to stderr
+- Specifying an `Action` that is not a `func` type will produce a non-zero exit
+from `App.Run`
+- Specifying an `Action` func that has an invalid (input) signature will
+produce a non-zero exit from `App.Run`
+
+### Deprecated
+- <a name="deprecated-cli-app-runandexitonerror"></a>
+`cli.App.RunAndExitOnError`, which should now be done by returning an error
+that fulfills `cli.ExitCoder` to `cli.App.Run`.
+- <a name="deprecated-cli-app-action-signature"></a> the legacy signature for
+`cli.App.Action` of `func(*cli.Context)`, which should now have a return
+signature of `func(*cli.Context) error`, as defined by `cli.ActionFunc`.
+
+### Fixed
+- Added missing `*cli.Context.GlobalFloat64` method
+
+## [1.14.0] - 2016-04-03 (backfilled 2016-04-25)
+### Added
+- Codebeat badge
+- Support for categorization via `CategorizedHelp` and `Categories` on app.
+
+### Changed
+- Use `filepath.Base` instead of `path.Base` in `Name` and `HelpName`.
+
+### Fixed
+- Ensure version is not shown in help text when `HideVersion` set.
+
+## [1.13.0] - 2016-03-06 (backfilled 2016-04-25)
+### Added
+- YAML file input support.
+- `NArg` method on context.
+
+## [1.12.0] - 2016-02-17 (backfilled 2016-04-25)
+### Added
+- Custom usage error handling.
+- Custom text support in `USAGE` section of help output.
+- Improved help messages for empty strings.
+- AppVeyor CI configuration.
+
+### Changed
+- Removed `panic` from default help printer func.
+- De-duping and optimizations.
+
+### Fixed
+- Correctly handle `Before`/`After` at command level when no subcommands.
+- Case of literal `-` argument causing flag reordering.
+- Environment variable hints on Windows.
+- Docs updates.
+
+## [1.11.1] - 2015-12-21 (backfilled 2016-04-25)
+### Changed
+- Use `path.Base` in `Name` and `HelpName`
+- Export `GetName` on flag types.
+
+### Fixed
+- Flag parsing when skipping is enabled.
+- Test output cleanup.
+- Move completion check to account for empty input case.
+
+## [1.11.0] - 2015-11-15 (backfilled 2016-04-25)
+### Added
+- Destination scan support for flags.
+- Testing against `tip` in Travis CI config.
+
+### Changed
+- Go version in Travis CI config.
+
+### Fixed
+- Removed redundant tests.
+- Use correct example naming in tests.
+
+## [1.10.2] - 2015-10-29 (backfilled 2016-04-25)
+### Fixed
+- Remove unused var in bash completion.
+
+## [1.10.1] - 2015-10-21 (backfilled 2016-04-25)
+### Added
+- Coverage and reference logos in README.
+
+### Fixed
+- Use specified values in help and version parsing.
+- Only display app version and help message once.
+
+## [1.10.0] - 2015-10-06 (backfilled 2016-04-25)
+### Added
+- More tests for existing functionality.
+- `ArgsUsage` at app and command level for help text flexibility.
+
+### Fixed
+- Honor `HideHelp` and `HideVersion` in `App.Run`.
+- Remove juvenile word from README.
+
+## [1.9.0] - 2015-09-08 (backfilled 2016-04-25)
+### Added
+- `FullName` on command with accompanying help output update.
+- Set default `$PROG` in bash completion.
+
+### Changed
+- Docs formatting.
+
+### Fixed
+- Removed self-referential imports in tests.
+
+## [1.8.0] - 2015-06-30 (backfilled 2016-04-25)
+### Added
+- Support for `Copyright` at app level.
+- `Parent` func at context level to walk up context lineage.
+
+### Fixed
+- Global flag processing at top level.
+
+## [1.7.1] - 2015-06-11 (backfilled 2016-04-25)
+### Added
+- Aggregate errors from `Before`/`After` funcs.
+- Doc comments on flag structs.
+- Include non-global flags when checking version and help.
+- Travis CI config updates.
+
+### Fixed
+- Ensure slice type flags have non-nil values.
+- Collect global flags from the full command hierarchy.
+- Docs prose.
+
+## [1.7.0] - 2015-05-03 (backfilled 2016-04-25)
+### Changed
+- `HelpPrinter` signature includes output writer.
+
+### Fixed
+- Specify go 1.1+ in docs.
+- Set `Writer` when running command as app.
+
+## [1.6.0] - 2015-03-23 (backfilled 2016-04-25)
+### Added
+- Multiple author support.
+- `NumFlags` at context level.
+- `Aliases` at command level.
+
+### Deprecated
+- `ShortName` at command level.
+
+### Fixed
+- Subcommand help output.
+- Backward compatible support for deprecated `Author` and `Email` fields.
+- Docs regarding `Names`/`Aliases`.
+
+## [1.5.0] - 2015-02-20 (backfilled 2016-04-25)
+### Added
+- `After` hook func support at app and command level.
+
+### Fixed
+- Use parsed context when running command as subcommand.
+- Docs prose.
+
+## [1.4.1] - 2015-01-09 (backfilled 2016-04-25)
+### Added
+- Support for hiding `-h / --help` flags, but not `help` subcommand.
+- Stop flag parsing after `--`.
+
+### Fixed
+- Help text for generic flags to specify single value.
+- Use double quotes in output for defaults.
+- Use `ParseInt` instead of `ParseUint` for int environment var values.
+- Use `0` as base when parsing int environment var values.
+
+## [1.4.0] - 2014-12-12 (backfilled 2016-04-25)
+### Added
+- Support for environment variable lookup "cascade".
+- Support for `Stdout` on app for output redirection.
+
+### Fixed
+- Print command help instead of app help in `ShowCommandHelp`.
+
+## [1.3.1] - 2014-11-13 (backfilled 2016-04-25)
+### Added
+- Docs and example code updates.
+
+### Changed
+- Default `-v / --version` flag made optional.
+
+## [1.3.0] - 2014-08-10 (backfilled 2016-04-25)
+### Added
+- `FlagNames` at context level.
+- Exposed `VersionPrinter` var for more control over version output.
+- Zsh completion hook.
+- `AUTHOR` section in default app help template.
+- Contribution guidelines.
+- `DurationFlag` type.
+
+## [1.2.0] - 2014-08-02
+### Added
+- Support for environment variable defaults on flags plus tests.
+
+## [1.1.0] - 2014-07-15
+### Added
+- Bash completion.
+- Optional hiding of built-in help command.
+- Optional skipping of flag parsing at command level.
+- `Author`, `Email`, and `Compiled` metadata on app.
+- `Before` hook func support at app and command level.
+- `CommandNotFound` func support at app level.
+- Command reference available on context.
+- `GenericFlag` type.
+- `Float64Flag` type.
+- `BoolTFlag` type.
+- `IsSet` flag helper on context.
+- More flag lookup funcs at context level.
+- More tests &amp; docs.
+
+### Changed
+- Help template updates to account for presence/absence of flags.
+- Separated subcommand help template.
+- Exposed `HelpPrinter` var for more control over help output.
+
+## [1.0.0] - 2013-11-01
+### Added
+- `help` flag in default app flag set and each command flag set.
+- Custom handling of argument parsing errors.
+- Command lookup by name at app level.
+- `StringSliceFlag` type and supporting `StringSlice` type.
+- `IntSliceFlag` type and supporting `IntSlice` type.
+- Slice type flag lookups by name at context level.
+- Export of app and command help functions.
+- More tests &amp; docs.
+
+## 0.1.0 - 2013-07-22
+### Added
+- Initial implementation.
+
+[Unreleased]: https://github.com/codegangsta/cli/compare/v1.17.0...HEAD
+[1.17.0]: https://github.com/codegangsta/cli/compare/v1.16.0...v1.17.0
+[1.16.0]: https://github.com/codegangsta/cli/compare/v1.15.0...v1.16.0
+[1.15.0]: https://github.com/codegangsta/cli/compare/v1.14.0...v1.15.0
+[1.14.0]: https://github.com/codegangsta/cli/compare/v1.13.0...v1.14.0
+[1.13.0]: https://github.com/codegangsta/cli/compare/v1.12.0...v1.13.0
+[1.12.0]: https://github.com/codegangsta/cli/compare/v1.11.1...v1.12.0
+[1.11.1]: https://github.com/codegangsta/cli/compare/v1.11.0...v1.11.1
+[1.11.0]: https://github.com/codegangsta/cli/compare/v1.10.2...v1.11.0
+[1.10.2]: https://github.com/codegangsta/cli/compare/v1.10.1...v1.10.2
+[1.10.1]: https://github.com/codegangsta/cli/compare/v1.10.0...v1.10.1
+[1.10.0]: https://github.com/codegangsta/cli/compare/v1.9.0...v1.10.0
+[1.9.0]: https://github.com/codegangsta/cli/compare/v1.8.0...v1.9.0
+[1.8.0]: https://github.com/codegangsta/cli/compare/v1.7.1...v1.8.0
+[1.7.1]: https://github.com/codegangsta/cli/compare/v1.7.0...v1.7.1
+[1.7.0]: https://github.com/codegangsta/cli/compare/v1.6.0...v1.7.0
+[1.6.0]: https://github.com/codegangsta/cli/compare/v1.5.0...v1.6.0
+[1.5.0]: https://github.com/codegangsta/cli/compare/v1.4.1...v1.5.0
+[1.4.1]: https://github.com/codegangsta/cli/compare/v1.4.0...v1.4.1
+[1.4.0]: https://github.com/codegangsta/cli/compare/v1.3.1...v1.4.0
+[1.3.1]: https://github.com/codegangsta/cli/compare/v1.3.0...v1.3.1
+[1.3.0]: https://github.com/codegangsta/cli/compare/v1.2.0...v1.3.0
+[1.2.0]: https://github.com/codegangsta/cli/compare/v1.1.0...v1.2.0
+[1.1.0]: https://github.com/codegangsta/cli/compare/v1.0.0...v1.1.0
+[1.0.0]: https://github.com/codegangsta/cli/compare/v0.1.0...v1.0.0

+ 21 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/LICENSE

@@ -0,0 +1,21 @@
+Copyright (C) 2013 Jeremy Saenz
+All Rights Reserved.
+
+MIT LICENSE
+
+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.

+ 579 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/README.md

@@ -0,0 +1,579 @@
+[![Coverage](http://gocover.io/_badge/github.com/codegangsta/cli?0)](http://gocover.io/github.com/codegangsta/cli)
+[![Build Status](https://travis-ci.org/codegangsta/cli.svg?branch=master)](https://travis-ci.org/codegangsta/cli)
+[![GoDoc](https://godoc.org/github.com/codegangsta/cli?status.svg)](https://godoc.org/github.com/codegangsta/cli)
+[![codebeat](https://codebeat.co/badges/0a8f30aa-f975-404b-b878-5fab3ae1cc5f)](https://codebeat.co/projects/github-com-codegangsta-cli)
+[![Go Report Card](https://goreportcard.com/badge/codegangsta/cli)](https://goreportcard.com/report/codegangsta/cli)
+
+# cli
+
+cli is a simple, fast, and fun package for building command line apps in Go. The goal is to enable developers to write fast and distributable command line applications in an expressive way.
+
+## Overview
+
+Command line apps are usually so tiny that there is absolutely no reason why your code should *not* be self-documenting. Things like generating help text and parsing command flags/options should not hinder productivity when writing a command line app.
+
+**This is where cli comes into play.** cli makes command line programming fun, organized, and expressive!
+
+## Installation
+
+Make sure you have a working Go environment (go 1.1+ is *required*). [See the install instructions](http://golang.org/doc/install.html).
+
+To install cli, simply run:
+```
+$ go get github.com/codegangsta/cli
+```
+
+Make sure your `PATH` includes to the `$GOPATH/bin` directory so your commands can be easily used:
+```
+export PATH=$PATH:$GOPATH/bin
+```
+
+## Getting Started
+
+One of the philosophies behind cli is that an API should be playful and full of discovery. So a cli app can be as little as one line of code in `main()`.
+
+``` go
+package main
+
+import (
+  "os"
+  "github.com/codegangsta/cli"
+)
+
+func main() {
+  cli.NewApp().Run(os.Args)
+}
+```
+
+This app will run and show help text, but is not very useful. Let's give an action to execute and some help documentation:
+
+<!-- {
+  "output": "boom! I say!"
+} -->
+``` go
+package main
+
+import (
+  "fmt"
+  "os"
+
+  "github.com/codegangsta/cli"
+)
+
+func main() {
+  app := cli.NewApp()
+  app.Name = "boom"
+  app.Usage = "make an explosive entrance"
+  app.Action = func(c *cli.Context) error {
+    fmt.Println("boom! I say!")
+    return nil
+  }
+
+  app.Run(os.Args)
+}
+```
+
+Running this already gives you a ton of functionality, plus support for things like subcommands and flags, which are covered below.
+
+## Example
+
+Being a programmer can be a lonely job. Thankfully by the power of automation that is not the case! Let's create a greeter app to fend off our demons of loneliness!
+
+Start by creating a directory named `greet`, and within it, add a file, `greet.go` with the following code in it:
+
+<!-- {
+  "output": "Hello friend!"
+} -->
+``` go
+package main
+
+import (
+  "fmt"
+  "os"
+
+  "github.com/codegangsta/cli"
+)
+
+func main() {
+  app := cli.NewApp()
+  app.Name = "greet"
+  app.Usage = "fight the loneliness!"
+  app.Action = func(c *cli.Context) error {
+    fmt.Println("Hello friend!")
+    return nil
+  }
+
+  app.Run(os.Args)
+}
+```
+
+Install our command to the `$GOPATH/bin` directory:
+
+```
+$ go install
+```
+
+Finally run our new command:
+
+```
+$ greet
+Hello friend!
+```
+
+cli also generates neat help text:
+
+```
+$ greet help
+NAME:
+    greet - fight the loneliness!
+
+USAGE:
+    greet [global options] command [command options] [arguments...]
+
+VERSION:
+    0.0.0
+
+COMMANDS:
+    help, h  Shows a list of commands or help for one command
+
+GLOBAL OPTIONS
+    --version	Shows version information
+```
+
+### Arguments
+
+You can lookup arguments by calling the `Args` function on `cli.Context`.
+
+``` go
+...
+app.Action = func(c *cli.Context) error {
+  fmt.Println("Hello", c.Args()[0])
+  return nil
+}
+...
+```
+
+### Flags
+
+Setting and querying flags is simple.
+
+``` go
+...
+app.Flags = []cli.Flag {
+  cli.StringFlag{
+    Name: "lang",
+    Value: "english",
+    Usage: "language for the greeting",
+  },
+}
+app.Action = func(c *cli.Context) error {
+  name := "someone"
+  if c.NArg() > 0 {
+    name = c.Args()[0]
+  }
+  if c.String("lang") == "spanish" {
+    fmt.Println("Hola", name)
+  } else {
+    fmt.Println("Hello", name)
+  }
+  return nil
+}
+...
+```
+
+You can also set a destination variable for a flag, to which the content will be scanned.
+
+``` go
+...
+var language string
+app.Flags = []cli.Flag {
+  cli.StringFlag{
+    Name:        "lang",
+    Value:       "english",
+    Usage:       "language for the greeting",
+    Destination: &language,
+  },
+}
+app.Action = func(c *cli.Context) error {
+  name := "someone"
+  if c.NArg() > 0 {
+    name = c.Args()[0]
+  }
+  if language == "spanish" {
+    fmt.Println("Hola", name)
+  } else {
+    fmt.Println("Hello", name)
+  }
+  return nil
+}
+...
+```
+
+See full list of flags at http://godoc.org/github.com/codegangsta/cli
+
+#### Placeholder Values
+
+Sometimes it's useful to specify a flag's value within the usage string itself. Such placeholders are
+indicated with back quotes.
+
+For example this:
+
+```go
+cli.StringFlag{
+  Name:  "config, c",
+  Usage: "Load configuration from `FILE`",
+}
+```
+
+Will result in help output like:
+
+```
+--config FILE, -c FILE   Load configuration from FILE
+```
+
+Note that only the first placeholder is used. Subsequent back-quoted words will be left as-is.
+
+#### Alternate Names
+
+You can set alternate (or short) names for flags by providing a comma-delimited list for the `Name`. e.g.
+
+``` go
+app.Flags = []cli.Flag {
+  cli.StringFlag{
+    Name: "lang, l",
+    Value: "english",
+    Usage: "language for the greeting",
+  },
+}
+```
+
+That flag can then be set with `--lang spanish` or `-l spanish`. Note that giving two different forms of the same flag in the same command invocation is an error.
+
+#### Values from the Environment
+
+You can also have the default value set from the environment via `EnvVar`.  e.g.
+
+``` go
+app.Flags = []cli.Flag {
+  cli.StringFlag{
+    Name: "lang, l",
+    Value: "english",
+    Usage: "language for the greeting",
+    EnvVar: "APP_LANG",
+  },
+}
+```
+
+The `EnvVar` may also be given as a comma-delimited "cascade", where the first environment variable that resolves is used as the default.
+
+``` go
+app.Flags = []cli.Flag {
+  cli.StringFlag{
+    Name: "lang, l",
+    Value: "english",
+    Usage: "language for the greeting",
+    EnvVar: "LEGACY_COMPAT_LANG,APP_LANG,LANG",
+  },
+}
+```
+
+#### Values from alternate input sources (YAML and others)
+
+There is a separate package altsrc that adds support for getting flag values from other input sources like YAML.
+
+In order to get values for a flag from an alternate input source the following code would be added to wrap an existing cli.Flag like below:
+
+``` go
+  altsrc.NewIntFlag(cli.IntFlag{Name: "test"})
+```
+
+Initialization must also occur for these flags. Below is an example initializing getting data from a yaml file below.
+
+``` go
+  command.Before = altsrc.InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load"))
+```
+
+The code above will use the "load" string as a flag name to get the file name of a yaml file from the cli.Context.
+It will then use that file name to initialize the yaml input source for any flags that are defined on that command.
+As a note the "load" flag used would also have to be defined on the command flags in order for this code snipped to work.
+
+Currently only YAML files are supported but developers can add support for other input sources by implementing the
+altsrc.InputSourceContext for their given sources.
+
+Here is a more complete sample of a command using YAML support:
+
+``` go
+  command := &cli.Command{
+    Name:        "test-cmd",
+    Aliases:     []string{"tc"},
+    Usage:       "this is for testing",
+    Description: "testing",
+    Action: func(c *cli.Context) error {
+      // Action to run
+      return nil
+    },
+    Flags: []cli.Flag{
+      NewIntFlag(cli.IntFlag{Name: "test"}),
+      cli.StringFlag{Name: "load"}},
+  }
+  command.Before = InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load"))
+  err := command.Run(c)
+```
+
+### Subcommands
+
+Subcommands can be defined for a more git-like command line app.
+
+```go
+...
+app.Commands = []cli.Command{
+  {
+    Name:      "add",
+    Aliases:     []string{"a"},
+    Usage:     "add a task to the list",
+    Action: func(c *cli.Context) error {
+      fmt.Println("added task: ", c.Args().First())
+      return nil
+    },
+  },
+  {
+    Name:      "complete",
+    Aliases:     []string{"c"},
+    Usage:     "complete a task on the list",
+    Action: func(c *cli.Context) error {
+      fmt.Println("completed task: ", c.Args().First())
+      return nil
+    },
+  },
+  {
+    Name:      "template",
+    Aliases:     []string{"r"},
+    Usage:     "options for task templates",
+    Subcommands: []cli.Command{
+      {
+        Name:  "add",
+        Usage: "add a new template",
+        Action: func(c *cli.Context) error {
+          fmt.Println("new task template: ", c.Args().First())
+          return nil
+        },
+      },
+      {
+        Name:  "remove",
+        Usage: "remove an existing template",
+        Action: func(c *cli.Context) error {
+          fmt.Println("removed task template: ", c.Args().First())
+          return nil
+        },
+      },
+    },
+  },
+}
+...
+```
+
+### Subcommands categories
+
+For additional organization in apps that have many subcommands, you can
+associate a category for each command to group them together in the help
+output.
+
+E.g.
+
+```go
+...
+  app.Commands = []cli.Command{
+    {
+      Name: "noop",
+    },
+    {
+      Name:     "add",
+      Category: "template",
+    },
+    {
+      Name:     "remove",
+      Category: "template",
+    },
+  }
+...
+```
+
+Will include:
+
+```
+...
+COMMANDS:
+    noop
+
+  Template actions:
+    add
+    remove
+...
+```
+
+### Exit code
+
+Calling `App.Run` will not automatically call `os.Exit`, which means that by
+default the exit code will "fall through" to being `0`.  An explicit exit code
+may be set by returning a non-nil error that fulfills `cli.ExitCoder`, *or* a
+`cli.MultiError` that includes an error that fulfills `cli.ExitCoder`, e.g.:
+
+``` go
+package main
+
+import (
+  "os"
+
+  "github.com/codegangsta/cli"
+)
+
+func main() {
+  app := cli.NewApp()
+  app.Flags = []cli.Flag{
+    cli.BoolTFlag{
+      Name:  "ginger-crouton",
+      Usage: "is it in the soup?",
+    },
+  }
+  app.Action = func(ctx *cli.Context) error {
+    if !ctx.Bool("ginger-crouton") {
+      return cli.NewExitError("it is not in the soup", 86)
+    }
+    return nil
+  }
+
+  app.Run(os.Args)
+}
+```
+
+### Bash Completion
+
+You can enable completion commands by setting the `EnableBashCompletion`
+flag on the `App` object.  By default, this setting will only auto-complete to
+show an app's subcommands, but you can write your own completion methods for
+the App or its subcommands.
+
+```go
+...
+var tasks = []string{"cook", "clean", "laundry", "eat", "sleep", "code"}
+app := cli.NewApp()
+app.EnableBashCompletion = true
+app.Commands = []cli.Command{
+  {
+    Name:  "complete",
+    Aliases: []string{"c"},
+    Usage: "complete a task on the list",
+    Action: func(c *cli.Context) error {
+       fmt.Println("completed task: ", c.Args().First())
+       return nil
+    },
+    BashComplete: func(c *cli.Context) {
+      // This will complete if no args are passed
+      if c.NArg() > 0 {
+        return
+      }
+      for _, t := range tasks {
+        fmt.Println(t)
+      }
+    },
+  }
+}
+...
+```
+
+#### To Enable
+
+Source the `autocomplete/bash_autocomplete` file in your `.bashrc` file while
+setting the `PROG` variable to the name of your program:
+
+`PROG=myprogram source /.../cli/autocomplete/bash_autocomplete`
+
+#### To Distribute
+
+Copy `autocomplete/bash_autocomplete` into `/etc/bash_completion.d/` and rename
+it to the name of the program you wish to add autocomplete support for (or
+automatically install it there if you are distributing a package). Don't forget
+to source the file to make it active in the current shell.
+
+```
+sudo cp src/bash_autocomplete /etc/bash_completion.d/<myprogram>
+source /etc/bash_completion.d/<myprogram>
+```
+
+Alternatively, you can just document that users should source the generic
+`autocomplete/bash_autocomplete` in their bash configuration with `$PROG` set
+to the name of their program (as above).
+
+### Generated Help Text Customization
+
+All of the help text generation may be customized, and at multiple levels.  The
+templates are exposed as variables `AppHelpTemplate`, `CommandHelpTemplate`, and
+`SubcommandHelpTemplate` which may be reassigned or augmented, and full override
+is possible by assigning a compatible func to the `cli.HelpPrinter` variable,
+e.g.:
+
+<!-- {
+  "output": "Ha HA.  I pwnd the help!!1"
+} -->
+``` go
+package main
+
+import (
+  "fmt"
+  "io"
+  "os"
+
+  "github.com/codegangsta/cli"
+)
+
+func main() {
+  // EXAMPLE: Append to an existing template
+  cli.AppHelpTemplate = fmt.Sprintf(`%s
+
+WEBSITE: http://awesometown.example.com
+
+SUPPORT: [email protected]
+
+`, cli.AppHelpTemplate)
+
+  // EXAMPLE: Override a template
+  cli.AppHelpTemplate = `NAME:
+   {{.Name}} - {{.Usage}}
+USAGE:
+   {{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command
+[command options]{{end}} {{if
+.ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}
+   {{if len .Authors}}
+AUTHOR(S):
+   {{range .Authors}}{{ . }}{{end}}
+   {{end}}{{if .Commands}}
+COMMANDS:
+{{range .Commands}}{{if not .HideHelp}}   {{join .Names ", "}}{{ "\t"
+}}{{.Usage}}{{ "\n" }}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
+GLOBAL OPTIONS:
+   {{range .VisibleFlags}}{{.}}
+   {{end}}{{end}}{{if .Copyright }}
+COPYRIGHT:
+   {{.Copyright}}
+   {{end}}{{if .Version}}
+VERSION:
+   {{.Version}}
+   {{end}}
+`
+
+  // EXAMPLE: Replace the `HelpPrinter` func
+  cli.HelpPrinter = func(w io.Writer, templ string, data interface{}) {
+    fmt.Println("Ha HA.  I pwnd the help!!1")
+  }
+
+  cli.NewApp().Run(os.Args)
+}
+```
+
+## Contribution Guidelines
+
+Feel free to put up a pull request to fix a bug or maybe add a feature. I will give it a code review and make sure that it does not break backwards compatibility. If I or any other collaborators agree that it is in line with the vision of the project, we will work with you to get the code into a mergeable state and merge it into the master branch.
+
+If you have contributed something significant to the project, I will most likely add you as a collaborator. As a collaborator you are given the ability to merge others pull requests. It is very important that new code does not break existing code, so be careful about what code you do choose to merge. If you have any questions feel free to link @codegangsta to the issue in question and we can review it together.
+
+If you feel like you have contributed to the project but have not yet been added as a collaborator, I probably forgot to add you. Hit @codegangsta up over email and we will get it figured out.

+ 439 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/altsrc/flag.go

@@ -0,0 +1,439 @@
+package altsrc
+
+import (
+	"flag"
+	"fmt"
+	"os"
+	"strconv"
+	"strings"
+
+	"github.com/codegangsta/cli"
+)
+
+// FlagInputSourceExtension is an extension interface of cli.Flag that
+// allows a value to be set on the existing parsed flags.
+type FlagInputSourceExtension interface {
+	cli.Flag
+	ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error
+}
+
+// ApplyInputSourceValues iterates over all provided flags and
+// executes ApplyInputSourceValue on flags implementing the
+// FlagInputSourceExtension interface to initialize these flags
+// to an alternate input source.
+func ApplyInputSourceValues(context *cli.Context, inputSourceContext InputSourceContext, flags []cli.Flag) error {
+	for _, f := range flags {
+		inputSourceExtendedFlag, isType := f.(FlagInputSourceExtension)
+		if isType {
+			err := inputSourceExtendedFlag.ApplyInputSourceValue(context, inputSourceContext)
+			if err != nil {
+				return err
+			}
+		}
+	}
+
+	return nil
+}
+
+// InitInputSource is used to to setup an InputSourceContext on a cli.Command Before method. It will create a new
+// input source based on the func provided. If there is no error it will then apply the new input source to any flags
+// that are supported by the input source
+func InitInputSource(flags []cli.Flag, createInputSource func() (InputSourceContext, error)) cli.BeforeFunc {
+	return func(context *cli.Context) error {
+		inputSource, err := createInputSource()
+		if err != nil {
+			return fmt.Errorf("Unable to create input source: inner error: \n'%v'", err.Error())
+		}
+
+		return ApplyInputSourceValues(context, inputSource, flags)
+	}
+}
+
+// InitInputSourceWithContext is used to to setup an InputSourceContext on a cli.Command Before method. It will create a new
+// input source based on the func provided with potentially using existing cli.Context values to initialize itself. If there is
+// no error it will then apply the new input source to any flags that are supported by the input source
+func InitInputSourceWithContext(flags []cli.Flag, createInputSource func(context *cli.Context) (InputSourceContext, error)) cli.BeforeFunc {
+	return func(context *cli.Context) error {
+		inputSource, err := createInputSource(context)
+		if err != nil {
+			return fmt.Errorf("Unable to create input source with context: inner error: \n'%v'", err.Error())
+		}
+
+		return ApplyInputSourceValues(context, inputSource, flags)
+	}
+}
+
+// GenericFlag is the flag type that wraps cli.GenericFlag to allow
+// for other values to be specified
+type GenericFlag struct {
+	cli.GenericFlag
+	set *flag.FlagSet
+}
+
+// NewGenericFlag creates a new GenericFlag
+func NewGenericFlag(flag cli.GenericFlag) *GenericFlag {
+	return &GenericFlag{GenericFlag: flag, set: nil}
+}
+
+// ApplyInputSourceValue applies a generic value to the flagSet if required
+func (f *GenericFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error {
+	if f.set != nil {
+		if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVar) {
+			value, err := isc.Generic(f.GenericFlag.Name)
+			if err != nil {
+				return err
+			}
+			if value != nil {
+				eachName(f.Name, func(name string) {
+					f.set.Set(f.Name, value.String())
+				})
+			}
+		}
+	}
+
+	return nil
+}
+
+// Apply saves the flagSet for later usage then calls
+// the wrapped GenericFlag.Apply
+func (f *GenericFlag) Apply(set *flag.FlagSet) {
+	f.set = set
+	f.GenericFlag.Apply(set)
+}
+
+// StringSliceFlag is the flag type that wraps cli.StringSliceFlag to allow
+// for other values to be specified
+type StringSliceFlag struct {
+	cli.StringSliceFlag
+	set *flag.FlagSet
+}
+
+// NewStringSliceFlag creates a new StringSliceFlag
+func NewStringSliceFlag(flag cli.StringSliceFlag) *StringSliceFlag {
+	return &StringSliceFlag{StringSliceFlag: flag, set: nil}
+}
+
+// ApplyInputSourceValue applies a StringSlice value to the flagSet if required
+func (f *StringSliceFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error {
+	if f.set != nil {
+		if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVar) {
+			value, err := isc.StringSlice(f.StringSliceFlag.Name)
+			if err != nil {
+				return err
+			}
+			if value != nil {
+				var sliceValue cli.StringSlice = value
+				eachName(f.Name, func(name string) {
+					underlyingFlag := f.set.Lookup(f.Name)
+					if underlyingFlag != nil {
+						underlyingFlag.Value = &sliceValue
+					}
+				})
+			}
+		}
+	}
+	return nil
+}
+
+// Apply saves the flagSet for later usage then calls
+// the wrapped StringSliceFlag.Apply
+func (f *StringSliceFlag) Apply(set *flag.FlagSet) {
+	f.set = set
+	f.StringSliceFlag.Apply(set)
+}
+
+// IntSliceFlag is the flag type that wraps cli.IntSliceFlag to allow
+// for other values to be specified
+type IntSliceFlag struct {
+	cli.IntSliceFlag
+	set *flag.FlagSet
+}
+
+// NewIntSliceFlag creates a new IntSliceFlag
+func NewIntSliceFlag(flag cli.IntSliceFlag) *IntSliceFlag {
+	return &IntSliceFlag{IntSliceFlag: flag, set: nil}
+}
+
+// ApplyInputSourceValue applies a IntSlice value if required
+func (f *IntSliceFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error {
+	if f.set != nil {
+		if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVar) {
+			value, err := isc.IntSlice(f.IntSliceFlag.Name)
+			if err != nil {
+				return err
+			}
+			if value != nil {
+				var sliceValue cli.IntSlice = value
+				eachName(f.Name, func(name string) {
+					underlyingFlag := f.set.Lookup(f.Name)
+					if underlyingFlag != nil {
+						underlyingFlag.Value = &sliceValue
+					}
+				})
+			}
+		}
+	}
+	return nil
+}
+
+// Apply saves the flagSet for later usage then calls
+// the wrapped IntSliceFlag.Apply
+func (f *IntSliceFlag) Apply(set *flag.FlagSet) {
+	f.set = set
+	f.IntSliceFlag.Apply(set)
+}
+
+// BoolFlag is the flag type that wraps cli.BoolFlag to allow
+// for other values to be specified
+type BoolFlag struct {
+	cli.BoolFlag
+	set *flag.FlagSet
+}
+
+// NewBoolFlag creates a new BoolFlag
+func NewBoolFlag(flag cli.BoolFlag) *BoolFlag {
+	return &BoolFlag{BoolFlag: flag, set: nil}
+}
+
+// ApplyInputSourceValue applies a Bool value to the flagSet if required
+func (f *BoolFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error {
+	if f.set != nil {
+		if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVar) {
+			value, err := isc.Bool(f.BoolFlag.Name)
+			if err != nil {
+				return err
+			}
+			if value {
+				eachName(f.Name, func(name string) {
+					f.set.Set(f.Name, strconv.FormatBool(value))
+				})
+			}
+		}
+	}
+	return nil
+}
+
+// Apply saves the flagSet for later usage then calls
+// the wrapped BoolFlag.Apply
+func (f *BoolFlag) Apply(set *flag.FlagSet) {
+	f.set = set
+	f.BoolFlag.Apply(set)
+}
+
+// BoolTFlag is the flag type that wraps cli.BoolTFlag to allow
+// for other values to be specified
+type BoolTFlag struct {
+	cli.BoolTFlag
+	set *flag.FlagSet
+}
+
+// NewBoolTFlag creates a new BoolTFlag
+func NewBoolTFlag(flag cli.BoolTFlag) *BoolTFlag {
+	return &BoolTFlag{BoolTFlag: flag, set: nil}
+}
+
+// ApplyInputSourceValue applies a BoolT value to the flagSet if required
+func (f *BoolTFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error {
+	if f.set != nil {
+		if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVar) {
+			value, err := isc.BoolT(f.BoolTFlag.Name)
+			if err != nil {
+				return err
+			}
+			if !value {
+				eachName(f.Name, func(name string) {
+					f.set.Set(f.Name, strconv.FormatBool(value))
+				})
+			}
+		}
+	}
+	return nil
+}
+
+// Apply saves the flagSet for later usage then calls
+// the wrapped BoolTFlag.Apply
+func (f *BoolTFlag) Apply(set *flag.FlagSet) {
+	f.set = set
+
+	f.BoolTFlag.Apply(set)
+}
+
+// StringFlag is the flag type that wraps cli.StringFlag to allow
+// for other values to be specified
+type StringFlag struct {
+	cli.StringFlag
+	set *flag.FlagSet
+}
+
+// NewStringFlag creates a new StringFlag
+func NewStringFlag(flag cli.StringFlag) *StringFlag {
+	return &StringFlag{StringFlag: flag, set: nil}
+}
+
+// ApplyInputSourceValue applies a String value to the flagSet if required
+func (f *StringFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error {
+	if f.set != nil {
+		if !(context.IsSet(f.Name) || isEnvVarSet(f.EnvVar)) {
+			value, err := isc.String(f.StringFlag.Name)
+			if err != nil {
+				return err
+			}
+			if value != "" {
+				eachName(f.Name, func(name string) {
+					f.set.Set(f.Name, value)
+				})
+			}
+		}
+	}
+	return nil
+}
+
+// Apply saves the flagSet for later usage then calls
+// the wrapped StringFlag.Apply
+func (f *StringFlag) Apply(set *flag.FlagSet) {
+	f.set = set
+
+	f.StringFlag.Apply(set)
+}
+
+// IntFlag is the flag type that wraps cli.IntFlag to allow
+// for other values to be specified
+type IntFlag struct {
+	cli.IntFlag
+	set *flag.FlagSet
+}
+
+// NewIntFlag creates a new IntFlag
+func NewIntFlag(flag cli.IntFlag) *IntFlag {
+	return &IntFlag{IntFlag: flag, set: nil}
+}
+
+// ApplyInputSourceValue applies a int value to the flagSet if required
+func (f *IntFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error {
+	if f.set != nil {
+		if !(context.IsSet(f.Name) || isEnvVarSet(f.EnvVar)) {
+			value, err := isc.Int(f.IntFlag.Name)
+			if err != nil {
+				return err
+			}
+			if value > 0 {
+				eachName(f.Name, func(name string) {
+					f.set.Set(f.Name, strconv.FormatInt(int64(value), 10))
+				})
+			}
+		}
+	}
+	return nil
+}
+
+// Apply saves the flagSet for later usage then calls
+// the wrapped IntFlag.Apply
+func (f *IntFlag) Apply(set *flag.FlagSet) {
+	f.set = set
+	f.IntFlag.Apply(set)
+}
+
+// DurationFlag is the flag type that wraps cli.DurationFlag to allow
+// for other values to be specified
+type DurationFlag struct {
+	cli.DurationFlag
+	set *flag.FlagSet
+}
+
+// NewDurationFlag creates a new DurationFlag
+func NewDurationFlag(flag cli.DurationFlag) *DurationFlag {
+	return &DurationFlag{DurationFlag: flag, set: nil}
+}
+
+// ApplyInputSourceValue applies a Duration value to the flagSet if required
+func (f *DurationFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error {
+	if f.set != nil {
+		if !(context.IsSet(f.Name) || isEnvVarSet(f.EnvVar)) {
+			value, err := isc.Duration(f.DurationFlag.Name)
+			if err != nil {
+				return err
+			}
+			if value > 0 {
+				eachName(f.Name, func(name string) {
+					f.set.Set(f.Name, value.String())
+				})
+			}
+		}
+	}
+	return nil
+}
+
+// Apply saves the flagSet for later usage then calls
+// the wrapped DurationFlag.Apply
+func (f *DurationFlag) Apply(set *flag.FlagSet) {
+	f.set = set
+
+	f.DurationFlag.Apply(set)
+}
+
+// Float64Flag is the flag type that wraps cli.Float64Flag to allow
+// for other values to be specified
+type Float64Flag struct {
+	cli.Float64Flag
+	set *flag.FlagSet
+}
+
+// NewFloat64Flag creates a new Float64Flag
+func NewFloat64Flag(flag cli.Float64Flag) *Float64Flag {
+	return &Float64Flag{Float64Flag: flag, set: nil}
+}
+
+// ApplyInputSourceValue applies a Float64 value to the flagSet if required
+func (f *Float64Flag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error {
+	if f.set != nil {
+		if !(context.IsSet(f.Name) || isEnvVarSet(f.EnvVar)) {
+			value, err := isc.Float64(f.Float64Flag.Name)
+			if err != nil {
+				return err
+			}
+			if value > 0 {
+				floatStr := float64ToString(value)
+				eachName(f.Name, func(name string) {
+					f.set.Set(f.Name, floatStr)
+				})
+			}
+		}
+	}
+	return nil
+}
+
+// Apply saves the flagSet for later usage then calls
+// the wrapped Float64Flag.Apply
+func (f *Float64Flag) Apply(set *flag.FlagSet) {
+	f.set = set
+
+	f.Float64Flag.Apply(set)
+}
+
+func isEnvVarSet(envVars string) bool {
+	for _, envVar := range strings.Split(envVars, ",") {
+		envVar = strings.TrimSpace(envVar)
+		if envVal := os.Getenv(envVar); envVal != "" {
+			// TODO: Can't use this for bools as
+			// set means that it was true or false based on
+			// Bool flag type, should work for other types
+			if len(envVal) > 0 {
+				return true
+			}
+		}
+	}
+
+	return false
+}
+
+func float64ToString(f float64) string {
+	return fmt.Sprintf("%v", f)
+}
+
+func eachName(longName string, fn func(string)) {
+	parts := strings.Split(longName, ",")
+	for _, name := range parts {
+		name = strings.Trim(name, " ")
+		fn(name)
+	}
+}

+ 336 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/altsrc/flag_test.go

@@ -0,0 +1,336 @@
+package altsrc
+
+import (
+	"flag"
+	"fmt"
+	"os"
+	"strings"
+	"testing"
+	"time"
+
+	"github.com/codegangsta/cli"
+)
+
+type testApplyInputSource struct {
+	Flag               FlagInputSourceExtension
+	FlagName           string
+	FlagSetName        string
+	Expected           string
+	ContextValueString string
+	ContextValue       flag.Value
+	EnvVarValue        string
+	EnvVarName         string
+	MapValue           interface{}
+}
+
+func TestGenericApplyInputSourceValue(t *testing.T) {
+	v := &Parser{"abc", "def"}
+	c := runTest(t, testApplyInputSource{
+		Flag:     NewGenericFlag(cli.GenericFlag{Name: "test", Value: &Parser{}}),
+		FlagName: "test",
+		MapValue: v,
+	})
+	expect(t, v, c.Generic("test"))
+}
+
+func TestGenericApplyInputSourceMethodContextSet(t *testing.T) {
+	p := &Parser{"abc", "def"}
+	c := runTest(t, testApplyInputSource{
+		Flag:               NewGenericFlag(cli.GenericFlag{Name: "test", Value: &Parser{}}),
+		FlagName:           "test",
+		MapValue:           &Parser{"efg", "hig"},
+		ContextValueString: p.String(),
+	})
+	expect(t, p, c.Generic("test"))
+}
+
+func TestGenericApplyInputSourceMethodEnvVarSet(t *testing.T) {
+	c := runTest(t, testApplyInputSource{
+		Flag:        NewGenericFlag(cli.GenericFlag{Name: "test", Value: &Parser{}, EnvVar: "TEST"}),
+		FlagName:    "test",
+		MapValue:    &Parser{"efg", "hij"},
+		EnvVarName:  "TEST",
+		EnvVarValue: "abc,def",
+	})
+	expect(t, &Parser{"abc", "def"}, c.Generic("test"))
+}
+
+func TestStringSliceApplyInputSourceValue(t *testing.T) {
+	c := runTest(t, testApplyInputSource{
+		Flag:     NewStringSliceFlag(cli.StringSliceFlag{Name: "test"}),
+		FlagName: "test",
+		MapValue: []string{"hello", "world"},
+	})
+	expect(t, c.StringSlice("test"), []string{"hello", "world"})
+}
+
+func TestStringSliceApplyInputSourceMethodContextSet(t *testing.T) {
+	c := runTest(t, testApplyInputSource{
+		Flag:               NewStringSliceFlag(cli.StringSliceFlag{Name: "test"}),
+		FlagName:           "test",
+		MapValue:           []string{"hello", "world"},
+		ContextValueString: "ohno",
+	})
+	expect(t, c.StringSlice("test"), []string{"ohno"})
+}
+
+func TestStringSliceApplyInputSourceMethodEnvVarSet(t *testing.T) {
+	c := runTest(t, testApplyInputSource{
+		Flag:        NewStringSliceFlag(cli.StringSliceFlag{Name: "test", EnvVar: "TEST"}),
+		FlagName:    "test",
+		MapValue:    []string{"hello", "world"},
+		EnvVarName:  "TEST",
+		EnvVarValue: "oh,no",
+	})
+	expect(t, c.StringSlice("test"), []string{"oh", "no"})
+}
+
+func TestIntSliceApplyInputSourceValue(t *testing.T) {
+	c := runTest(t, testApplyInputSource{
+		Flag:     NewIntSliceFlag(cli.IntSliceFlag{Name: "test"}),
+		FlagName: "test",
+		MapValue: []int{1, 2},
+	})
+	expect(t, c.IntSlice("test"), []int{1, 2})
+}
+
+func TestIntSliceApplyInputSourceMethodContextSet(t *testing.T) {
+	c := runTest(t, testApplyInputSource{
+		Flag:               NewIntSliceFlag(cli.IntSliceFlag{Name: "test"}),
+		FlagName:           "test",
+		MapValue:           []int{1, 2},
+		ContextValueString: "3",
+	})
+	expect(t, c.IntSlice("test"), []int{3})
+}
+
+func TestIntSliceApplyInputSourceMethodEnvVarSet(t *testing.T) {
+	c := runTest(t, testApplyInputSource{
+		Flag:        NewIntSliceFlag(cli.IntSliceFlag{Name: "test", EnvVar: "TEST"}),
+		FlagName:    "test",
+		MapValue:    []int{1, 2},
+		EnvVarName:  "TEST",
+		EnvVarValue: "3,4",
+	})
+	expect(t, c.IntSlice("test"), []int{3, 4})
+}
+
+func TestBoolApplyInputSourceMethodSet(t *testing.T) {
+	c := runTest(t, testApplyInputSource{
+		Flag:     NewBoolFlag(cli.BoolFlag{Name: "test"}),
+		FlagName: "test",
+		MapValue: true,
+	})
+	expect(t, true, c.Bool("test"))
+}
+
+func TestBoolApplyInputSourceMethodContextSet(t *testing.T) {
+	c := runTest(t, testApplyInputSource{
+		Flag:               NewBoolFlag(cli.BoolFlag{Name: "test"}),
+		FlagName:           "test",
+		MapValue:           false,
+		ContextValueString: "true",
+	})
+	expect(t, true, c.Bool("test"))
+}
+
+func TestBoolApplyInputSourceMethodEnvVarSet(t *testing.T) {
+	c := runTest(t, testApplyInputSource{
+		Flag:        NewBoolFlag(cli.BoolFlag{Name: "test", EnvVar: "TEST"}),
+		FlagName:    "test",
+		MapValue:    false,
+		EnvVarName:  "TEST",
+		EnvVarValue: "true",
+	})
+	expect(t, true, c.Bool("test"))
+}
+
+func TestBoolTApplyInputSourceMethodSet(t *testing.T) {
+	c := runTest(t, testApplyInputSource{
+		Flag:     NewBoolTFlag(cli.BoolTFlag{Name: "test"}),
+		FlagName: "test",
+		MapValue: false,
+	})
+	expect(t, false, c.BoolT("test"))
+}
+
+func TestBoolTApplyInputSourceMethodContextSet(t *testing.T) {
+	c := runTest(t, testApplyInputSource{
+		Flag:               NewBoolTFlag(cli.BoolTFlag{Name: "test"}),
+		FlagName:           "test",
+		MapValue:           true,
+		ContextValueString: "false",
+	})
+	expect(t, false, c.BoolT("test"))
+}
+
+func TestBoolTApplyInputSourceMethodEnvVarSet(t *testing.T) {
+	c := runTest(t, testApplyInputSource{
+		Flag:        NewBoolTFlag(cli.BoolTFlag{Name: "test", EnvVar: "TEST"}),
+		FlagName:    "test",
+		MapValue:    true,
+		EnvVarName:  "TEST",
+		EnvVarValue: "false",
+	})
+	expect(t, false, c.BoolT("test"))
+}
+
+func TestStringApplyInputSourceMethodSet(t *testing.T) {
+	c := runTest(t, testApplyInputSource{
+		Flag:     NewStringFlag(cli.StringFlag{Name: "test"}),
+		FlagName: "test",
+		MapValue: "hello",
+	})
+	expect(t, "hello", c.String("test"))
+}
+
+func TestStringApplyInputSourceMethodContextSet(t *testing.T) {
+	c := runTest(t, testApplyInputSource{
+		Flag:               NewStringFlag(cli.StringFlag{Name: "test"}),
+		FlagName:           "test",
+		MapValue:           "hello",
+		ContextValueString: "goodbye",
+	})
+	expect(t, "goodbye", c.String("test"))
+}
+
+func TestStringApplyInputSourceMethodEnvVarSet(t *testing.T) {
+	c := runTest(t, testApplyInputSource{
+		Flag:        NewStringFlag(cli.StringFlag{Name: "test", EnvVar: "TEST"}),
+		FlagName:    "test",
+		MapValue:    "hello",
+		EnvVarName:  "TEST",
+		EnvVarValue: "goodbye",
+	})
+	expect(t, "goodbye", c.String("test"))
+}
+
+func TestIntApplyInputSourceMethodSet(t *testing.T) {
+	c := runTest(t, testApplyInputSource{
+		Flag:     NewIntFlag(cli.IntFlag{Name: "test"}),
+		FlagName: "test",
+		MapValue: 15,
+	})
+	expect(t, 15, c.Int("test"))
+}
+
+func TestIntApplyInputSourceMethodContextSet(t *testing.T) {
+	c := runTest(t, testApplyInputSource{
+		Flag:               NewIntFlag(cli.IntFlag{Name: "test"}),
+		FlagName:           "test",
+		MapValue:           15,
+		ContextValueString: "7",
+	})
+	expect(t, 7, c.Int("test"))
+}
+
+func TestIntApplyInputSourceMethodEnvVarSet(t *testing.T) {
+	c := runTest(t, testApplyInputSource{
+		Flag:        NewIntFlag(cli.IntFlag{Name: "test", EnvVar: "TEST"}),
+		FlagName:    "test",
+		MapValue:    15,
+		EnvVarName:  "TEST",
+		EnvVarValue: "12",
+	})
+	expect(t, 12, c.Int("test"))
+}
+
+func TestDurationApplyInputSourceMethodSet(t *testing.T) {
+	c := runTest(t, testApplyInputSource{
+		Flag:     NewDurationFlag(cli.DurationFlag{Name: "test"}),
+		FlagName: "test",
+		MapValue: time.Duration(30 * time.Second),
+	})
+	expect(t, time.Duration(30*time.Second), c.Duration("test"))
+}
+
+func TestDurationApplyInputSourceMethodContextSet(t *testing.T) {
+	c := runTest(t, testApplyInputSource{
+		Flag:               NewDurationFlag(cli.DurationFlag{Name: "test"}),
+		FlagName:           "test",
+		MapValue:           time.Duration(30 * time.Second),
+		ContextValueString: time.Duration(15 * time.Second).String(),
+	})
+	expect(t, time.Duration(15*time.Second), c.Duration("test"))
+}
+
+func TestDurationApplyInputSourceMethodEnvVarSet(t *testing.T) {
+	c := runTest(t, testApplyInputSource{
+		Flag:        NewDurationFlag(cli.DurationFlag{Name: "test", EnvVar: "TEST"}),
+		FlagName:    "test",
+		MapValue:    time.Duration(30 * time.Second),
+		EnvVarName:  "TEST",
+		EnvVarValue: time.Duration(15 * time.Second).String(),
+	})
+	expect(t, time.Duration(15*time.Second), c.Duration("test"))
+}
+
+func TestFloat64ApplyInputSourceMethodSet(t *testing.T) {
+	c := runTest(t, testApplyInputSource{
+		Flag:     NewFloat64Flag(cli.Float64Flag{Name: "test"}),
+		FlagName: "test",
+		MapValue: 1.3,
+	})
+	expect(t, 1.3, c.Float64("test"))
+}
+
+func TestFloat64ApplyInputSourceMethodContextSet(t *testing.T) {
+	c := runTest(t, testApplyInputSource{
+		Flag:               NewFloat64Flag(cli.Float64Flag{Name: "test"}),
+		FlagName:           "test",
+		MapValue:           1.3,
+		ContextValueString: fmt.Sprintf("%v", 1.4),
+	})
+	expect(t, 1.4, c.Float64("test"))
+}
+
+func TestFloat64ApplyInputSourceMethodEnvVarSet(t *testing.T) {
+	c := runTest(t, testApplyInputSource{
+		Flag:        NewFloat64Flag(cli.Float64Flag{Name: "test", EnvVar: "TEST"}),
+		FlagName:    "test",
+		MapValue:    1.3,
+		EnvVarName:  "TEST",
+		EnvVarValue: fmt.Sprintf("%v", 1.4),
+	})
+	expect(t, 1.4, c.Float64("test"))
+}
+
+func runTest(t *testing.T, test testApplyInputSource) *cli.Context {
+	inputSource := &MapInputSource{valueMap: map[interface{}]interface{}{test.FlagName: test.MapValue}}
+	set := flag.NewFlagSet(test.FlagSetName, flag.ContinueOnError)
+	c := cli.NewContext(nil, set, nil)
+	if test.EnvVarName != "" && test.EnvVarValue != "" {
+		os.Setenv(test.EnvVarName, test.EnvVarValue)
+		defer os.Setenv(test.EnvVarName, "")
+	}
+
+	test.Flag.Apply(set)
+	if test.ContextValue != nil {
+		flag := set.Lookup(test.FlagName)
+		flag.Value = test.ContextValue
+	}
+	if test.ContextValueString != "" {
+		set.Set(test.FlagName, test.ContextValueString)
+	}
+	test.Flag.ApplyInputSourceValue(c, inputSource)
+
+	return c
+}
+
+type Parser [2]string
+
+func (p *Parser) Set(value string) error {
+	parts := strings.Split(value, ",")
+	if len(parts) != 2 {
+		return fmt.Errorf("invalid format")
+	}
+
+	(*p)[0] = parts[0]
+	(*p)[1] = parts[1]
+
+	return nil
+}
+
+func (p *Parser) String() string {
+	return fmt.Sprintf("%s,%s", p[0], p[1])
+}

+ 18 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/altsrc/helpers_test.go

@@ -0,0 +1,18 @@
+package altsrc
+
+import (
+	"reflect"
+	"testing"
+)
+
+func expect(t *testing.T, a interface{}, b interface{}) {
+	if !reflect.DeepEqual(b, a) {
+		t.Errorf("Expected %#v (type %v) - Got %#v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
+	}
+}
+
+func refute(t *testing.T, a interface{}, b interface{}) {
+	if a == b {
+		t.Errorf("Did not expect %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
+	}
+}

+ 21 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/altsrc/input_source_context.go

@@ -0,0 +1,21 @@
+package altsrc
+
+import (
+	"time"
+
+	"github.com/codegangsta/cli"
+)
+
+// InputSourceContext is an interface used to allow
+// other input sources to be implemented as needed.
+type InputSourceContext interface {
+	Int(name string) (int, error)
+	Duration(name string) (time.Duration, error)
+	Float64(name string) (float64, error)
+	String(name string) (string, error)
+	StringSlice(name string) ([]string, error)
+	IntSlice(name string) ([]int, error)
+	Generic(name string) (cli.Generic, error)
+	Bool(name string) (bool, error)
+	BoolT(name string) (bool, error)
+}

+ 248 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/altsrc/map_input_source.go

@@ -0,0 +1,248 @@
+package altsrc
+
+import (
+	"fmt"
+	"reflect"
+	"strings"
+	"time"
+
+	"github.com/codegangsta/cli"
+)
+
+// MapInputSource implements InputSourceContext to return
+// data from the map that is loaded.
+type MapInputSource struct {
+	valueMap map[interface{}]interface{}
+}
+
+// nestedVal checks if the name has '.' delimiters.
+// If so, it tries to traverse the tree by the '.' delimited sections to find
+// a nested value for the key.
+func nestedVal(name string, tree map[interface{}]interface{}) (interface{}, bool) {
+	if sections := strings.Split(name, "."); len(sections) > 1 {
+		node := tree
+		for _, section := range sections[:len(sections)-1] {
+			if child, ok := node[section]; !ok {
+				return nil, false
+			} else {
+				if ctype, ok := child.(map[interface{}]interface{}); !ok {
+					return nil, false
+				} else {
+					node = ctype
+				}
+			}
+		}
+		if val, ok := node[sections[len(sections)-1]]; ok {
+			return val, true
+		}
+	}
+	return nil, false
+}
+
+// Int returns an int from the map if it exists otherwise returns 0
+func (fsm *MapInputSource) Int(name string) (int, error) {
+	otherGenericValue, exists := fsm.valueMap[name]
+	if exists {
+		otherValue, isType := otherGenericValue.(int)
+		if !isType {
+			return 0, incorrectTypeForFlagError(name, "int", otherGenericValue)
+		}
+		return otherValue, nil
+	}
+	nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
+	if exists {
+		otherValue, isType := nestedGenericValue.(int)
+		if !isType {
+			return 0, incorrectTypeForFlagError(name, "int", nestedGenericValue)
+		}
+		return otherValue, nil
+	}
+
+	return 0, nil
+}
+
+// Duration returns a duration from the map if it exists otherwise returns 0
+func (fsm *MapInputSource) Duration(name string) (time.Duration, error) {
+	otherGenericValue, exists := fsm.valueMap[name]
+	if exists {
+		otherValue, isType := otherGenericValue.(time.Duration)
+		if !isType {
+			return 0, incorrectTypeForFlagError(name, "duration", otherGenericValue)
+		}
+		return otherValue, nil
+	}
+	nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
+	if exists {
+		otherValue, isType := nestedGenericValue.(time.Duration)
+		if !isType {
+			return 0, incorrectTypeForFlagError(name, "duration", nestedGenericValue)
+		}
+		return otherValue, nil
+	}
+
+	return 0, nil
+}
+
+// Float64 returns an float64 from the map if it exists otherwise returns 0
+func (fsm *MapInputSource) Float64(name string) (float64, error) {
+	otherGenericValue, exists := fsm.valueMap[name]
+	if exists {
+		otherValue, isType := otherGenericValue.(float64)
+		if !isType {
+			return 0, incorrectTypeForFlagError(name, "float64", otherGenericValue)
+		}
+		return otherValue, nil
+	}
+	nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
+	if exists {
+		otherValue, isType := nestedGenericValue.(float64)
+		if !isType {
+			return 0, incorrectTypeForFlagError(name, "float64", nestedGenericValue)
+		}
+		return otherValue, nil
+	}
+
+	return 0, nil
+}
+
+// String returns a string from the map if it exists otherwise returns an empty string
+func (fsm *MapInputSource) String(name string) (string, error) {
+	otherGenericValue, exists := fsm.valueMap[name]
+	if exists {
+		otherValue, isType := otherGenericValue.(string)
+		if !isType {
+			return "", incorrectTypeForFlagError(name, "string", otherGenericValue)
+		}
+		return otherValue, nil
+	}
+	nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
+	if exists {
+		otherValue, isType := nestedGenericValue.(string)
+		if !isType {
+			return "", incorrectTypeForFlagError(name, "string", nestedGenericValue)
+		}
+		return otherValue, nil
+	}
+
+	return "", nil
+}
+
+// StringSlice returns an []string from the map if it exists otherwise returns nil
+func (fsm *MapInputSource) StringSlice(name string) ([]string, error) {
+	otherGenericValue, exists := fsm.valueMap[name]
+	if exists {
+		otherValue, isType := otherGenericValue.([]string)
+		if !isType {
+			return nil, incorrectTypeForFlagError(name, "[]string", otherGenericValue)
+		}
+		return otherValue, nil
+	}
+	nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
+	if exists {
+		otherValue, isType := nestedGenericValue.([]string)
+		if !isType {
+			return nil, incorrectTypeForFlagError(name, "[]string", nestedGenericValue)
+		}
+		return otherValue, nil
+	}
+
+	return nil, nil
+}
+
+// IntSlice returns an []int from the map if it exists otherwise returns nil
+func (fsm *MapInputSource) IntSlice(name string) ([]int, error) {
+	otherGenericValue, exists := fsm.valueMap[name]
+	if exists {
+		otherValue, isType := otherGenericValue.([]int)
+		if !isType {
+			return nil, incorrectTypeForFlagError(name, "[]int", otherGenericValue)
+		}
+		return otherValue, nil
+	}
+	nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
+	if exists {
+		otherValue, isType := nestedGenericValue.([]int)
+		if !isType {
+			return nil, incorrectTypeForFlagError(name, "[]int", nestedGenericValue)
+		}
+		return otherValue, nil
+	}
+
+	return nil, nil
+}
+
+// Generic returns an cli.Generic from the map if it exists otherwise returns nil
+func (fsm *MapInputSource) Generic(name string) (cli.Generic, error) {
+	otherGenericValue, exists := fsm.valueMap[name]
+	if exists {
+		otherValue, isType := otherGenericValue.(cli.Generic)
+		if !isType {
+			return nil, incorrectTypeForFlagError(name, "cli.Generic", otherGenericValue)
+		}
+		return otherValue, nil
+	}
+	nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
+	if exists {
+		otherValue, isType := nestedGenericValue.(cli.Generic)
+		if !isType {
+			return nil, incorrectTypeForFlagError(name, "cli.Generic", nestedGenericValue)
+		}
+		return otherValue, nil
+	}
+
+	return nil, nil
+}
+
+// Bool returns an bool from the map otherwise returns false
+func (fsm *MapInputSource) Bool(name string) (bool, error) {
+	otherGenericValue, exists := fsm.valueMap[name]
+	if exists {
+		otherValue, isType := otherGenericValue.(bool)
+		if !isType {
+			return false, incorrectTypeForFlagError(name, "bool", otherGenericValue)
+		}
+		return otherValue, nil
+	}
+	nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
+	if exists {
+		otherValue, isType := nestedGenericValue.(bool)
+		if !isType {
+			return false, incorrectTypeForFlagError(name, "bool", nestedGenericValue)
+		}
+		return otherValue, nil
+	}
+
+	return false, nil
+}
+
+// BoolT returns an bool from the map otherwise returns true
+func (fsm *MapInputSource) BoolT(name string) (bool, error) {
+	otherGenericValue, exists := fsm.valueMap[name]
+	if exists {
+		otherValue, isType := otherGenericValue.(bool)
+		if !isType {
+			return true, incorrectTypeForFlagError(name, "bool", otherGenericValue)
+		}
+		return otherValue, nil
+	}
+	nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
+	if exists {
+		otherValue, isType := nestedGenericValue.(bool)
+		if !isType {
+			return true, incorrectTypeForFlagError(name, "bool", nestedGenericValue)
+		}
+		return otherValue, nil
+	}
+
+	return true, nil
+}
+
+func incorrectTypeForFlagError(name, expectedTypeName string, value interface{}) error {
+	valueType := reflect.TypeOf(value)
+	valueTypeName := ""
+	if valueType != nil {
+		valueTypeName = valueType.Name()
+	}
+
+	return fmt.Errorf("Mismatched type for flag '%s'. Expected '%s' but actual is '%s'", name, expectedTypeName, valueTypeName)
+}

+ 313 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/altsrc/yaml_command_test.go

@@ -0,0 +1,313 @@
+// Disabling building of yaml support in cases where golang is 1.0 or 1.1
+// as the encoding library is not implemented or supported.
+
+// +build go1.2
+
+package altsrc
+
+import (
+	"flag"
+	"io/ioutil"
+	"os"
+	"testing"
+
+	"github.com/codegangsta/cli"
+)
+
+func TestCommandYamlFileTest(t *testing.T) {
+	app := cli.NewApp()
+	set := flag.NewFlagSet("test", 0)
+	ioutil.WriteFile("current.yaml", []byte("test: 15"), 0666)
+	defer os.Remove("current.yaml")
+	test := []string{"test-cmd", "--load", "current.yaml"}
+	set.Parse(test)
+
+	c := cli.NewContext(app, set, nil)
+
+	command := &cli.Command{
+		Name:        "test-cmd",
+		Aliases:     []string{"tc"},
+		Usage:       "this is for testing",
+		Description: "testing",
+		Action: func(c *cli.Context) error {
+			val := c.Int("test")
+			expect(t, val, 15)
+			return nil
+		},
+		Flags: []cli.Flag{
+			NewIntFlag(cli.IntFlag{Name: "test"}),
+			cli.StringFlag{Name: "load"}},
+	}
+	command.Before = InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load"))
+	err := command.Run(c)
+
+	expect(t, err, nil)
+}
+
+func TestCommandYamlFileTestGlobalEnvVarWins(t *testing.T) {
+	app := cli.NewApp()
+	set := flag.NewFlagSet("test", 0)
+	ioutil.WriteFile("current.yaml", []byte("test: 15"), 0666)
+	defer os.Remove("current.yaml")
+
+	os.Setenv("THE_TEST", "10")
+	defer os.Setenv("THE_TEST", "")
+	test := []string{"test-cmd", "--load", "current.yaml"}
+	set.Parse(test)
+
+	c := cli.NewContext(app, set, nil)
+
+	command := &cli.Command{
+		Name:        "test-cmd",
+		Aliases:     []string{"tc"},
+		Usage:       "this is for testing",
+		Description: "testing",
+		Action: func(c *cli.Context) error {
+			val := c.Int("test")
+			expect(t, val, 10)
+			return nil
+		},
+		Flags: []cli.Flag{
+			NewIntFlag(cli.IntFlag{Name: "test", EnvVar: "THE_TEST"}),
+			cli.StringFlag{Name: "load"}},
+	}
+	command.Before = InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load"))
+
+	err := command.Run(c)
+
+	expect(t, err, nil)
+}
+
+func TestCommandYamlFileTestGlobalEnvVarWinsNested(t *testing.T) {
+	app := cli.NewApp()
+	set := flag.NewFlagSet("test", 0)
+	ioutil.WriteFile("current.yaml", []byte(`top:
+  test: 15`), 0666)
+	defer os.Remove("current.yaml")
+
+	os.Setenv("THE_TEST", "10")
+	defer os.Setenv("THE_TEST", "")
+	test := []string{"test-cmd", "--load", "current.yaml"}
+	set.Parse(test)
+
+	c := cli.NewContext(app, set, nil)
+
+	command := &cli.Command{
+		Name:        "test-cmd",
+		Aliases:     []string{"tc"},
+		Usage:       "this is for testing",
+		Description: "testing",
+		Action: func(c *cli.Context) error {
+			val := c.Int("top.test")
+			expect(t, val, 10)
+			return nil
+		},
+		Flags: []cli.Flag{
+			NewIntFlag(cli.IntFlag{Name: "top.test", EnvVar: "THE_TEST"}),
+			cli.StringFlag{Name: "load"}},
+	}
+	command.Before = InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load"))
+
+	err := command.Run(c)
+
+	expect(t, err, nil)
+}
+
+func TestCommandYamlFileTestSpecifiedFlagWins(t *testing.T) {
+	app := cli.NewApp()
+	set := flag.NewFlagSet("test", 0)
+	ioutil.WriteFile("current.yaml", []byte("test: 15"), 0666)
+	defer os.Remove("current.yaml")
+
+	test := []string{"test-cmd", "--load", "current.yaml", "--test", "7"}
+	set.Parse(test)
+
+	c := cli.NewContext(app, set, nil)
+
+	command := &cli.Command{
+		Name:        "test-cmd",
+		Aliases:     []string{"tc"},
+		Usage:       "this is for testing",
+		Description: "testing",
+		Action: func(c *cli.Context) error {
+			val := c.Int("test")
+			expect(t, val, 7)
+			return nil
+		},
+		Flags: []cli.Flag{
+			NewIntFlag(cli.IntFlag{Name: "test"}),
+			cli.StringFlag{Name: "load"}},
+	}
+	command.Before = InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load"))
+
+	err := command.Run(c)
+
+	expect(t, err, nil)
+}
+
+func TestCommandYamlFileTestSpecifiedFlagWinsNested(t *testing.T) {
+	app := cli.NewApp()
+	set := flag.NewFlagSet("test", 0)
+	ioutil.WriteFile("current.yaml", []byte(`top:
+  test: 15`), 0666)
+	defer os.Remove("current.yaml")
+
+	test := []string{"test-cmd", "--load", "current.yaml", "--top.test", "7"}
+	set.Parse(test)
+
+	c := cli.NewContext(app, set, nil)
+
+	command := &cli.Command{
+		Name:        "test-cmd",
+		Aliases:     []string{"tc"},
+		Usage:       "this is for testing",
+		Description: "testing",
+		Action: func(c *cli.Context) error {
+			val := c.Int("top.test")
+			expect(t, val, 7)
+			return nil
+		},
+		Flags: []cli.Flag{
+			NewIntFlag(cli.IntFlag{Name: "top.test"}),
+			cli.StringFlag{Name: "load"}},
+	}
+	command.Before = InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load"))
+
+	err := command.Run(c)
+
+	expect(t, err, nil)
+}
+
+func TestCommandYamlFileTestDefaultValueFileWins(t *testing.T) {
+	app := cli.NewApp()
+	set := flag.NewFlagSet("test", 0)
+	ioutil.WriteFile("current.yaml", []byte("test: 15"), 0666)
+	defer os.Remove("current.yaml")
+
+	test := []string{"test-cmd", "--load", "current.yaml"}
+	set.Parse(test)
+
+	c := cli.NewContext(app, set, nil)
+
+	command := &cli.Command{
+		Name:        "test-cmd",
+		Aliases:     []string{"tc"},
+		Usage:       "this is for testing",
+		Description: "testing",
+		Action: func(c *cli.Context) error {
+			val := c.Int("test")
+			expect(t, val, 15)
+			return nil
+		},
+		Flags: []cli.Flag{
+			NewIntFlag(cli.IntFlag{Name: "test", Value: 7}),
+			cli.StringFlag{Name: "load"}},
+	}
+	command.Before = InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load"))
+
+	err := command.Run(c)
+
+	expect(t, err, nil)
+}
+
+func TestCommandYamlFileTestDefaultValueFileWinsNested(t *testing.T) {
+	app := cli.NewApp()
+	set := flag.NewFlagSet("test", 0)
+	ioutil.WriteFile("current.yaml", []byte(`top:
+  test: 15`), 0666)
+	defer os.Remove("current.yaml")
+
+	test := []string{"test-cmd", "--load", "current.yaml"}
+	set.Parse(test)
+
+	c := cli.NewContext(app, set, nil)
+
+	command := &cli.Command{
+		Name:        "test-cmd",
+		Aliases:     []string{"tc"},
+		Usage:       "this is for testing",
+		Description: "testing",
+		Action: func(c *cli.Context) error {
+			val := c.Int("top.test")
+			expect(t, val, 15)
+			return nil
+		},
+		Flags: []cli.Flag{
+			NewIntFlag(cli.IntFlag{Name: "top.test", Value: 7}),
+			cli.StringFlag{Name: "load"}},
+	}
+	command.Before = InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load"))
+
+	err := command.Run(c)
+
+	expect(t, err, nil)
+}
+
+func TestCommandYamlFileFlagHasDefaultGlobalEnvYamlSetGlobalEnvWins(t *testing.T) {
+	app := cli.NewApp()
+	set := flag.NewFlagSet("test", 0)
+	ioutil.WriteFile("current.yaml", []byte("test: 15"), 0666)
+	defer os.Remove("current.yaml")
+
+	os.Setenv("THE_TEST", "11")
+	defer os.Setenv("THE_TEST", "")
+
+	test := []string{"test-cmd", "--load", "current.yaml"}
+	set.Parse(test)
+
+	c := cli.NewContext(app, set, nil)
+
+	command := &cli.Command{
+		Name:        "test-cmd",
+		Aliases:     []string{"tc"},
+		Usage:       "this is for testing",
+		Description: "testing",
+		Action: func(c *cli.Context) error {
+			val := c.Int("test")
+			expect(t, val, 11)
+			return nil
+		},
+		Flags: []cli.Flag{
+			NewIntFlag(cli.IntFlag{Name: "test", Value: 7, EnvVar: "THE_TEST"}),
+			cli.StringFlag{Name: "load"}},
+	}
+	command.Before = InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load"))
+	err := command.Run(c)
+
+	expect(t, err, nil)
+}
+
+func TestCommandYamlFileFlagHasDefaultGlobalEnvYamlSetGlobalEnvWinsNested(t *testing.T) {
+	app := cli.NewApp()
+	set := flag.NewFlagSet("test", 0)
+	ioutil.WriteFile("current.yaml", []byte(`top:
+  test: 15`), 0666)
+	defer os.Remove("current.yaml")
+
+	os.Setenv("THE_TEST", "11")
+	defer os.Setenv("THE_TEST", "")
+
+	test := []string{"test-cmd", "--load", "current.yaml"}
+	set.Parse(test)
+
+	c := cli.NewContext(app, set, nil)
+
+	command := &cli.Command{
+		Name:        "test-cmd",
+		Aliases:     []string{"tc"},
+		Usage:       "this is for testing",
+		Description: "testing",
+		Action: func(c *cli.Context) error {
+			val := c.Int("top.test")
+			expect(t, val, 11)
+			return nil
+		},
+		Flags: []cli.Flag{
+			NewIntFlag(cli.IntFlag{Name: "top.test", Value: 7, EnvVar: "THE_TEST"}),
+			cli.StringFlag{Name: "load"}},
+	}
+	command.Before = InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load"))
+	err := command.Run(c)
+
+	expect(t, err, nil)
+}

+ 84 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/altsrc/yaml_file_loader.go

@@ -0,0 +1,84 @@
+// Disabling building of yaml support in cases where golang is 1.0 or 1.1
+// as the encoding library is not implemented or supported.
+
+// +build go1.2
+
+package altsrc
+
+import (
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"os"
+
+	"github.com/codegangsta/cli"
+
+	"gopkg.in/yaml.v2"
+)
+
+type yamlSourceContext struct {
+	FilePath string
+}
+
+// NewYamlSourceFromFile creates a new Yaml InputSourceContext from a filepath.
+func NewYamlSourceFromFile(file string) (InputSourceContext, error) {
+	ysc := &yamlSourceContext{FilePath: file}
+	var results map[interface{}]interface{}
+	err := readCommandYaml(ysc.FilePath, &results)
+	if err != nil {
+		return nil, fmt.Errorf("Unable to load Yaml file '%s': inner error: \n'%v'", ysc.FilePath, err.Error())
+	}
+
+	return &MapInputSource{valueMap: results}, nil
+}
+
+// NewYamlSourceFromFlagFunc creates a new Yaml InputSourceContext from a provided flag name and source context.
+func NewYamlSourceFromFlagFunc(flagFileName string) func(context *cli.Context) (InputSourceContext, error) {
+	return func(context *cli.Context) (InputSourceContext, error) {
+		filePath := context.String(flagFileName)
+		return NewYamlSourceFromFile(filePath)
+	}
+}
+
+func readCommandYaml(filePath string, container interface{}) (err error) {
+	b, err := loadDataFrom(filePath)
+	if err != nil {
+		return err
+	}
+
+	err = yaml.Unmarshal(b, container)
+	if err != nil {
+		return err
+	}
+
+	err = nil
+	return
+}
+
+func loadDataFrom(filePath string) ([]byte, error) {
+	u, err := url.Parse(filePath)
+	if err != nil {
+		return nil, err
+	}
+
+	if u.Host != "" { // i have a host, now do i support the scheme?
+		switch u.Scheme {
+		case "http", "https":
+			res, err := http.Get(filePath)
+			if err != nil {
+				return nil, err
+			}
+			return ioutil.ReadAll(res.Body)
+		default:
+			return nil, fmt.Errorf("scheme of %s is unsupported", filePath)
+		}
+	} else if u.Path != "" { // i dont have a host, but I have a path. I am a local file.
+		if _, notFoundFileErr := os.Stat(filePath); notFoundFileErr != nil {
+			return nil, fmt.Errorf("Cannot read from file: '%s' because it does not exist.", filePath)
+		}
+		return ioutil.ReadFile(filePath)
+	} else {
+		return nil, fmt.Errorf("unable to determine how to load from path %s", filePath)
+	}
+}

+ 498 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/app.go

@@ -0,0 +1,498 @@
+package cli
+
+import (
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"reflect"
+	"sort"
+	"time"
+)
+
+var (
+	changeLogURL                    = "https://github.com/codegangsta/cli/blob/master/CHANGELOG.md"
+	appActionDeprecationURL         = fmt.Sprintf("%s#deprecated-cli-app-action-signature", changeLogURL)
+	runAndExitOnErrorDeprecationURL = fmt.Sprintf("%s#deprecated-cli-app-runandexitonerror", changeLogURL)
+
+	contactSysadmin = "This is an error in the application.  Please contact the distributor of this application if this is not you."
+
+	errNonFuncAction = NewExitError("ERROR invalid Action type.  "+
+		fmt.Sprintf("Must be a func of type `cli.ActionFunc`.  %s", contactSysadmin)+
+		fmt.Sprintf("See %s", appActionDeprecationURL), 2)
+	errInvalidActionSignature = NewExitError("ERROR invalid Action signature.  "+
+		fmt.Sprintf("Must be `cli.ActionFunc`.  %s", contactSysadmin)+
+		fmt.Sprintf("See %s", appActionDeprecationURL), 2)
+)
+
+// App is the main structure of a cli application. It is recommended that
+// an app be created with the cli.NewApp() function
+type App struct {
+	// The name of the program. Defaults to path.Base(os.Args[0])
+	Name string
+	// Full name of command for help, defaults to Name
+	HelpName string
+	// Description of the program.
+	Usage string
+	// Text to override the USAGE section of help
+	UsageText string
+	// Description of the program argument format.
+	ArgsUsage string
+	// Version of the program
+	Version string
+	// List of commands to execute
+	Commands []Command
+	// List of flags to parse
+	Flags []Flag
+	// Boolean to enable bash completion commands
+	EnableBashCompletion bool
+	// Boolean to hide built-in help command
+	HideHelp bool
+	// Boolean to hide built-in version flag and the VERSION section of help
+	HideVersion bool
+	// Populate on app startup, only gettable through method Categories()
+	categories CommandCategories
+	// An action to execute when the bash-completion flag is set
+	BashComplete BashCompleteFunc
+	// An action to execute before any subcommands are run, but after the context is ready
+	// If a non-nil error is returned, no subcommands are run
+	Before BeforeFunc
+	// An action to execute after any subcommands are run, but after the subcommand has finished
+	// It is run even if Action() panics
+	After AfterFunc
+	// The action to execute when no subcommands are specified
+	Action interface{}
+	// TODO: replace `Action: interface{}` with `Action: ActionFunc` once some kind
+	// of deprecation period has passed, maybe?
+
+	// Execute this function if the proper command cannot be found
+	CommandNotFound CommandNotFoundFunc
+	// Execute this function if an usage error occurs
+	OnUsageError OnUsageErrorFunc
+	// Compilation date
+	Compiled time.Time
+	// List of all authors who contributed
+	Authors []Author
+	// Copyright of the binary if any
+	Copyright string
+	// Name of Author (Note: Use App.Authors, this is deprecated)
+	Author string
+	// Email of Author (Note: Use App.Authors, this is deprecated)
+	Email string
+	// Writer writer to write output to
+	Writer io.Writer
+	// ErrWriter writes error output
+	ErrWriter io.Writer
+	// Other custom info
+	Metadata map[string]interface{}
+
+	didSetup bool
+}
+
+// Tries to find out when this binary was compiled.
+// Returns the current time if it fails to find it.
+func compileTime() time.Time {
+	info, err := os.Stat(os.Args[0])
+	if err != nil {
+		return time.Now()
+	}
+	return info.ModTime()
+}
+
+// NewApp creates a new cli Application with some reasonable defaults for Name,
+// Usage, Version and Action.
+func NewApp() *App {
+	return &App{
+		Name:         filepath.Base(os.Args[0]),
+		HelpName:     filepath.Base(os.Args[0]),
+		Usage:        "A new cli application",
+		UsageText:    "",
+		Version:      "0.0.0",
+		BashComplete: DefaultAppComplete,
+		Action:       helpCommand.Action,
+		Compiled:     compileTime(),
+		Writer:       os.Stdout,
+	}
+}
+
+// Setup runs initialization code to ensure all data structures are ready for
+// `Run` or inspection prior to `Run`.  It is internally called by `Run`, but
+// will return early if setup has already happened.
+func (a *App) Setup() {
+	if a.didSetup {
+		return
+	}
+
+	a.didSetup = true
+
+	if a.Author != "" || a.Email != "" {
+		a.Authors = append(a.Authors, Author{Name: a.Author, Email: a.Email})
+	}
+
+	newCmds := []Command{}
+	for _, c := range a.Commands {
+		if c.HelpName == "" {
+			c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name)
+		}
+		newCmds = append(newCmds, c)
+	}
+	a.Commands = newCmds
+
+	a.categories = CommandCategories{}
+	for _, command := range a.Commands {
+		a.categories = a.categories.AddCommand(command.Category, command)
+	}
+	sort.Sort(a.categories)
+
+	// append help to commands
+	if a.Command(helpCommand.Name) == nil && !a.HideHelp {
+		a.Commands = append(a.Commands, helpCommand)
+		if (HelpFlag != BoolFlag{}) {
+			a.appendFlag(HelpFlag)
+		}
+	}
+
+	//append version/help flags
+	if a.EnableBashCompletion {
+		a.appendFlag(BashCompletionFlag)
+	}
+
+	if !a.HideVersion {
+		a.appendFlag(VersionFlag)
+	}
+}
+
+// Run is the entry point to the cli app. Parses the arguments slice and routes
+// to the proper flag/args combination
+func (a *App) Run(arguments []string) (err error) {
+	a.Setup()
+
+	// parse flags
+	set := flagSet(a.Name, a.Flags)
+	set.SetOutput(ioutil.Discard)
+	err = set.Parse(arguments[1:])
+	nerr := normalizeFlags(a.Flags, set)
+	context := NewContext(a, set, nil)
+	if nerr != nil {
+		fmt.Fprintln(a.Writer, nerr)
+		ShowAppHelp(context)
+		return nerr
+	}
+
+	if checkCompletions(context) {
+		return nil
+	}
+
+	if err != nil {
+		if a.OnUsageError != nil {
+			err := a.OnUsageError(context, err, false)
+			HandleExitCoder(err)
+			return err
+		}
+		fmt.Fprintf(a.Writer, "%s\n\n", "Incorrect Usage.")
+		ShowAppHelp(context)
+		return err
+	}
+
+	if !a.HideHelp && checkHelp(context) {
+		ShowAppHelp(context)
+		return nil
+	}
+
+	if !a.HideVersion && checkVersion(context) {
+		ShowVersion(context)
+		return nil
+	}
+
+	if a.After != nil {
+		defer func() {
+			if afterErr := a.After(context); afterErr != nil {
+				if err != nil {
+					err = NewMultiError(err, afterErr)
+				} else {
+					err = afterErr
+				}
+			}
+		}()
+	}
+
+	if a.Before != nil {
+		beforeErr := a.Before(context)
+		if beforeErr != nil {
+			fmt.Fprintf(a.Writer, "%v\n\n", beforeErr)
+			ShowAppHelp(context)
+			HandleExitCoder(beforeErr)
+			err = beforeErr
+			return err
+		}
+	}
+
+	args := context.Args()
+	if args.Present() {
+		name := args.First()
+		c := a.Command(name)
+		if c != nil {
+			return c.Run(context)
+		}
+	}
+
+	// Run default Action
+	err = HandleAction(a.Action, context)
+
+	HandleExitCoder(err)
+	return err
+}
+
+// DEPRECATED: Another entry point to the cli app, takes care of passing arguments and error handling
+func (a *App) RunAndExitOnError() {
+	fmt.Fprintf(a.errWriter(),
+		"DEPRECATED cli.App.RunAndExitOnError.  %s  See %s\n",
+		contactSysadmin, runAndExitOnErrorDeprecationURL)
+	if err := a.Run(os.Args); err != nil {
+		fmt.Fprintln(a.errWriter(), err)
+		OsExiter(1)
+	}
+}
+
+// RunAsSubcommand invokes the subcommand given the context, parses ctx.Args() to
+// generate command-specific flags
+func (a *App) RunAsSubcommand(ctx *Context) (err error) {
+	// append help to commands
+	if len(a.Commands) > 0 {
+		if a.Command(helpCommand.Name) == nil && !a.HideHelp {
+			a.Commands = append(a.Commands, helpCommand)
+			if (HelpFlag != BoolFlag{}) {
+				a.appendFlag(HelpFlag)
+			}
+		}
+	}
+
+	newCmds := []Command{}
+	for _, c := range a.Commands {
+		if c.HelpName == "" {
+			c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name)
+		}
+		newCmds = append(newCmds, c)
+	}
+	a.Commands = newCmds
+
+	// append flags
+	if a.EnableBashCompletion {
+		a.appendFlag(BashCompletionFlag)
+	}
+
+	// parse flags
+	set := flagSet(a.Name, a.Flags)
+	set.SetOutput(ioutil.Discard)
+	err = set.Parse(ctx.Args().Tail())
+	nerr := normalizeFlags(a.Flags, set)
+	context := NewContext(a, set, ctx)
+
+	if nerr != nil {
+		fmt.Fprintln(a.Writer, nerr)
+		fmt.Fprintln(a.Writer)
+		if len(a.Commands) > 0 {
+			ShowSubcommandHelp(context)
+		} else {
+			ShowCommandHelp(ctx, context.Args().First())
+		}
+		return nerr
+	}
+
+	if checkCompletions(context) {
+		return nil
+	}
+
+	if err != nil {
+		if a.OnUsageError != nil {
+			err = a.OnUsageError(context, err, true)
+			HandleExitCoder(err)
+			return err
+		}
+		fmt.Fprintf(a.Writer, "%s\n\n", "Incorrect Usage.")
+		ShowSubcommandHelp(context)
+		return err
+	}
+
+	if len(a.Commands) > 0 {
+		if checkSubcommandHelp(context) {
+			return nil
+		}
+	} else {
+		if checkCommandHelp(ctx, context.Args().First()) {
+			return nil
+		}
+	}
+
+	if a.After != nil {
+		defer func() {
+			afterErr := a.After(context)
+			if afterErr != nil {
+				HandleExitCoder(err)
+				if err != nil {
+					err = NewMultiError(err, afterErr)
+				} else {
+					err = afterErr
+				}
+			}
+		}()
+	}
+
+	if a.Before != nil {
+		beforeErr := a.Before(context)
+		if beforeErr != nil {
+			HandleExitCoder(beforeErr)
+			err = beforeErr
+			return err
+		}
+	}
+
+	args := context.Args()
+	if args.Present() {
+		name := args.First()
+		c := a.Command(name)
+		if c != nil {
+			return c.Run(context)
+		}
+	}
+
+	// Run default Action
+	err = HandleAction(a.Action, context)
+
+	HandleExitCoder(err)
+	return err
+}
+
+// Command returns the named command on App. Returns nil if the command does not exist
+func (a *App) Command(name string) *Command {
+	for _, c := range a.Commands {
+		if c.HasName(name) {
+			return &c
+		}
+	}
+
+	return nil
+}
+
+// Categories returns a slice containing all the categories with the commands they contain
+func (a *App) Categories() CommandCategories {
+	return a.categories
+}
+
+// VisibleCategories returns a slice of categories and commands that are
+// Hidden=false
+func (a *App) VisibleCategories() []*CommandCategory {
+	ret := []*CommandCategory{}
+	for _, category := range a.categories {
+		if visible := func() *CommandCategory {
+			for _, command := range category.Commands {
+				if !command.Hidden {
+					return category
+				}
+			}
+			return nil
+		}(); visible != nil {
+			ret = append(ret, visible)
+		}
+	}
+	return ret
+}
+
+// VisibleCommands returns a slice of the Commands with Hidden=false
+func (a *App) VisibleCommands() []Command {
+	ret := []Command{}
+	for _, command := range a.Commands {
+		if !command.Hidden {
+			ret = append(ret, command)
+		}
+	}
+	return ret
+}
+
+// VisibleFlags returns a slice of the Flags with Hidden=false
+func (a *App) VisibleFlags() []Flag {
+	return visibleFlags(a.Flags)
+}
+
+func (a *App) hasFlag(flag Flag) bool {
+	for _, f := range a.Flags {
+		if flag == f {
+			return true
+		}
+	}
+
+	return false
+}
+
+func (a *App) errWriter() io.Writer {
+
+	// When the app ErrWriter is nil use the package level one.
+	if a.ErrWriter == nil {
+		return ErrWriter
+	}
+
+	return a.ErrWriter
+}
+
+func (a *App) appendFlag(flag Flag) {
+	if !a.hasFlag(flag) {
+		a.Flags = append(a.Flags, flag)
+	}
+}
+
+// Author represents someone who has contributed to a cli project.
+type Author struct {
+	Name  string // The Authors name
+	Email string // The Authors email
+}
+
+// String makes Author comply to the Stringer interface, to allow an easy print in the templating process
+func (a Author) String() string {
+	e := ""
+	if a.Email != "" {
+		e = "<" + a.Email + "> "
+	}
+
+	return fmt.Sprintf("%v %v", a.Name, e)
+}
+
+// HandleAction uses ✧✧✧reflection✧✧✧ to figure out if the given Action is an
+// ActionFunc, a func with the legacy signature for Action, or some other
+// invalid thing.  If it's an ActionFunc or a func with the legacy signature for
+// Action, the func is run!
+func HandleAction(action interface{}, context *Context) (err error) {
+	defer func() {
+		if r := recover(); r != nil {
+			switch r.(type) {
+			case error:
+				err = r.(error)
+			default:
+				err = NewExitError(fmt.Sprintf("ERROR unknown Action error: %v. See %s", r, appActionDeprecationURL), 2)
+			}
+		}
+	}()
+
+	if reflect.TypeOf(action).Kind() != reflect.Func {
+		return errNonFuncAction
+	}
+
+	vals := reflect.ValueOf(action).Call([]reflect.Value{reflect.ValueOf(context)})
+
+	if len(vals) == 0 {
+		fmt.Fprintf(ErrWriter,
+			"DEPRECATED Action signature.  Must be `cli.ActionFunc`.  %s  See %s\n",
+			contactSysadmin, appActionDeprecationURL)
+		return nil
+	}
+
+	if len(vals) > 1 {
+		return errInvalidActionSignature
+	}
+
+	if retErr, ok := vals[0].Interface().(error); vals[0].IsValid() && ok {
+		return retErr
+	}
+
+	return err
+}

+ 1454 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/app_test.go

@@ -0,0 +1,1454 @@
+package cli
+
+import (
+	"bytes"
+	"errors"
+	"flag"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"reflect"
+	"strings"
+	"testing"
+)
+
+type opCounts struct {
+	Total, BashComplete, OnUsageError, Before, CommandNotFound, Action, After, SubCommand int
+}
+
+func ExampleApp_Run() {
+	// set args for examples sake
+	os.Args = []string{"greet", "--name", "Jeremy"}
+
+	app := NewApp()
+	app.Name = "greet"
+	app.Flags = []Flag{
+		StringFlag{Name: "name", Value: "bob", Usage: "a name to say"},
+	}
+	app.Action = func(c *Context) error {
+		fmt.Printf("Hello %v\n", c.String("name"))
+		return nil
+	}
+	app.UsageText = "app [first_arg] [second_arg]"
+	app.Author = "Harrison"
+	app.Email = "[email protected]"
+	app.Authors = []Author{{Name: "Oliver Allen", Email: "[email protected]"}}
+	app.Run(os.Args)
+	// Output:
+	// Hello Jeremy
+}
+
+func ExampleApp_Run_subcommand() {
+	// set args for examples sake
+	os.Args = []string{"say", "hi", "english", "--name", "Jeremy"}
+	app := NewApp()
+	app.Name = "say"
+	app.Commands = []Command{
+		{
+			Name:        "hello",
+			Aliases:     []string{"hi"},
+			Usage:       "use it to see a description",
+			Description: "This is how we describe hello the function",
+			Subcommands: []Command{
+				{
+					Name:        "english",
+					Aliases:     []string{"en"},
+					Usage:       "sends a greeting in english",
+					Description: "greets someone in english",
+					Flags: []Flag{
+						StringFlag{
+							Name:  "name",
+							Value: "Bob",
+							Usage: "Name of the person to greet",
+						},
+					},
+					Action: func(c *Context) error {
+						fmt.Println("Hello,", c.String("name"))
+						return nil
+					},
+				},
+			},
+		},
+	}
+
+	app.Run(os.Args)
+	// Output:
+	// Hello, Jeremy
+}
+
+func ExampleApp_Run_help() {
+	// set args for examples sake
+	os.Args = []string{"greet", "h", "describeit"}
+
+	app := NewApp()
+	app.Name = "greet"
+	app.Flags = []Flag{
+		StringFlag{Name: "name", Value: "bob", Usage: "a name to say"},
+	}
+	app.Commands = []Command{
+		{
+			Name:        "describeit",
+			Aliases:     []string{"d"},
+			Usage:       "use it to see a description",
+			Description: "This is how we describe describeit the function",
+			Action: func(c *Context) error {
+				fmt.Printf("i like to describe things")
+				return nil
+			},
+		},
+	}
+	app.Run(os.Args)
+	// Output:
+	// NAME:
+	//    greet describeit - use it to see a description
+	//
+	// USAGE:
+	//    greet describeit [arguments...]
+	//
+	// DESCRIPTION:
+	//    This is how we describe describeit the function
+}
+
+func ExampleApp_Run_bashComplete() {
+	// set args for examples sake
+	os.Args = []string{"greet", "--generate-bash-completion"}
+
+	app := NewApp()
+	app.Name = "greet"
+	app.EnableBashCompletion = true
+	app.Commands = []Command{
+		{
+			Name:        "describeit",
+			Aliases:     []string{"d"},
+			Usage:       "use it to see a description",
+			Description: "This is how we describe describeit the function",
+			Action: func(c *Context) error {
+				fmt.Printf("i like to describe things")
+				return nil
+			},
+		}, {
+			Name:        "next",
+			Usage:       "next example",
+			Description: "more stuff to see when generating bash completion",
+			Action: func(c *Context) error {
+				fmt.Printf("the next example")
+				return nil
+			},
+		},
+	}
+
+	app.Run(os.Args)
+	// Output:
+	// describeit
+	// d
+	// next
+	// help
+	// h
+}
+
+func TestApp_Run(t *testing.T) {
+	s := ""
+
+	app := NewApp()
+	app.Action = func(c *Context) error {
+		s = s + c.Args().First()
+		return nil
+	}
+
+	err := app.Run([]string{"command", "foo"})
+	expect(t, err, nil)
+	err = app.Run([]string{"command", "bar"})
+	expect(t, err, nil)
+	expect(t, s, "foobar")
+}
+
+var commandAppTests = []struct {
+	name     string
+	expected bool
+}{
+	{"foobar", true},
+	{"batbaz", true},
+	{"b", true},
+	{"f", true},
+	{"bat", false},
+	{"nothing", false},
+}
+
+func TestApp_Command(t *testing.T) {
+	app := NewApp()
+	fooCommand := Command{Name: "foobar", Aliases: []string{"f"}}
+	batCommand := Command{Name: "batbaz", Aliases: []string{"b"}}
+	app.Commands = []Command{
+		fooCommand,
+		batCommand,
+	}
+
+	for _, test := range commandAppTests {
+		expect(t, app.Command(test.name) != nil, test.expected)
+	}
+}
+
+func TestApp_CommandWithArgBeforeFlags(t *testing.T) {
+	var parsedOption, firstArg string
+
+	app := NewApp()
+	command := Command{
+		Name: "cmd",
+		Flags: []Flag{
+			StringFlag{Name: "option", Value: "", Usage: "some option"},
+		},
+		Action: func(c *Context) error {
+			parsedOption = c.String("option")
+			firstArg = c.Args().First()
+			return nil
+		},
+	}
+	app.Commands = []Command{command}
+
+	app.Run([]string{"", "cmd", "my-arg", "--option", "my-option"})
+
+	expect(t, parsedOption, "my-option")
+	expect(t, firstArg, "my-arg")
+}
+
+func TestApp_RunAsSubcommandParseFlags(t *testing.T) {
+	var context *Context
+
+	a := NewApp()
+	a.Commands = []Command{
+		{
+			Name: "foo",
+			Action: func(c *Context) error {
+				context = c
+				return nil
+			},
+			Flags: []Flag{
+				StringFlag{
+					Name:  "lang",
+					Value: "english",
+					Usage: "language for the greeting",
+				},
+			},
+			Before: func(_ *Context) error { return nil },
+		},
+	}
+	a.Run([]string{"", "foo", "--lang", "spanish", "abcd"})
+
+	expect(t, context.Args().Get(0), "abcd")
+	expect(t, context.String("lang"), "spanish")
+}
+
+func TestApp_CommandWithFlagBeforeTerminator(t *testing.T) {
+	var parsedOption string
+	var args []string
+
+	app := NewApp()
+	command := Command{
+		Name: "cmd",
+		Flags: []Flag{
+			StringFlag{Name: "option", Value: "", Usage: "some option"},
+		},
+		Action: func(c *Context) error {
+			parsedOption = c.String("option")
+			args = c.Args()
+			return nil
+		},
+	}
+	app.Commands = []Command{command}
+
+	app.Run([]string{"", "cmd", "my-arg", "--option", "my-option", "--", "--notARealFlag"})
+
+	expect(t, parsedOption, "my-option")
+	expect(t, args[0], "my-arg")
+	expect(t, args[1], "--")
+	expect(t, args[2], "--notARealFlag")
+}
+
+func TestApp_CommandWithDash(t *testing.T) {
+	var args []string
+
+	app := NewApp()
+	command := Command{
+		Name: "cmd",
+		Action: func(c *Context) error {
+			args = c.Args()
+			return nil
+		},
+	}
+	app.Commands = []Command{command}
+
+	app.Run([]string{"", "cmd", "my-arg", "-"})
+
+	expect(t, args[0], "my-arg")
+	expect(t, args[1], "-")
+}
+
+func TestApp_CommandWithNoFlagBeforeTerminator(t *testing.T) {
+	var args []string
+
+	app := NewApp()
+	command := Command{
+		Name: "cmd",
+		Action: func(c *Context) error {
+			args = c.Args()
+			return nil
+		},
+	}
+	app.Commands = []Command{command}
+
+	app.Run([]string{"", "cmd", "my-arg", "--", "notAFlagAtAll"})
+
+	expect(t, args[0], "my-arg")
+	expect(t, args[1], "--")
+	expect(t, args[2], "notAFlagAtAll")
+}
+
+func TestApp_VisibleCommands(t *testing.T) {
+	app := NewApp()
+	app.Commands = []Command{
+		{
+			Name:     "frob",
+			HelpName: "foo frob",
+			Action:   func(_ *Context) error { return nil },
+		},
+		{
+			Name:     "frib",
+			HelpName: "foo frib",
+			Hidden:   true,
+			Action:   func(_ *Context) error { return nil },
+		},
+	}
+
+	app.Setup()
+	expected := []Command{
+		app.Commands[0],
+		app.Commands[2], // help
+	}
+	actual := app.VisibleCommands()
+	expect(t, len(expected), len(actual))
+	for i, actualCommand := range actual {
+		expectedCommand := expected[i]
+
+		if expectedCommand.Action != nil {
+			// comparing func addresses is OK!
+			expect(t, fmt.Sprintf("%p", expectedCommand.Action), fmt.Sprintf("%p", actualCommand.Action))
+		}
+
+		// nil out funcs, as they cannot be compared
+		// (https://github.com/golang/go/issues/8554)
+		expectedCommand.Action = nil
+		actualCommand.Action = nil
+
+		if !reflect.DeepEqual(expectedCommand, actualCommand) {
+			t.Errorf("expected\n%#v\n!=\n%#v", expectedCommand, actualCommand)
+		}
+	}
+}
+
+func TestApp_Float64Flag(t *testing.T) {
+	var meters float64
+
+	app := NewApp()
+	app.Flags = []Flag{
+		Float64Flag{Name: "height", Value: 1.5, Usage: "Set the height, in meters"},
+	}
+	app.Action = func(c *Context) error {
+		meters = c.Float64("height")
+		return nil
+	}
+
+	app.Run([]string{"", "--height", "1.93"})
+	expect(t, meters, 1.93)
+}
+
+func TestApp_ParseSliceFlags(t *testing.T) {
+	var parsedOption, firstArg string
+	var parsedIntSlice []int
+	var parsedStringSlice []string
+
+	app := NewApp()
+	command := Command{
+		Name: "cmd",
+		Flags: []Flag{
+			IntSliceFlag{Name: "p", Value: &IntSlice{}, Usage: "set one or more ip addr"},
+			StringSliceFlag{Name: "ip", Value: &StringSlice{}, Usage: "set one or more ports to open"},
+		},
+		Action: func(c *Context) error {
+			parsedIntSlice = c.IntSlice("p")
+			parsedStringSlice = c.StringSlice("ip")
+			parsedOption = c.String("option")
+			firstArg = c.Args().First()
+			return nil
+		},
+	}
+	app.Commands = []Command{command}
+
+	app.Run([]string{"", "cmd", "my-arg", "-p", "22", "-p", "80", "-ip", "8.8.8.8", "-ip", "8.8.4.4"})
+
+	IntsEquals := func(a, b []int) bool {
+		if len(a) != len(b) {
+			return false
+		}
+		for i, v := range a {
+			if v != b[i] {
+				return false
+			}
+		}
+		return true
+	}
+
+	StrsEquals := func(a, b []string) bool {
+		if len(a) != len(b) {
+			return false
+		}
+		for i, v := range a {
+			if v != b[i] {
+				return false
+			}
+		}
+		return true
+	}
+	var expectedIntSlice = []int{22, 80}
+	var expectedStringSlice = []string{"8.8.8.8", "8.8.4.4"}
+
+	if !IntsEquals(parsedIntSlice, expectedIntSlice) {
+		t.Errorf("%v does not match %v", parsedIntSlice, expectedIntSlice)
+	}
+
+	if !StrsEquals(parsedStringSlice, expectedStringSlice) {
+		t.Errorf("%v does not match %v", parsedStringSlice, expectedStringSlice)
+	}
+}
+
+func TestApp_ParseSliceFlagsWithMissingValue(t *testing.T) {
+	var parsedIntSlice []int
+	var parsedStringSlice []string
+
+	app := NewApp()
+	command := Command{
+		Name: "cmd",
+		Flags: []Flag{
+			IntSliceFlag{Name: "a", Usage: "set numbers"},
+			StringSliceFlag{Name: "str", Usage: "set strings"},
+		},
+		Action: func(c *Context) error {
+			parsedIntSlice = c.IntSlice("a")
+			parsedStringSlice = c.StringSlice("str")
+			return nil
+		},
+	}
+	app.Commands = []Command{command}
+
+	app.Run([]string{"", "cmd", "my-arg", "-a", "2", "-str", "A"})
+
+	var expectedIntSlice = []int{2}
+	var expectedStringSlice = []string{"A"}
+
+	if parsedIntSlice[0] != expectedIntSlice[0] {
+		t.Errorf("%v does not match %v", parsedIntSlice[0], expectedIntSlice[0])
+	}
+
+	if parsedStringSlice[0] != expectedStringSlice[0] {
+		t.Errorf("%v does not match %v", parsedIntSlice[0], expectedIntSlice[0])
+	}
+}
+
+func TestApp_DefaultStdout(t *testing.T) {
+	app := NewApp()
+
+	if app.Writer != os.Stdout {
+		t.Error("Default output writer not set.")
+	}
+}
+
+type mockWriter struct {
+	written []byte
+}
+
+func (fw *mockWriter) Write(p []byte) (n int, err error) {
+	if fw.written == nil {
+		fw.written = p
+	} else {
+		fw.written = append(fw.written, p...)
+	}
+
+	return len(p), nil
+}
+
+func (fw *mockWriter) GetWritten() (b []byte) {
+	return fw.written
+}
+
+func TestApp_SetStdout(t *testing.T) {
+	w := &mockWriter{}
+
+	app := NewApp()
+	app.Name = "test"
+	app.Writer = w
+
+	err := app.Run([]string{"help"})
+
+	if err != nil {
+		t.Fatalf("Run error: %s", err)
+	}
+
+	if len(w.written) == 0 {
+		t.Error("App did not write output to desired writer.")
+	}
+}
+
+func TestApp_BeforeFunc(t *testing.T) {
+	counts := &opCounts{}
+	beforeError := fmt.Errorf("fail")
+	var err error
+
+	app := NewApp()
+
+	app.Before = func(c *Context) error {
+		counts.Total++
+		counts.Before = counts.Total
+		s := c.String("opt")
+		if s == "fail" {
+			return beforeError
+		}
+
+		return nil
+	}
+
+	app.Commands = []Command{
+		{
+			Name: "sub",
+			Action: func(c *Context) error {
+				counts.Total++
+				counts.SubCommand = counts.Total
+				return nil
+			},
+		},
+	}
+
+	app.Flags = []Flag{
+		StringFlag{Name: "opt"},
+	}
+
+	// run with the Before() func succeeding
+	err = app.Run([]string{"command", "--opt", "succeed", "sub"})
+
+	if err != nil {
+		t.Fatalf("Run error: %s", err)
+	}
+
+	if counts.Before != 1 {
+		t.Errorf("Before() not executed when expected")
+	}
+
+	if counts.SubCommand != 2 {
+		t.Errorf("Subcommand not executed when expected")
+	}
+
+	// reset
+	counts = &opCounts{}
+
+	// run with the Before() func failing
+	err = app.Run([]string{"command", "--opt", "fail", "sub"})
+
+	// should be the same error produced by the Before func
+	if err != beforeError {
+		t.Errorf("Run error expected, but not received")
+	}
+
+	if counts.Before != 1 {
+		t.Errorf("Before() not executed when expected")
+	}
+
+	if counts.SubCommand != 0 {
+		t.Errorf("Subcommand executed when NOT expected")
+	}
+
+	// reset
+	counts = &opCounts{}
+
+	afterError := errors.New("fail again")
+	app.After = func(_ *Context) error {
+		return afterError
+	}
+
+	// run with the Before() func failing, wrapped by After()
+	err = app.Run([]string{"command", "--opt", "fail", "sub"})
+
+	// should be the same error produced by the Before func
+	if _, ok := err.(MultiError); !ok {
+		t.Errorf("MultiError expected, but not received")
+	}
+
+	if counts.Before != 1 {
+		t.Errorf("Before() not executed when expected")
+	}
+
+	if counts.SubCommand != 0 {
+		t.Errorf("Subcommand executed when NOT expected")
+	}
+}
+
+func TestApp_AfterFunc(t *testing.T) {
+	counts := &opCounts{}
+	afterError := fmt.Errorf("fail")
+	var err error
+
+	app := NewApp()
+
+	app.After = func(c *Context) error {
+		counts.Total++
+		counts.After = counts.Total
+		s := c.String("opt")
+		if s == "fail" {
+			return afterError
+		}
+
+		return nil
+	}
+
+	app.Commands = []Command{
+		{
+			Name: "sub",
+			Action: func(c *Context) error {
+				counts.Total++
+				counts.SubCommand = counts.Total
+				return nil
+			},
+		},
+	}
+
+	app.Flags = []Flag{
+		StringFlag{Name: "opt"},
+	}
+
+	// run with the After() func succeeding
+	err = app.Run([]string{"command", "--opt", "succeed", "sub"})
+
+	if err != nil {
+		t.Fatalf("Run error: %s", err)
+	}
+
+	if counts.After != 2 {
+		t.Errorf("After() not executed when expected")
+	}
+
+	if counts.SubCommand != 1 {
+		t.Errorf("Subcommand not executed when expected")
+	}
+
+	// reset
+	counts = &opCounts{}
+
+	// run with the Before() func failing
+	err = app.Run([]string{"command", "--opt", "fail", "sub"})
+
+	// should be the same error produced by the Before func
+	if err != afterError {
+		t.Errorf("Run error expected, but not received")
+	}
+
+	if counts.After != 2 {
+		t.Errorf("After() not executed when expected")
+	}
+
+	if counts.SubCommand != 1 {
+		t.Errorf("Subcommand not executed when expected")
+	}
+}
+
+func TestAppNoHelpFlag(t *testing.T) {
+	oldFlag := HelpFlag
+	defer func() {
+		HelpFlag = oldFlag
+	}()
+
+	HelpFlag = BoolFlag{}
+
+	app := NewApp()
+	app.Writer = ioutil.Discard
+	err := app.Run([]string{"test", "-h"})
+
+	if err != flag.ErrHelp {
+		t.Errorf("expected error about missing help flag, but got: %s (%T)", err, err)
+	}
+}
+
+func TestAppHelpPrinter(t *testing.T) {
+	oldPrinter := HelpPrinter
+	defer func() {
+		HelpPrinter = oldPrinter
+	}()
+
+	var wasCalled = false
+	HelpPrinter = func(w io.Writer, template string, data interface{}) {
+		wasCalled = true
+	}
+
+	app := NewApp()
+	app.Run([]string{"-h"})
+
+	if wasCalled == false {
+		t.Errorf("Help printer expected to be called, but was not")
+	}
+}
+
+func TestApp_VersionPrinter(t *testing.T) {
+	oldPrinter := VersionPrinter
+	defer func() {
+		VersionPrinter = oldPrinter
+	}()
+
+	var wasCalled = false
+	VersionPrinter = func(c *Context) {
+		wasCalled = true
+	}
+
+	app := NewApp()
+	ctx := NewContext(app, nil, nil)
+	ShowVersion(ctx)
+
+	if wasCalled == false {
+		t.Errorf("Version printer expected to be called, but was not")
+	}
+}
+
+func TestApp_CommandNotFound(t *testing.T) {
+	counts := &opCounts{}
+	app := NewApp()
+
+	app.CommandNotFound = func(c *Context, command string) {
+		counts.Total++
+		counts.CommandNotFound = counts.Total
+	}
+
+	app.Commands = []Command{
+		{
+			Name: "bar",
+			Action: func(c *Context) error {
+				counts.Total++
+				counts.SubCommand = counts.Total
+				return nil
+			},
+		},
+	}
+
+	app.Run([]string{"command", "foo"})
+
+	expect(t, counts.CommandNotFound, 1)
+	expect(t, counts.SubCommand, 0)
+	expect(t, counts.Total, 1)
+}
+
+func TestApp_OrderOfOperations(t *testing.T) {
+	counts := &opCounts{}
+
+	resetCounts := func() { counts = &opCounts{} }
+
+	app := NewApp()
+	app.EnableBashCompletion = true
+	app.BashComplete = func(c *Context) {
+		counts.Total++
+		counts.BashComplete = counts.Total
+	}
+
+	app.OnUsageError = func(c *Context, err error, isSubcommand bool) error {
+		counts.Total++
+		counts.OnUsageError = counts.Total
+		return errors.New("hay OnUsageError")
+	}
+
+	beforeNoError := func(c *Context) error {
+		counts.Total++
+		counts.Before = counts.Total
+		return nil
+	}
+
+	beforeError := func(c *Context) error {
+		counts.Total++
+		counts.Before = counts.Total
+		return errors.New("hay Before")
+	}
+
+	app.Before = beforeNoError
+	app.CommandNotFound = func(c *Context, command string) {
+		counts.Total++
+		counts.CommandNotFound = counts.Total
+	}
+
+	afterNoError := func(c *Context) error {
+		counts.Total++
+		counts.After = counts.Total
+		return nil
+	}
+
+	afterError := func(c *Context) error {
+		counts.Total++
+		counts.After = counts.Total
+		return errors.New("hay After")
+	}
+
+	app.After = afterNoError
+	app.Commands = []Command{
+		{
+			Name: "bar",
+			Action: func(c *Context) error {
+				counts.Total++
+				counts.SubCommand = counts.Total
+				return nil
+			},
+		},
+	}
+
+	app.Action = func(c *Context) error {
+		counts.Total++
+		counts.Action = counts.Total
+		return nil
+	}
+
+	_ = app.Run([]string{"command", "--nope"})
+	expect(t, counts.OnUsageError, 1)
+	expect(t, counts.Total, 1)
+
+	resetCounts()
+
+	_ = app.Run([]string{"command", "--generate-bash-completion"})
+	expect(t, counts.BashComplete, 1)
+	expect(t, counts.Total, 1)
+
+	resetCounts()
+
+	oldOnUsageError := app.OnUsageError
+	app.OnUsageError = nil
+	_ = app.Run([]string{"command", "--nope"})
+	expect(t, counts.Total, 0)
+	app.OnUsageError = oldOnUsageError
+
+	resetCounts()
+
+	_ = app.Run([]string{"command", "foo"})
+	expect(t, counts.OnUsageError, 0)
+	expect(t, counts.Before, 1)
+	expect(t, counts.CommandNotFound, 0)
+	expect(t, counts.Action, 2)
+	expect(t, counts.After, 3)
+	expect(t, counts.Total, 3)
+
+	resetCounts()
+
+	app.Before = beforeError
+	_ = app.Run([]string{"command", "bar"})
+	expect(t, counts.OnUsageError, 0)
+	expect(t, counts.Before, 1)
+	expect(t, counts.After, 2)
+	expect(t, counts.Total, 2)
+	app.Before = beforeNoError
+
+	resetCounts()
+
+	app.After = nil
+	_ = app.Run([]string{"command", "bar"})
+	expect(t, counts.OnUsageError, 0)
+	expect(t, counts.Before, 1)
+	expect(t, counts.SubCommand, 2)
+	expect(t, counts.Total, 2)
+	app.After = afterNoError
+
+	resetCounts()
+
+	app.After = afterError
+	err := app.Run([]string{"command", "bar"})
+	if err == nil {
+		t.Fatalf("expected a non-nil error")
+	}
+	expect(t, counts.OnUsageError, 0)
+	expect(t, counts.Before, 1)
+	expect(t, counts.SubCommand, 2)
+	expect(t, counts.After, 3)
+	expect(t, counts.Total, 3)
+	app.After = afterNoError
+
+	resetCounts()
+
+	oldCommands := app.Commands
+	app.Commands = nil
+	_ = app.Run([]string{"command"})
+	expect(t, counts.OnUsageError, 0)
+	expect(t, counts.Before, 1)
+	expect(t, counts.Action, 2)
+	expect(t, counts.After, 3)
+	expect(t, counts.Total, 3)
+	app.Commands = oldCommands
+}
+
+func TestApp_Run_CommandWithSubcommandHasHelpTopic(t *testing.T) {
+	var subcommandHelpTopics = [][]string{
+		{"command", "foo", "--help"},
+		{"command", "foo", "-h"},
+		{"command", "foo", "help"},
+	}
+
+	for _, flagSet := range subcommandHelpTopics {
+		t.Logf("==> checking with flags %v", flagSet)
+
+		app := NewApp()
+		buf := new(bytes.Buffer)
+		app.Writer = buf
+
+		subCmdBar := Command{
+			Name:  "bar",
+			Usage: "does bar things",
+		}
+		subCmdBaz := Command{
+			Name:  "baz",
+			Usage: "does baz things",
+		}
+		cmd := Command{
+			Name:        "foo",
+			Description: "descriptive wall of text about how it does foo things",
+			Subcommands: []Command{subCmdBar, subCmdBaz},
+		}
+
+		app.Commands = []Command{cmd}
+		err := app.Run(flagSet)
+
+		if err != nil {
+			t.Error(err)
+		}
+
+		output := buf.String()
+		t.Logf("output: %q\n", buf.Bytes())
+
+		if strings.Contains(output, "No help topic for") {
+			t.Errorf("expect a help topic, got none: \n%q", output)
+		}
+
+		for _, shouldContain := range []string{
+			cmd.Name, cmd.Description,
+			subCmdBar.Name, subCmdBar.Usage,
+			subCmdBaz.Name, subCmdBaz.Usage,
+		} {
+			if !strings.Contains(output, shouldContain) {
+				t.Errorf("want help to contain %q, did not: \n%q", shouldContain, output)
+			}
+		}
+	}
+}
+
+func TestApp_Run_SubcommandFullPath(t *testing.T) {
+	app := NewApp()
+	buf := new(bytes.Buffer)
+	app.Writer = buf
+	app.Name = "command"
+	subCmd := Command{
+		Name:  "bar",
+		Usage: "does bar things",
+	}
+	cmd := Command{
+		Name:        "foo",
+		Description: "foo commands",
+		Subcommands: []Command{subCmd},
+	}
+	app.Commands = []Command{cmd}
+
+	err := app.Run([]string{"command", "foo", "bar", "--help"})
+	if err != nil {
+		t.Error(err)
+	}
+
+	output := buf.String()
+	if !strings.Contains(output, "command foo bar - does bar things") {
+		t.Errorf("expected full path to subcommand: %s", output)
+	}
+	if !strings.Contains(output, "command foo bar [arguments...]") {
+		t.Errorf("expected full path to subcommand: %s", output)
+	}
+}
+
+func TestApp_Run_SubcommandHelpName(t *testing.T) {
+	app := NewApp()
+	buf := new(bytes.Buffer)
+	app.Writer = buf
+	app.Name = "command"
+	subCmd := Command{
+		Name:     "bar",
+		HelpName: "custom",
+		Usage:    "does bar things",
+	}
+	cmd := Command{
+		Name:        "foo",
+		Description: "foo commands",
+		Subcommands: []Command{subCmd},
+	}
+	app.Commands = []Command{cmd}
+
+	err := app.Run([]string{"command", "foo", "bar", "--help"})
+	if err != nil {
+		t.Error(err)
+	}
+
+	output := buf.String()
+	if !strings.Contains(output, "custom - does bar things") {
+		t.Errorf("expected HelpName for subcommand: %s", output)
+	}
+	if !strings.Contains(output, "custom [arguments...]") {
+		t.Errorf("expected HelpName to subcommand: %s", output)
+	}
+}
+
+func TestApp_Run_CommandHelpName(t *testing.T) {
+	app := NewApp()
+	buf := new(bytes.Buffer)
+	app.Writer = buf
+	app.Name = "command"
+	subCmd := Command{
+		Name:  "bar",
+		Usage: "does bar things",
+	}
+	cmd := Command{
+		Name:        "foo",
+		HelpName:    "custom",
+		Description: "foo commands",
+		Subcommands: []Command{subCmd},
+	}
+	app.Commands = []Command{cmd}
+
+	err := app.Run([]string{"command", "foo", "bar", "--help"})
+	if err != nil {
+		t.Error(err)
+	}
+
+	output := buf.String()
+	if !strings.Contains(output, "command foo bar - does bar things") {
+		t.Errorf("expected full path to subcommand: %s", output)
+	}
+	if !strings.Contains(output, "command foo bar [arguments...]") {
+		t.Errorf("expected full path to subcommand: %s", output)
+	}
+}
+
+func TestApp_Run_CommandSubcommandHelpName(t *testing.T) {
+	app := NewApp()
+	buf := new(bytes.Buffer)
+	app.Writer = buf
+	app.Name = "base"
+	subCmd := Command{
+		Name:     "bar",
+		HelpName: "custom",
+		Usage:    "does bar things",
+	}
+	cmd := Command{
+		Name:        "foo",
+		Description: "foo commands",
+		Subcommands: []Command{subCmd},
+	}
+	app.Commands = []Command{cmd}
+
+	err := app.Run([]string{"command", "foo", "--help"})
+	if err != nil {
+		t.Error(err)
+	}
+
+	output := buf.String()
+	if !strings.Contains(output, "base foo - foo commands") {
+		t.Errorf("expected full path to subcommand: %s", output)
+	}
+	if !strings.Contains(output, "base foo command [command options] [arguments...]") {
+		t.Errorf("expected full path to subcommand: %s", output)
+	}
+}
+
+func TestApp_Run_Help(t *testing.T) {
+	var helpArguments = [][]string{{"boom", "--help"}, {"boom", "-h"}, {"boom", "help"}}
+
+	for _, args := range helpArguments {
+		buf := new(bytes.Buffer)
+
+		t.Logf("==> checking with arguments %v", args)
+
+		app := NewApp()
+		app.Name = "boom"
+		app.Usage = "make an explosive entrance"
+		app.Writer = buf
+		app.Action = func(c *Context) error {
+			buf.WriteString("boom I say!")
+			return nil
+		}
+
+		err := app.Run(args)
+		if err != nil {
+			t.Error(err)
+		}
+
+		output := buf.String()
+		t.Logf("output: %q\n", buf.Bytes())
+
+		if !strings.Contains(output, "boom - make an explosive entrance") {
+			t.Errorf("want help to contain %q, did not: \n%q", "boom - make an explosive entrance", output)
+		}
+	}
+}
+
+func TestApp_Run_Version(t *testing.T) {
+	var versionArguments = [][]string{{"boom", "--version"}, {"boom", "-v"}}
+
+	for _, args := range versionArguments {
+		buf := new(bytes.Buffer)
+
+		t.Logf("==> checking with arguments %v", args)
+
+		app := NewApp()
+		app.Name = "boom"
+		app.Usage = "make an explosive entrance"
+		app.Version = "0.1.0"
+		app.Writer = buf
+		app.Action = func(c *Context) error {
+			buf.WriteString("boom I say!")
+			return nil
+		}
+
+		err := app.Run(args)
+		if err != nil {
+			t.Error(err)
+		}
+
+		output := buf.String()
+		t.Logf("output: %q\n", buf.Bytes())
+
+		if !strings.Contains(output, "0.1.0") {
+			t.Errorf("want version to contain %q, did not: \n%q", "0.1.0", output)
+		}
+	}
+}
+
+func TestApp_Run_Categories(t *testing.T) {
+	app := NewApp()
+	app.Name = "categories"
+	app.Commands = []Command{
+		{
+			Name:     "command1",
+			Category: "1",
+		},
+		{
+			Name:     "command2",
+			Category: "1",
+		},
+		{
+			Name:     "command3",
+			Category: "2",
+		},
+	}
+	buf := new(bytes.Buffer)
+	app.Writer = buf
+
+	app.Run([]string{"categories"})
+
+	expect := CommandCategories{
+		&CommandCategory{
+			Name: "1",
+			Commands: []Command{
+				app.Commands[0],
+				app.Commands[1],
+			},
+		},
+		&CommandCategory{
+			Name: "2",
+			Commands: []Command{
+				app.Commands[2],
+			},
+		},
+	}
+	if !reflect.DeepEqual(app.Categories(), expect) {
+		t.Fatalf("expected categories %#v, to equal %#v", app.Categories(), expect)
+	}
+
+	output := buf.String()
+	t.Logf("output: %q\n", buf.Bytes())
+
+	if !strings.Contains(output, "1:\n     command1") {
+		t.Errorf("want buffer to include category %q, did not: \n%q", "1:\n     command1", output)
+	}
+}
+
+func TestApp_VisibleCategories(t *testing.T) {
+	app := NewApp()
+	app.Name = "visible-categories"
+	app.Commands = []Command{
+		{
+			Name:     "command1",
+			Category: "1",
+			HelpName: "foo command1",
+			Hidden:   true,
+		},
+		{
+			Name:     "command2",
+			Category: "2",
+			HelpName: "foo command2",
+		},
+		{
+			Name:     "command3",
+			Category: "3",
+			HelpName: "foo command3",
+		},
+	}
+
+	expected := []*CommandCategory{
+		{
+			Name: "2",
+			Commands: []Command{
+				app.Commands[1],
+			},
+		},
+		{
+			Name: "3",
+			Commands: []Command{
+				app.Commands[2],
+			},
+		},
+	}
+
+	app.Setup()
+	expect(t, expected, app.VisibleCategories())
+
+	app = NewApp()
+	app.Name = "visible-categories"
+	app.Commands = []Command{
+		{
+			Name:     "command1",
+			Category: "1",
+			HelpName: "foo command1",
+			Hidden:   true,
+		},
+		{
+			Name:     "command2",
+			Category: "2",
+			HelpName: "foo command2",
+			Hidden:   true,
+		},
+		{
+			Name:     "command3",
+			Category: "3",
+			HelpName: "foo command3",
+		},
+	}
+
+	expected = []*CommandCategory{
+		{
+			Name: "3",
+			Commands: []Command{
+				app.Commands[2],
+			},
+		},
+	}
+
+	app.Setup()
+	expect(t, expected, app.VisibleCategories())
+
+	app = NewApp()
+	app.Name = "visible-categories"
+	app.Commands = []Command{
+		{
+			Name:     "command1",
+			Category: "1",
+			HelpName: "foo command1",
+			Hidden:   true,
+		},
+		{
+			Name:     "command2",
+			Category: "2",
+			HelpName: "foo command2",
+			Hidden:   true,
+		},
+		{
+			Name:     "command3",
+			Category: "3",
+			HelpName: "foo command3",
+			Hidden:   true,
+		},
+	}
+
+	expected = []*CommandCategory{}
+
+	app.Setup()
+	expect(t, expected, app.VisibleCategories())
+}
+
+func TestApp_Run_DoesNotOverwriteErrorFromBefore(t *testing.T) {
+	app := NewApp()
+	app.Action = func(c *Context) error { return nil }
+	app.Before = func(c *Context) error { return fmt.Errorf("before error") }
+	app.After = func(c *Context) error { return fmt.Errorf("after error") }
+
+	err := app.Run([]string{"foo"})
+	if err == nil {
+		t.Fatalf("expected to receive error from Run, got none")
+	}
+
+	if !strings.Contains(err.Error(), "before error") {
+		t.Errorf("expected text of error from Before method, but got none in \"%v\"", err)
+	}
+	if !strings.Contains(err.Error(), "after error") {
+		t.Errorf("expected text of error from After method, but got none in \"%v\"", err)
+	}
+}
+
+func TestApp_Run_SubcommandDoesNotOverwriteErrorFromBefore(t *testing.T) {
+	app := NewApp()
+	app.Commands = []Command{
+		{
+			Subcommands: []Command{
+				{
+					Name: "sub",
+				},
+			},
+			Name:   "bar",
+			Before: func(c *Context) error { return fmt.Errorf("before error") },
+			After:  func(c *Context) error { return fmt.Errorf("after error") },
+		},
+	}
+
+	err := app.Run([]string{"foo", "bar"})
+	if err == nil {
+		t.Fatalf("expected to receive error from Run, got none")
+	}
+
+	if !strings.Contains(err.Error(), "before error") {
+		t.Errorf("expected text of error from Before method, but got none in \"%v\"", err)
+	}
+	if !strings.Contains(err.Error(), "after error") {
+		t.Errorf("expected text of error from After method, but got none in \"%v\"", err)
+	}
+}
+
+func TestApp_OnUsageError_WithWrongFlagValue(t *testing.T) {
+	app := NewApp()
+	app.Flags = []Flag{
+		IntFlag{Name: "flag"},
+	}
+	app.OnUsageError = func(c *Context, err error, isSubcommand bool) error {
+		if isSubcommand {
+			t.Errorf("Expect no subcommand")
+		}
+		if !strings.HasPrefix(err.Error(), "invalid value \"wrong\"") {
+			t.Errorf("Expect an invalid value error, but got \"%v\"", err)
+		}
+		return errors.New("intercepted: " + err.Error())
+	}
+	app.Commands = []Command{
+		{
+			Name: "bar",
+		},
+	}
+
+	err := app.Run([]string{"foo", "--flag=wrong"})
+	if err == nil {
+		t.Fatalf("expected to receive error from Run, got none")
+	}
+
+	if !strings.HasPrefix(err.Error(), "intercepted: invalid value") {
+		t.Errorf("Expect an intercepted error, but got \"%v\"", err)
+	}
+}
+
+func TestApp_OnUsageError_WithWrongFlagValue_ForSubcommand(t *testing.T) {
+	app := NewApp()
+	app.Flags = []Flag{
+		IntFlag{Name: "flag"},
+	}
+	app.OnUsageError = func(c *Context, err error, isSubcommand bool) error {
+		if isSubcommand {
+			t.Errorf("Expect subcommand")
+		}
+		if !strings.HasPrefix(err.Error(), "invalid value \"wrong\"") {
+			t.Errorf("Expect an invalid value error, but got \"%v\"", err)
+		}
+		return errors.New("intercepted: " + err.Error())
+	}
+	app.Commands = []Command{
+		{
+			Name: "bar",
+		},
+	}
+
+	err := app.Run([]string{"foo", "--flag=wrong", "bar"})
+	if err == nil {
+		t.Fatalf("expected to receive error from Run, got none")
+	}
+
+	if !strings.HasPrefix(err.Error(), "intercepted: invalid value") {
+		t.Errorf("Expect an intercepted error, but got \"%v\"", err)
+	}
+}
+
+func TestHandleAction_WithNonFuncAction(t *testing.T) {
+	app := NewApp()
+	app.Action = 42
+	err := HandleAction(app.Action, NewContext(app, flagSet(app.Name, app.Flags), nil))
+
+	if err == nil {
+		t.Fatalf("expected to receive error from Run, got none")
+	}
+
+	exitErr, ok := err.(*ExitError)
+
+	if !ok {
+		t.Fatalf("expected to receive a *ExitError")
+	}
+
+	if !strings.HasPrefix(exitErr.Error(), "ERROR invalid Action type") {
+		t.Fatalf("expected an unknown Action error, but got: %v", exitErr.Error())
+	}
+
+	if exitErr.ExitCode() != 2 {
+		t.Fatalf("expected error exit code to be 2, but got: %v", exitErr.ExitCode())
+	}
+}
+
+func TestHandleAction_WithInvalidFuncSignature(t *testing.T) {
+	app := NewApp()
+	app.Action = func() string { return "" }
+	err := HandleAction(app.Action, NewContext(app, flagSet(app.Name, app.Flags), nil))
+
+	if err == nil {
+		t.Fatalf("expected to receive error from Run, got none")
+	}
+
+	exitErr, ok := err.(*ExitError)
+
+	if !ok {
+		t.Fatalf("expected to receive a *ExitError")
+	}
+
+	if !strings.HasPrefix(exitErr.Error(), "ERROR unknown Action error") {
+		t.Fatalf("expected an unknown Action error, but got: %v", exitErr.Error())
+	}
+
+	if exitErr.ExitCode() != 2 {
+		t.Fatalf("expected error exit code to be 2, but got: %v", exitErr.ExitCode())
+	}
+}
+
+func TestHandleAction_WithInvalidFuncReturnSignature(t *testing.T) {
+	app := NewApp()
+	app.Action = func(_ *Context) (int, error) { return 0, nil }
+	err := HandleAction(app.Action, NewContext(app, flagSet(app.Name, app.Flags), nil))
+
+	if err == nil {
+		t.Fatalf("expected to receive error from Run, got none")
+	}
+
+	exitErr, ok := err.(*ExitError)
+
+	if !ok {
+		t.Fatalf("expected to receive a *ExitError")
+	}
+
+	if !strings.HasPrefix(exitErr.Error(), "ERROR invalid Action signature") {
+		t.Fatalf("expected an invalid Action signature error, but got: %v", exitErr.Error())
+	}
+
+	if exitErr.ExitCode() != 2 {
+		t.Fatalf("expected error exit code to be 2, but got: %v", exitErr.ExitCode())
+	}
+}

+ 16 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/appveyor.yml

@@ -0,0 +1,16 @@
+version: "{build}"
+
+os: Windows Server 2012 R2
+
+install:
+  - go version
+  - go env
+
+build_script:
+  - cd %APPVEYOR_BUILD_FOLDER%
+  - go vet ./...
+  - go test -v ./...
+
+test: off
+
+deploy: off

+ 14 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/autocomplete/bash_autocomplete

@@ -0,0 +1,14 @@
+#! /bin/bash
+
+: ${PROG:=$(basename ${BASH_SOURCE})}
+
+_cli_bash_autocomplete() {
+     local cur opts base
+     COMPREPLY=()
+     cur="${COMP_WORDS[COMP_CWORD]}"
+     opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --generate-bash-completion )
+     COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+     return 0
+ }
+  
+ complete -F _cli_bash_autocomplete $PROG

+ 5 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/autocomplete/zsh_autocomplete

@@ -0,0 +1,5 @@
+autoload -U compinit && compinit
+autoload -U bashcompinit && bashcompinit
+
+script_dir=$(dirname $0)
+source ${script_dir}/bash_autocomplete

+ 44 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/category.go

@@ -0,0 +1,44 @@
+package cli
+
+// CommandCategories is a slice of *CommandCategory.
+type CommandCategories []*CommandCategory
+
+// CommandCategory is a category containing commands.
+type CommandCategory struct {
+	Name     string
+	Commands Commands
+}
+
+func (c CommandCategories) Less(i, j int) bool {
+	return c[i].Name < c[j].Name
+}
+
+func (c CommandCategories) Len() int {
+	return len(c)
+}
+
+func (c CommandCategories) Swap(i, j int) {
+	c[i], c[j] = c[j], c[i]
+}
+
+// AddCommand adds a command to a category.
+func (c CommandCategories) AddCommand(category string, command Command) CommandCategories {
+	for _, commandCategory := range c {
+		if commandCategory.Name == category {
+			commandCategory.Commands = append(commandCategory.Commands, command)
+			return c
+		}
+	}
+	return append(c, &CommandCategory{Name: category, Commands: []Command{command}})
+}
+
+// VisibleCommands returns a slice of the Commands with Hidden=false
+func (c *CommandCategory) VisibleCommands() []Command {
+	ret := []Command{}
+	for _, command := range c.Commands {
+		if !command.Hidden {
+			ret = append(ret, command)
+		}
+	}
+	return ret
+}

+ 19 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/cli.go

@@ -0,0 +1,19 @@
+// Package cli provides a minimal framework for creating and organizing command line
+// Go applications. cli is designed to be easy to understand and write, the most simple
+// cli application can be written as follows:
+//   func main() {
+//     cli.NewApp().Run(os.Args)
+//   }
+//
+// Of course this application does not do much, so let's make this an actual application:
+//   func main() {
+//     app := cli.NewApp()
+//     app.Name = "greet"
+//     app.Usage = "say a greeting"
+//     app.Action = func(c *cli.Context) error {
+//       println("Greetings")
+//     }
+//
+//     app.Run(os.Args)
+//   }
+package cli

+ 279 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/command.go

@@ -0,0 +1,279 @@
+package cli
+
+import (
+	"fmt"
+	"io/ioutil"
+	"sort"
+	"strings"
+)
+
+// Command is a subcommand for a cli.App.
+type Command struct {
+	// The name of the command
+	Name string
+	// short name of the command. Typically one character (deprecated, use `Aliases`)
+	ShortName string
+	// A list of aliases for the command
+	Aliases []string
+	// A short description of the usage of this command
+	Usage string
+	// Custom text to show on USAGE section of help
+	UsageText string
+	// A longer explanation of how the command works
+	Description string
+	// A short description of the arguments of this command
+	ArgsUsage string
+	// The category the command is part of
+	Category string
+	// The function to call when checking for bash command completions
+	BashComplete BashCompleteFunc
+	// An action to execute before any sub-subcommands are run, but after the context is ready
+	// If a non-nil error is returned, no sub-subcommands are run
+	Before BeforeFunc
+	// An action to execute after any subcommands are run, but after the subcommand has finished
+	// It is run even if Action() panics
+	After AfterFunc
+	// The function to call when this command is invoked
+	Action interface{}
+	// TODO: replace `Action: interface{}` with `Action: ActionFunc` once some kind
+	// of deprecation period has passed, maybe?
+
+	// Execute this function if a usage error occurs.
+	OnUsageError OnUsageErrorFunc
+	// List of child commands
+	Subcommands Commands
+	// List of flags to parse
+	Flags []Flag
+	// Treat all flags as normal arguments if true
+	SkipFlagParsing bool
+	// Boolean to hide built-in help command
+	HideHelp bool
+	// Boolean to hide this command from help or completion
+	Hidden bool
+
+	// Full name of command for help, defaults to full command name, including parent commands.
+	HelpName        string
+	commandNamePath []string
+}
+
+// FullName returns the full name of the command.
+// For subcommands this ensures that parent commands are part of the command path
+func (c Command) FullName() string {
+	if c.commandNamePath == nil {
+		return c.Name
+	}
+	return strings.Join(c.commandNamePath, " ")
+}
+
+// Commands is a slice of Command
+type Commands []Command
+
+// Run invokes the command given the context, parses ctx.Args() to generate command-specific flags
+func (c Command) Run(ctx *Context) (err error) {
+	if len(c.Subcommands) > 0 {
+		return c.startApp(ctx)
+	}
+
+	if !c.HideHelp && (HelpFlag != BoolFlag{}) {
+		// append help to flags
+		c.Flags = append(
+			c.Flags,
+			HelpFlag,
+		)
+	}
+
+	if ctx.App.EnableBashCompletion {
+		c.Flags = append(c.Flags, BashCompletionFlag)
+	}
+
+	set := flagSet(c.Name, c.Flags)
+	set.SetOutput(ioutil.Discard)
+
+	if !c.SkipFlagParsing {
+		firstFlagIndex := -1
+		terminatorIndex := -1
+		for index, arg := range ctx.Args() {
+			if arg == "--" {
+				terminatorIndex = index
+				break
+			} else if arg == "-" {
+				// Do nothing. A dash alone is not really a flag.
+				continue
+			} else if strings.HasPrefix(arg, "-") && firstFlagIndex == -1 {
+				firstFlagIndex = index
+			}
+		}
+
+		if firstFlagIndex > -1 {
+			args := ctx.Args()
+			regularArgs := make([]string, len(args[1:firstFlagIndex]))
+			copy(regularArgs, args[1:firstFlagIndex])
+
+			var flagArgs []string
+			if terminatorIndex > -1 {
+				flagArgs = args[firstFlagIndex:terminatorIndex]
+				regularArgs = append(regularArgs, args[terminatorIndex:]...)
+			} else {
+				flagArgs = args[firstFlagIndex:]
+			}
+
+			err = set.Parse(append(flagArgs, regularArgs...))
+		} else {
+			err = set.Parse(ctx.Args().Tail())
+		}
+	} else {
+		if c.SkipFlagParsing {
+			err = set.Parse(append([]string{"--"}, ctx.Args().Tail()...))
+		}
+	}
+
+	if err != nil {
+		if c.OnUsageError != nil {
+			err := c.OnUsageError(ctx, err, false)
+			HandleExitCoder(err)
+			return err
+		}
+		fmt.Fprintln(ctx.App.Writer, "Incorrect Usage.")
+		fmt.Fprintln(ctx.App.Writer)
+		ShowCommandHelp(ctx, c.Name)
+		return err
+	}
+
+	nerr := normalizeFlags(c.Flags, set)
+	if nerr != nil {
+		fmt.Fprintln(ctx.App.Writer, nerr)
+		fmt.Fprintln(ctx.App.Writer)
+		ShowCommandHelp(ctx, c.Name)
+		return nerr
+	}
+
+	context := NewContext(ctx.App, set, ctx)
+
+	if checkCommandCompletions(context, c.Name) {
+		return nil
+	}
+
+	if checkCommandHelp(context, c.Name) {
+		return nil
+	}
+
+	if c.After != nil {
+		defer func() {
+			afterErr := c.After(context)
+			if afterErr != nil {
+				HandleExitCoder(err)
+				if err != nil {
+					err = NewMultiError(err, afterErr)
+				} else {
+					err = afterErr
+				}
+			}
+		}()
+	}
+
+	if c.Before != nil {
+		err = c.Before(context)
+		if err != nil {
+			fmt.Fprintln(ctx.App.Writer, err)
+			fmt.Fprintln(ctx.App.Writer)
+			ShowCommandHelp(ctx, c.Name)
+			HandleExitCoder(err)
+			return err
+		}
+	}
+
+	context.Command = c
+	err = HandleAction(c.Action, context)
+
+	if err != nil {
+		HandleExitCoder(err)
+	}
+	return err
+}
+
+// Names returns the names including short names and aliases.
+func (c Command) Names() []string {
+	names := []string{c.Name}
+
+	if c.ShortName != "" {
+		names = append(names, c.ShortName)
+	}
+
+	return append(names, c.Aliases...)
+}
+
+// HasName returns true if Command.Name or Command.ShortName matches given name
+func (c Command) HasName(name string) bool {
+	for _, n := range c.Names() {
+		if n == name {
+			return true
+		}
+	}
+	return false
+}
+
+func (c Command) startApp(ctx *Context) error {
+	app := NewApp()
+	app.Metadata = ctx.App.Metadata
+	// set the name and usage
+	app.Name = fmt.Sprintf("%s %s", ctx.App.Name, c.Name)
+	if c.HelpName == "" {
+		app.HelpName = c.HelpName
+	} else {
+		app.HelpName = app.Name
+	}
+
+	if c.Description != "" {
+		app.Usage = c.Description
+	} else {
+		app.Usage = c.Usage
+	}
+
+	// set CommandNotFound
+	app.CommandNotFound = ctx.App.CommandNotFound
+
+	// set the flags and commands
+	app.Commands = c.Subcommands
+	app.Flags = c.Flags
+	app.HideHelp = c.HideHelp
+
+	app.Version = ctx.App.Version
+	app.HideVersion = ctx.App.HideVersion
+	app.Compiled = ctx.App.Compiled
+	app.Author = ctx.App.Author
+	app.Email = ctx.App.Email
+	app.Writer = ctx.App.Writer
+
+	app.categories = CommandCategories{}
+	for _, command := range c.Subcommands {
+		app.categories = app.categories.AddCommand(command.Category, command)
+	}
+
+	sort.Sort(app.categories)
+
+	// bash completion
+	app.EnableBashCompletion = ctx.App.EnableBashCompletion
+	if c.BashComplete != nil {
+		app.BashComplete = c.BashComplete
+	}
+
+	// set the actions
+	app.Before = c.Before
+	app.After = c.After
+	if c.Action != nil {
+		app.Action = c.Action
+	} else {
+		app.Action = helpSubcommand.Action
+	}
+
+	for index, cc := range app.Commands {
+		app.Commands[index].commandNamePath = []string{c.Name, cc.Name}
+	}
+
+	return app.RunAsSubcommand(ctx)
+}
+
+// VisibleFlags returns a slice of the Flags with Hidden=false
+func (c Command) VisibleFlags() []Flag {
+	return visibleFlags(c.Flags)
+}

+ 101 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/command_test.go

@@ -0,0 +1,101 @@
+package cli
+
+import (
+	"errors"
+	"flag"
+	"fmt"
+	"io/ioutil"
+	"strings"
+	"testing"
+)
+
+func TestCommandFlagParsing(t *testing.T) {
+	cases := []struct {
+		testArgs        []string
+		skipFlagParsing bool
+		expectedErr     error
+	}{
+		{[]string{"blah", "blah", "-break"}, false, errors.New("flag provided but not defined: -break")}, // Test normal "not ignoring flags" flow
+		{[]string{"blah", "blah"}, true, nil},                                                            // Test SkipFlagParsing without any args that look like flags
+		{[]string{"blah", "-break"}, true, nil},                                                          // Test SkipFlagParsing with random flag arg
+		{[]string{"blah", "-help"}, true, nil},                                                           // Test SkipFlagParsing with "special" help flag arg
+	}
+
+	for _, c := range cases {
+		app := NewApp()
+		app.Writer = ioutil.Discard
+		set := flag.NewFlagSet("test", 0)
+		set.Parse(c.testArgs)
+
+		context := NewContext(app, set, nil)
+
+		command := Command{
+			Name:        "test-cmd",
+			Aliases:     []string{"tc"},
+			Usage:       "this is for testing",
+			Description: "testing",
+			Action:      func(_ *Context) error { return nil },
+		}
+
+		command.SkipFlagParsing = c.skipFlagParsing
+
+		err := command.Run(context)
+
+		expect(t, err, c.expectedErr)
+		expect(t, []string(context.Args()), c.testArgs)
+	}
+}
+
+func TestCommand_Run_DoesNotOverwriteErrorFromBefore(t *testing.T) {
+	app := NewApp()
+	app.Commands = []Command{
+		{
+			Name: "bar",
+			Before: func(c *Context) error {
+				return fmt.Errorf("before error")
+			},
+			After: func(c *Context) error {
+				return fmt.Errorf("after error")
+			},
+		},
+	}
+
+	err := app.Run([]string{"foo", "bar"})
+	if err == nil {
+		t.Fatalf("expected to receive error from Run, got none")
+	}
+
+	if !strings.Contains(err.Error(), "before error") {
+		t.Errorf("expected text of error from Before method, but got none in \"%v\"", err)
+	}
+	if !strings.Contains(err.Error(), "after error") {
+		t.Errorf("expected text of error from After method, but got none in \"%v\"", err)
+	}
+}
+
+func TestCommand_OnUsageError_WithWrongFlagValue(t *testing.T) {
+	app := NewApp()
+	app.Commands = []Command{
+		{
+			Name: "bar",
+			Flags: []Flag{
+				IntFlag{Name: "flag"},
+			},
+			OnUsageError: func(c *Context, err error, _ bool) error {
+				if !strings.HasPrefix(err.Error(), "invalid value \"wrong\"") {
+					t.Errorf("Expect an invalid value error, but got \"%v\"", err)
+				}
+				return errors.New("intercepted: " + err.Error())
+			},
+		},
+	}
+
+	err := app.Run([]string{"foo", "bar", "--flag=wrong"})
+	if err == nil {
+		t.Fatalf("expected to receive error from Run, got none")
+	}
+
+	if !strings.HasPrefix(err.Error(), "intercepted: invalid value") {
+		t.Errorf("Expect an intercepted error, but got \"%v\"", err)
+	}
+}

+ 446 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/context.go

@@ -0,0 +1,446 @@
+package cli
+
+import (
+	"errors"
+	"flag"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// Context is a type that is passed through to
+// each Handler action in a cli application. Context
+// can be used to retrieve context-specific Args and
+// parsed command-line options.
+type Context struct {
+	App            *App
+	Command        Command
+	flagSet        *flag.FlagSet
+	setFlags       map[string]bool
+	globalSetFlags map[string]bool
+	parentContext  *Context
+}
+
+// NewContext creates a new context. For use in when invoking an App or Command action.
+func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context {
+	return &Context{App: app, flagSet: set, parentContext: parentCtx}
+}
+
+// Int looks up the value of a local int flag, returns 0 if no int flag exists
+func (c *Context) Int(name string) int {
+	return lookupInt(name, c.flagSet)
+}
+
+// Duration looks up the value of a local time.Duration flag, returns 0 if no
+// time.Duration flag exists
+func (c *Context) Duration(name string) time.Duration {
+	return lookupDuration(name, c.flagSet)
+}
+
+// Float64 looks up the value of a local float64 flag, returns 0 if no float64
+// flag exists
+func (c *Context) Float64(name string) float64 {
+	return lookupFloat64(name, c.flagSet)
+}
+
+// Bool looks up the value of a local bool flag, returns false if no bool flag exists
+func (c *Context) Bool(name string) bool {
+	return lookupBool(name, c.flagSet)
+}
+
+// BoolT looks up the value of a local boolT flag, returns false if no bool flag exists
+func (c *Context) BoolT(name string) bool {
+	return lookupBoolT(name, c.flagSet)
+}
+
+// String looks up the value of a local string flag, returns "" if no string flag exists
+func (c *Context) String(name string) string {
+	return lookupString(name, c.flagSet)
+}
+
+// StringSlice looks up the value of a local string slice flag, returns nil if no
+// string slice flag exists
+func (c *Context) StringSlice(name string) []string {
+	return lookupStringSlice(name, c.flagSet)
+}
+
+// IntSlice looks up the value of a local int slice flag, returns nil if no int
+// slice flag exists
+func (c *Context) IntSlice(name string) []int {
+	return lookupIntSlice(name, c.flagSet)
+}
+
+// Generic looks up the value of a local generic flag, returns nil if no generic
+// flag exists
+func (c *Context) Generic(name string) interface{} {
+	return lookupGeneric(name, c.flagSet)
+}
+
+// GlobalInt looks up the value of a global int flag, returns 0 if no int flag exists
+func (c *Context) GlobalInt(name string) int {
+	if fs := lookupGlobalFlagSet(name, c); fs != nil {
+		return lookupInt(name, fs)
+	}
+	return 0
+}
+
+// GlobalFloat64 looks up the value of a global float64 flag, returns float64(0)
+// if no float64 flag exists
+func (c *Context) GlobalFloat64(name string) float64 {
+	if fs := lookupGlobalFlagSet(name, c); fs != nil {
+		return lookupFloat64(name, fs)
+	}
+	return float64(0)
+}
+
+// GlobalDuration looks up the value of a global time.Duration flag, returns 0
+// if no time.Duration flag exists
+func (c *Context) GlobalDuration(name string) time.Duration {
+	if fs := lookupGlobalFlagSet(name, c); fs != nil {
+		return lookupDuration(name, fs)
+	}
+	return 0
+}
+
+// GlobalBool looks up the value of a global bool flag, returns false if no bool
+// flag exists
+func (c *Context) GlobalBool(name string) bool {
+	if fs := lookupGlobalFlagSet(name, c); fs != nil {
+		return lookupBool(name, fs)
+	}
+	return false
+}
+
+// GlobalBoolT looks up the value of a global bool flag, returns true if no bool
+// flag exists
+func (c *Context) GlobalBoolT(name string) bool {
+	if fs := lookupGlobalFlagSet(name, c); fs != nil {
+		return lookupBoolT(name, fs)
+	}
+	return false
+}
+
+// GlobalString looks up the value of a global string flag, returns "" if no
+// string flag exists
+func (c *Context) GlobalString(name string) string {
+	if fs := lookupGlobalFlagSet(name, c); fs != nil {
+		return lookupString(name, fs)
+	}
+	return ""
+}
+
+// GlobalStringSlice looks up the value of a global string slice flag, returns
+// nil if no string slice flag exists
+func (c *Context) GlobalStringSlice(name string) []string {
+	if fs := lookupGlobalFlagSet(name, c); fs != nil {
+		return lookupStringSlice(name, fs)
+	}
+	return nil
+}
+
+// GlobalIntSlice looks up the value of a global int slice flag, returns nil if
+// no int slice flag exists
+func (c *Context) GlobalIntSlice(name string) []int {
+	if fs := lookupGlobalFlagSet(name, c); fs != nil {
+		return lookupIntSlice(name, fs)
+	}
+	return nil
+}
+
+// GlobalGeneric looks up the value of a global generic flag, returns nil if no
+// generic flag exists
+func (c *Context) GlobalGeneric(name string) interface{} {
+	if fs := lookupGlobalFlagSet(name, c); fs != nil {
+		return lookupGeneric(name, fs)
+	}
+	return nil
+}
+
+// NumFlags returns the number of flags set
+func (c *Context) NumFlags() int {
+	return c.flagSet.NFlag()
+}
+
+// Set sets a context flag to a value.
+func (c *Context) Set(name, value string) error {
+	return c.flagSet.Set(name, value)
+}
+
+// GlobalSet sets a context flag to a value on the global flagset
+func (c *Context) GlobalSet(name, value string) error {
+	return globalContext(c).flagSet.Set(name, value)
+}
+
+// IsSet determines if the flag was actually set
+func (c *Context) IsSet(name string) bool {
+	if c.setFlags == nil {
+		c.setFlags = make(map[string]bool)
+		c.flagSet.Visit(func(f *flag.Flag) {
+			c.setFlags[f.Name] = true
+		})
+	}
+	return c.setFlags[name] == true
+}
+
+// GlobalIsSet determines if the global flag was actually set
+func (c *Context) GlobalIsSet(name string) bool {
+	if c.globalSetFlags == nil {
+		c.globalSetFlags = make(map[string]bool)
+		ctx := c
+		if ctx.parentContext != nil {
+			ctx = ctx.parentContext
+		}
+		for ; ctx != nil && c.globalSetFlags[name] == false; ctx = ctx.parentContext {
+			ctx.flagSet.Visit(func(f *flag.Flag) {
+				c.globalSetFlags[f.Name] = true
+			})
+		}
+	}
+	return c.globalSetFlags[name]
+}
+
+// FlagNames returns a slice of flag names used in this context.
+func (c *Context) FlagNames() (names []string) {
+	for _, flag := range c.Command.Flags {
+		name := strings.Split(flag.GetName(), ",")[0]
+		if name == "help" {
+			continue
+		}
+		names = append(names, name)
+	}
+	return
+}
+
+// GlobalFlagNames returns a slice of global flag names used by the app.
+func (c *Context) GlobalFlagNames() (names []string) {
+	for _, flag := range c.App.Flags {
+		name := strings.Split(flag.GetName(), ",")[0]
+		if name == "help" || name == "version" {
+			continue
+		}
+		names = append(names, name)
+	}
+	return
+}
+
+// Parent returns the parent context, if any
+func (c *Context) Parent() *Context {
+	return c.parentContext
+}
+
+// Args contains apps console arguments
+type Args []string
+
+// Args returns the command line arguments associated with the context.
+func (c *Context) Args() Args {
+	args := Args(c.flagSet.Args())
+	return args
+}
+
+// NArg returns the number of the command line arguments.
+func (c *Context) NArg() int {
+	return len(c.Args())
+}
+
+// Get returns the nth argument, or else a blank string
+func (a Args) Get(n int) string {
+	if len(a) > n {
+		return a[n]
+	}
+	return ""
+}
+
+// First returns the first argument, or else a blank string
+func (a Args) First() string {
+	return a.Get(0)
+}
+
+// Tail returns the rest of the arguments (not the first one)
+// or else an empty string slice
+func (a Args) Tail() []string {
+	if len(a) >= 2 {
+		return []string(a)[1:]
+	}
+	return []string{}
+}
+
+// Present checks if there are any arguments present
+func (a Args) Present() bool {
+	return len(a) != 0
+}
+
+// Swap swaps arguments at the given indexes
+func (a Args) Swap(from, to int) error {
+	if from >= len(a) || to >= len(a) {
+		return errors.New("index out of range")
+	}
+	a[from], a[to] = a[to], a[from]
+	return nil
+}
+
+func globalContext(ctx *Context) *Context {
+	if ctx == nil {
+		return nil
+	}
+
+	for {
+		if ctx.parentContext == nil {
+			return ctx
+		}
+		ctx = ctx.parentContext
+	}
+}
+
+func lookupGlobalFlagSet(name string, ctx *Context) *flag.FlagSet {
+	if ctx.parentContext != nil {
+		ctx = ctx.parentContext
+	}
+	for ; ctx != nil; ctx = ctx.parentContext {
+		if f := ctx.flagSet.Lookup(name); f != nil {
+			return ctx.flagSet
+		}
+	}
+	return nil
+}
+
+func lookupInt(name string, set *flag.FlagSet) int {
+	f := set.Lookup(name)
+	if f != nil {
+		val, err := strconv.Atoi(f.Value.String())
+		if err != nil {
+			return 0
+		}
+		return val
+	}
+
+	return 0
+}
+
+func lookupDuration(name string, set *flag.FlagSet) time.Duration {
+	f := set.Lookup(name)
+	if f != nil {
+		val, err := time.ParseDuration(f.Value.String())
+		if err == nil {
+			return val
+		}
+	}
+
+	return 0
+}
+
+func lookupFloat64(name string, set *flag.FlagSet) float64 {
+	f := set.Lookup(name)
+	if f != nil {
+		val, err := strconv.ParseFloat(f.Value.String(), 64)
+		if err != nil {
+			return 0
+		}
+		return val
+	}
+
+	return 0
+}
+
+func lookupString(name string, set *flag.FlagSet) string {
+	f := set.Lookup(name)
+	if f != nil {
+		return f.Value.String()
+	}
+
+	return ""
+}
+
+func lookupStringSlice(name string, set *flag.FlagSet) []string {
+	f := set.Lookup(name)
+	if f != nil {
+		return (f.Value.(*StringSlice)).Value()
+
+	}
+
+	return nil
+}
+
+func lookupIntSlice(name string, set *flag.FlagSet) []int {
+	f := set.Lookup(name)
+	if f != nil {
+		return (f.Value.(*IntSlice)).Value()
+
+	}
+
+	return nil
+}
+
+func lookupGeneric(name string, set *flag.FlagSet) interface{} {
+	f := set.Lookup(name)
+	if f != nil {
+		return f.Value
+	}
+	return nil
+}
+
+func lookupBool(name string, set *flag.FlagSet) bool {
+	f := set.Lookup(name)
+	if f != nil {
+		val, err := strconv.ParseBool(f.Value.String())
+		if err != nil {
+			return false
+		}
+		return val
+	}
+
+	return false
+}
+
+func lookupBoolT(name string, set *flag.FlagSet) bool {
+	f := set.Lookup(name)
+	if f != nil {
+		val, err := strconv.ParseBool(f.Value.String())
+		if err != nil {
+			return true
+		}
+		return val
+	}
+
+	return false
+}
+
+func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) {
+	switch ff.Value.(type) {
+	case *StringSlice:
+	default:
+		set.Set(name, ff.Value.String())
+	}
+}
+
+func normalizeFlags(flags []Flag, set *flag.FlagSet) error {
+	visited := make(map[string]bool)
+	set.Visit(func(f *flag.Flag) {
+		visited[f.Name] = true
+	})
+	for _, f := range flags {
+		parts := strings.Split(f.GetName(), ",")
+		if len(parts) == 1 {
+			continue
+		}
+		var ff *flag.Flag
+		for _, name := range parts {
+			name = strings.Trim(name, " ")
+			if visited[name] {
+				if ff != nil {
+					return errors.New("Cannot use two forms of the same flag: " + name + " " + ff.Name)
+				}
+				ff = set.Lookup(name)
+			}
+		}
+		if ff == nil {
+			continue
+		}
+		for _, name := range parts {
+			name = strings.Trim(name, " ")
+			if !visited[name] {
+				copyFlag(name, ff, set)
+			}
+		}
+	}
+	return nil
+}

+ 256 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/context_test.go

@@ -0,0 +1,256 @@
+package cli
+
+import (
+	"flag"
+	"testing"
+	"time"
+)
+
+func TestNewContext(t *testing.T) {
+	set := flag.NewFlagSet("test", 0)
+	set.Int("myflag", 12, "doc")
+	set.Float64("myflag64", float64(17), "doc")
+	globalSet := flag.NewFlagSet("test", 0)
+	globalSet.Int("myflag", 42, "doc")
+	globalSet.Float64("myflag64", float64(47), "doc")
+	globalCtx := NewContext(nil, globalSet, nil)
+	command := Command{Name: "mycommand"}
+	c := NewContext(nil, set, globalCtx)
+	c.Command = command
+	expect(t, c.Int("myflag"), 12)
+	expect(t, c.Float64("myflag64"), float64(17))
+	expect(t, c.GlobalInt("myflag"), 42)
+	expect(t, c.GlobalFloat64("myflag64"), float64(47))
+	expect(t, c.Command.Name, "mycommand")
+}
+
+func TestContext_Int(t *testing.T) {
+	set := flag.NewFlagSet("test", 0)
+	set.Int("myflag", 12, "doc")
+	c := NewContext(nil, set, nil)
+	expect(t, c.Int("myflag"), 12)
+}
+
+func TestContext_GlobalInt(t *testing.T) {
+	set := flag.NewFlagSet("test", 0)
+	set.Int("myflag", 12, "doc")
+	c := NewContext(nil, set, nil)
+	expect(t, c.GlobalInt("myflag"), 12)
+	expect(t, c.GlobalInt("nope"), 0)
+}
+
+func TestContext_Float64(t *testing.T) {
+	set := flag.NewFlagSet("test", 0)
+	set.Float64("myflag", float64(17), "doc")
+	c := NewContext(nil, set, nil)
+	expect(t, c.Float64("myflag"), float64(17))
+}
+
+func TestContext_GlobalFloat64(t *testing.T) {
+	set := flag.NewFlagSet("test", 0)
+	set.Float64("myflag", float64(17), "doc")
+	c := NewContext(nil, set, nil)
+	expect(t, c.GlobalFloat64("myflag"), float64(17))
+	expect(t, c.GlobalFloat64("nope"), float64(0))
+}
+
+func TestContext_Duration(t *testing.T) {
+	set := flag.NewFlagSet("test", 0)
+	set.Duration("myflag", time.Duration(12*time.Second), "doc")
+	c := NewContext(nil, set, nil)
+	expect(t, c.Duration("myflag"), time.Duration(12*time.Second))
+}
+
+func TestContext_String(t *testing.T) {
+	set := flag.NewFlagSet("test", 0)
+	set.String("myflag", "hello world", "doc")
+	c := NewContext(nil, set, nil)
+	expect(t, c.String("myflag"), "hello world")
+}
+
+func TestContext_Bool(t *testing.T) {
+	set := flag.NewFlagSet("test", 0)
+	set.Bool("myflag", false, "doc")
+	c := NewContext(nil, set, nil)
+	expect(t, c.Bool("myflag"), false)
+}
+
+func TestContext_BoolT(t *testing.T) {
+	set := flag.NewFlagSet("test", 0)
+	set.Bool("myflag", true, "doc")
+	c := NewContext(nil, set, nil)
+	expect(t, c.BoolT("myflag"), true)
+}
+
+func TestContext_GlobalBool(t *testing.T) {
+	set := flag.NewFlagSet("test", 0)
+
+	globalSet := flag.NewFlagSet("test-global", 0)
+	globalSet.Bool("myflag", false, "doc")
+	globalCtx := NewContext(nil, globalSet, nil)
+
+	c := NewContext(nil, set, globalCtx)
+	expect(t, c.GlobalBool("myflag"), false)
+	expect(t, c.GlobalBool("nope"), false)
+}
+
+func TestContext_GlobalBoolT(t *testing.T) {
+	set := flag.NewFlagSet("test", 0)
+
+	globalSet := flag.NewFlagSet("test-global", 0)
+	globalSet.Bool("myflag", true, "doc")
+	globalCtx := NewContext(nil, globalSet, nil)
+
+	c := NewContext(nil, set, globalCtx)
+	expect(t, c.GlobalBoolT("myflag"), true)
+	expect(t, c.GlobalBoolT("nope"), false)
+}
+
+func TestContext_Args(t *testing.T) {
+	set := flag.NewFlagSet("test", 0)
+	set.Bool("myflag", false, "doc")
+	c := NewContext(nil, set, nil)
+	set.Parse([]string{"--myflag", "bat", "baz"})
+	expect(t, len(c.Args()), 2)
+	expect(t, c.Bool("myflag"), true)
+}
+
+func TestContext_NArg(t *testing.T) {
+	set := flag.NewFlagSet("test", 0)
+	set.Bool("myflag", false, "doc")
+	c := NewContext(nil, set, nil)
+	set.Parse([]string{"--myflag", "bat", "baz"})
+	expect(t, c.NArg(), 2)
+}
+
+func TestContext_IsSet(t *testing.T) {
+	set := flag.NewFlagSet("test", 0)
+	set.Bool("myflag", false, "doc")
+	set.String("otherflag", "hello world", "doc")
+	globalSet := flag.NewFlagSet("test", 0)
+	globalSet.Bool("myflagGlobal", true, "doc")
+	globalCtx := NewContext(nil, globalSet, nil)
+	c := NewContext(nil, set, globalCtx)
+	set.Parse([]string{"--myflag", "bat", "baz"})
+	globalSet.Parse([]string{"--myflagGlobal", "bat", "baz"})
+	expect(t, c.IsSet("myflag"), true)
+	expect(t, c.IsSet("otherflag"), false)
+	expect(t, c.IsSet("bogusflag"), false)
+	expect(t, c.IsSet("myflagGlobal"), false)
+}
+
+func TestContext_GlobalIsSet(t *testing.T) {
+	set := flag.NewFlagSet("test", 0)
+	set.Bool("myflag", false, "doc")
+	set.String("otherflag", "hello world", "doc")
+	globalSet := flag.NewFlagSet("test", 0)
+	globalSet.Bool("myflagGlobal", true, "doc")
+	globalSet.Bool("myflagGlobalUnset", true, "doc")
+	globalCtx := NewContext(nil, globalSet, nil)
+	c := NewContext(nil, set, globalCtx)
+	set.Parse([]string{"--myflag", "bat", "baz"})
+	globalSet.Parse([]string{"--myflagGlobal", "bat", "baz"})
+	expect(t, c.GlobalIsSet("myflag"), false)
+	expect(t, c.GlobalIsSet("otherflag"), false)
+	expect(t, c.GlobalIsSet("bogusflag"), false)
+	expect(t, c.GlobalIsSet("myflagGlobal"), true)
+	expect(t, c.GlobalIsSet("myflagGlobalUnset"), false)
+	expect(t, c.GlobalIsSet("bogusGlobal"), false)
+}
+
+func TestContext_NumFlags(t *testing.T) {
+	set := flag.NewFlagSet("test", 0)
+	set.Bool("myflag", false, "doc")
+	set.String("otherflag", "hello world", "doc")
+	globalSet := flag.NewFlagSet("test", 0)
+	globalSet.Bool("myflagGlobal", true, "doc")
+	globalCtx := NewContext(nil, globalSet, nil)
+	c := NewContext(nil, set, globalCtx)
+	set.Parse([]string{"--myflag", "--otherflag=foo"})
+	globalSet.Parse([]string{"--myflagGlobal"})
+	expect(t, c.NumFlags(), 2)
+}
+
+func TestContext_GlobalFlag(t *testing.T) {
+	var globalFlag string
+	var globalFlagSet bool
+	app := NewApp()
+	app.Flags = []Flag{
+		StringFlag{Name: "global, g", Usage: "global"},
+	}
+	app.Action = func(c *Context) error {
+		globalFlag = c.GlobalString("global")
+		globalFlagSet = c.GlobalIsSet("global")
+		return nil
+	}
+	app.Run([]string{"command", "-g", "foo"})
+	expect(t, globalFlag, "foo")
+	expect(t, globalFlagSet, true)
+
+}
+
+func TestContext_GlobalFlagsInSubcommands(t *testing.T) {
+	subcommandRun := false
+	parentFlag := false
+	app := NewApp()
+
+	app.Flags = []Flag{
+		BoolFlag{Name: "debug, d", Usage: "Enable debugging"},
+	}
+
+	app.Commands = []Command{
+		{
+			Name: "foo",
+			Flags: []Flag{
+				BoolFlag{Name: "parent, p", Usage: "Parent flag"},
+			},
+			Subcommands: []Command{
+				{
+					Name: "bar",
+					Action: func(c *Context) error {
+						if c.GlobalBool("debug") {
+							subcommandRun = true
+						}
+						if c.GlobalBool("parent") {
+							parentFlag = true
+						}
+						return nil
+					},
+				},
+			},
+		},
+	}
+
+	app.Run([]string{"command", "-d", "foo", "-p", "bar"})
+
+	expect(t, subcommandRun, true)
+	expect(t, parentFlag, true)
+}
+
+func TestContext_Set(t *testing.T) {
+	set := flag.NewFlagSet("test", 0)
+	set.Int("int", 5, "an int")
+	c := NewContext(nil, set, nil)
+
+	c.Set("int", "1")
+	expect(t, c.Int("int"), 1)
+}
+
+func TestContext_GlobalSet(t *testing.T) {
+	gSet := flag.NewFlagSet("test", 0)
+	gSet.Int("int", 5, "an int")
+
+	set := flag.NewFlagSet("sub", 0)
+	set.Int("int", 3, "an int")
+
+	pc := NewContext(nil, gSet, nil)
+	c := NewContext(nil, set, pc)
+
+	c.Set("int", "1")
+	expect(t, c.Int("int"), 1)
+	expect(t, c.GlobalInt("int"), 5)
+
+	c.GlobalSet("int", "1")
+	expect(t, c.Int("int"), 1)
+	expect(t, c.GlobalInt("int"), 1)
+}

+ 92 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/errors.go

@@ -0,0 +1,92 @@
+package cli
+
+import (
+	"fmt"
+	"io"
+	"os"
+	"strings"
+)
+
+// OsExiter is the function used when the app exits. If not set defaults to os.Exit.
+var OsExiter = os.Exit
+
+// ErrWriter is used to write errors to the user. This can be anything
+// implementing the io.Writer interface and defaults to os.Stderr.
+var ErrWriter io.Writer = os.Stderr
+
+// MultiError is an error that wraps multiple errors.
+type MultiError struct {
+	Errors []error
+}
+
+// NewMultiError creates a new MultiError. Pass in one or more errors.
+func NewMultiError(err ...error) MultiError {
+	return MultiError{Errors: err}
+}
+
+// Error implents the error interface.
+func (m MultiError) Error() string {
+	errs := make([]string, len(m.Errors))
+	for i, err := range m.Errors {
+		errs[i] = err.Error()
+	}
+
+	return strings.Join(errs, "\n")
+}
+
+// ExitCoder is the interface checked by `App` and `Command` for a custom exit
+// code
+type ExitCoder interface {
+	error
+	ExitCode() int
+}
+
+// ExitError fulfills both the builtin `error` interface and `ExitCoder`
+type ExitError struct {
+	exitCode int
+	message  string
+}
+
+// NewExitError makes a new *ExitError
+func NewExitError(message string, exitCode int) *ExitError {
+	return &ExitError{
+		exitCode: exitCode,
+		message:  message,
+	}
+}
+
+// Error returns the string message, fulfilling the interface required by
+// `error`
+func (ee *ExitError) Error() string {
+	return ee.message
+}
+
+// ExitCode returns the exit code, fulfilling the interface required by
+// `ExitCoder`
+func (ee *ExitError) ExitCode() int {
+	return ee.exitCode
+}
+
+// HandleExitCoder checks if the error fulfills the ExitCoder interface, and if
+// so prints the error to stderr (if it is non-empty) and calls OsExiter with the
+// given exit code.  If the given error is a MultiError, then this func is
+// called on all members of the Errors slice.
+func HandleExitCoder(err error) {
+	if err == nil {
+		return
+	}
+
+	if exitErr, ok := err.(ExitCoder); ok {
+		if err.Error() != "" {
+			fmt.Fprintln(ErrWriter, err)
+		}
+		OsExiter(exitErr.ExitCode())
+		return
+	}
+
+	if multiErr, ok := err.(MultiError); ok {
+		for _, merr := range multiErr.Errors {
+			HandleExitCoder(merr)
+		}
+	}
+}

+ 60 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/errors_test.go

@@ -0,0 +1,60 @@
+package cli
+
+import (
+	"errors"
+	"os"
+	"testing"
+)
+
+func TestHandleExitCoder_nil(t *testing.T) {
+	exitCode := 0
+	called := false
+
+	OsExiter = func(rc int) {
+		exitCode = rc
+		called = true
+	}
+
+	defer func() { OsExiter = os.Exit }()
+
+	HandleExitCoder(nil)
+
+	expect(t, exitCode, 0)
+	expect(t, called, false)
+}
+
+func TestHandleExitCoder_ExitCoder(t *testing.T) {
+	exitCode := 0
+	called := false
+
+	OsExiter = func(rc int) {
+		exitCode = rc
+		called = true
+	}
+
+	defer func() { OsExiter = os.Exit }()
+
+	HandleExitCoder(NewExitError("galactic perimeter breach", 9))
+
+	expect(t, exitCode, 9)
+	expect(t, called, true)
+}
+
+func TestHandleExitCoder_MultiErrorWithExitCoder(t *testing.T) {
+	exitCode := 0
+	called := false
+
+	OsExiter = func(rc int) {
+		exitCode = rc
+		called = true
+	}
+
+	defer func() { OsExiter = os.Exit }()
+
+	exitErr := NewExitError("galactic perimeter breach", 9)
+	err := NewMultiError(errors.New("wowsa"), errors.New("egad"), exitErr)
+	HandleExitCoder(err)
+
+	expect(t, exitCode, 9)
+	expect(t, called, true)
+}

+ 659 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/flag.go

@@ -0,0 +1,659 @@
+package cli
+
+import (
+	"flag"
+	"fmt"
+	"os"
+	"reflect"
+	"runtime"
+	"strconv"
+	"strings"
+	"time"
+)
+
+const defaultPlaceholder = "value"
+
+// BashCompletionFlag enables bash-completion for all commands and subcommands
+var BashCompletionFlag = BoolFlag{
+	Name:   "generate-bash-completion",
+	Hidden: true,
+}
+
+// VersionFlag prints the version for the application
+var VersionFlag = BoolFlag{
+	Name:  "version, v",
+	Usage: "print the version",
+}
+
+// HelpFlag prints the help for all commands and subcommands
+// Set to the zero value (BoolFlag{}) to disable flag -- keeps subcommand
+// unless HideHelp is set to true)
+var HelpFlag = BoolFlag{
+	Name:  "help, h",
+	Usage: "show help",
+}
+
+// FlagStringer converts a flag definition to a string. This is used by help
+// to display a flag.
+var FlagStringer FlagStringFunc = stringifyFlag
+
+// Flag is a common interface related to parsing flags in cli.
+// For more advanced flag parsing techniques, it is recommended that
+// this interface be implemented.
+type Flag interface {
+	fmt.Stringer
+	// Apply Flag settings to the given flag set
+	Apply(*flag.FlagSet)
+	GetName() string
+}
+
+func flagSet(name string, flags []Flag) *flag.FlagSet {
+	set := flag.NewFlagSet(name, flag.ContinueOnError)
+
+	for _, f := range flags {
+		f.Apply(set)
+	}
+	return set
+}
+
+func eachName(longName string, fn func(string)) {
+	parts := strings.Split(longName, ",")
+	for _, name := range parts {
+		name = strings.Trim(name, " ")
+		fn(name)
+	}
+}
+
+// Generic is a generic parseable type identified by a specific flag
+type Generic interface {
+	Set(value string) error
+	String() string
+}
+
+// GenericFlag is the flag type for types implementing Generic
+type GenericFlag struct {
+	Name   string
+	Value  Generic
+	Usage  string
+	EnvVar string
+	Hidden bool
+}
+
+// String returns the string representation of the generic flag to display the
+// help text to the user (uses the String() method of the generic flag to show
+// the value)
+func (f GenericFlag) String() string {
+	return FlagStringer(f)
+}
+
+// Apply takes the flagset and calls Set on the generic flag with the value
+// provided by the user for parsing by the flag
+func (f GenericFlag) Apply(set *flag.FlagSet) {
+	val := f.Value
+	if f.EnvVar != "" {
+		for _, envVar := range strings.Split(f.EnvVar, ",") {
+			envVar = strings.TrimSpace(envVar)
+			if envVal := os.Getenv(envVar); envVal != "" {
+				val.Set(envVal)
+				break
+			}
+		}
+	}
+
+	eachName(f.Name, func(name string) {
+		set.Var(f.Value, name, f.Usage)
+	})
+}
+
+// GetName returns the name of a flag.
+func (f GenericFlag) GetName() string {
+	return f.Name
+}
+
+// StringSlice is an opaque type for []string to satisfy flag.Value
+type StringSlice []string
+
+// Set appends the string value to the list of values
+func (f *StringSlice) Set(value string) error {
+	*f = append(*f, value)
+	return nil
+}
+
+// String returns a readable representation of this value (for usage defaults)
+func (f *StringSlice) String() string {
+	return fmt.Sprintf("%s", *f)
+}
+
+// Value returns the slice of strings set by this flag
+func (f *StringSlice) Value() []string {
+	return *f
+}
+
+// StringSliceFlag is a string flag that can be specified multiple times on the
+// command-line
+type StringSliceFlag struct {
+	Name   string
+	Value  *StringSlice
+	Usage  string
+	EnvVar string
+	Hidden bool
+}
+
+// String returns the usage
+func (f StringSliceFlag) String() string {
+	return FlagStringer(f)
+}
+
+// Apply populates the flag given the flag set and environment
+func (f StringSliceFlag) Apply(set *flag.FlagSet) {
+	if f.EnvVar != "" {
+		for _, envVar := range strings.Split(f.EnvVar, ",") {
+			envVar = strings.TrimSpace(envVar)
+			if envVal := os.Getenv(envVar); envVal != "" {
+				newVal := &StringSlice{}
+				for _, s := range strings.Split(envVal, ",") {
+					s = strings.TrimSpace(s)
+					newVal.Set(s)
+				}
+				f.Value = newVal
+				break
+			}
+		}
+	}
+
+	eachName(f.Name, func(name string) {
+		if f.Value == nil {
+			f.Value = &StringSlice{}
+		}
+		set.Var(f.Value, name, f.Usage)
+	})
+}
+
+// GetName returns the name of a flag.
+func (f StringSliceFlag) GetName() string {
+	return f.Name
+}
+
+// IntSlice is an opaque type for []int to satisfy flag.Value
+type IntSlice []int
+
+// Set parses the value into an integer and appends it to the list of values
+func (f *IntSlice) Set(value string) error {
+	tmp, err := strconv.Atoi(value)
+	if err != nil {
+		return err
+	}
+	*f = append(*f, tmp)
+	return nil
+}
+
+// String returns a readable representation of this value (for usage defaults)
+func (f *IntSlice) String() string {
+	return fmt.Sprintf("%d", *f)
+}
+
+// Value returns the slice of ints set by this flag
+func (f *IntSlice) Value() []int {
+	return *f
+}
+
+// IntSliceFlag is an int flag that can be specified multiple times on the
+// command-line
+type IntSliceFlag struct {
+	Name   string
+	Value  *IntSlice
+	Usage  string
+	EnvVar string
+	Hidden bool
+}
+
+// String returns the usage
+func (f IntSliceFlag) String() string {
+	return FlagStringer(f)
+}
+
+// Apply populates the flag given the flag set and environment
+func (f IntSliceFlag) Apply(set *flag.FlagSet) {
+	if f.EnvVar != "" {
+		for _, envVar := range strings.Split(f.EnvVar, ",") {
+			envVar = strings.TrimSpace(envVar)
+			if envVal := os.Getenv(envVar); envVal != "" {
+				newVal := &IntSlice{}
+				for _, s := range strings.Split(envVal, ",") {
+					s = strings.TrimSpace(s)
+					err := newVal.Set(s)
+					if err != nil {
+						fmt.Fprintf(ErrWriter, err.Error())
+					}
+				}
+				f.Value = newVal
+				break
+			}
+		}
+	}
+
+	eachName(f.Name, func(name string) {
+		if f.Value == nil {
+			f.Value = &IntSlice{}
+		}
+		set.Var(f.Value, name, f.Usage)
+	})
+}
+
+// GetName returns the name of the flag.
+func (f IntSliceFlag) GetName() string {
+	return f.Name
+}
+
+// BoolFlag is a switch that defaults to false
+type BoolFlag struct {
+	Name        string
+	Usage       string
+	EnvVar      string
+	Destination *bool
+	Hidden      bool
+}
+
+// String returns a readable representation of this value (for usage defaults)
+func (f BoolFlag) String() string {
+	return FlagStringer(f)
+}
+
+// Apply populates the flag given the flag set and environment
+func (f BoolFlag) Apply(set *flag.FlagSet) {
+	val := false
+	if f.EnvVar != "" {
+		for _, envVar := range strings.Split(f.EnvVar, ",") {
+			envVar = strings.TrimSpace(envVar)
+			if envVal := os.Getenv(envVar); envVal != "" {
+				envValBool, err := strconv.ParseBool(envVal)
+				if err == nil {
+					val = envValBool
+				}
+				break
+			}
+		}
+	}
+
+	eachName(f.Name, func(name string) {
+		if f.Destination != nil {
+			set.BoolVar(f.Destination, name, val, f.Usage)
+			return
+		}
+		set.Bool(name, val, f.Usage)
+	})
+}
+
+// GetName returns the name of the flag.
+func (f BoolFlag) GetName() string {
+	return f.Name
+}
+
+// BoolTFlag this represents a boolean flag that is true by default, but can
+// still be set to false by --some-flag=false
+type BoolTFlag struct {
+	Name        string
+	Usage       string
+	EnvVar      string
+	Destination *bool
+	Hidden      bool
+}
+
+// String returns a readable representation of this value (for usage defaults)
+func (f BoolTFlag) String() string {
+	return FlagStringer(f)
+}
+
+// Apply populates the flag given the flag set and environment
+func (f BoolTFlag) Apply(set *flag.FlagSet) {
+	val := true
+	if f.EnvVar != "" {
+		for _, envVar := range strings.Split(f.EnvVar, ",") {
+			envVar = strings.TrimSpace(envVar)
+			if envVal := os.Getenv(envVar); envVal != "" {
+				envValBool, err := strconv.ParseBool(envVal)
+				if err == nil {
+					val = envValBool
+					break
+				}
+			}
+		}
+	}
+
+	eachName(f.Name, func(name string) {
+		if f.Destination != nil {
+			set.BoolVar(f.Destination, name, val, f.Usage)
+			return
+		}
+		set.Bool(name, val, f.Usage)
+	})
+}
+
+// GetName returns the name of the flag.
+func (f BoolTFlag) GetName() string {
+	return f.Name
+}
+
+// StringFlag represents a flag that takes as string value
+type StringFlag struct {
+	Name        string
+	Value       string
+	Usage       string
+	EnvVar      string
+	Destination *string
+	Hidden      bool
+}
+
+// String returns the usage
+func (f StringFlag) String() string {
+	return FlagStringer(f)
+}
+
+// Apply populates the flag given the flag set and environment
+func (f StringFlag) Apply(set *flag.FlagSet) {
+	if f.EnvVar != "" {
+		for _, envVar := range strings.Split(f.EnvVar, ",") {
+			envVar = strings.TrimSpace(envVar)
+			if envVal := os.Getenv(envVar); envVal != "" {
+				f.Value = envVal
+				break
+			}
+		}
+	}
+
+	eachName(f.Name, func(name string) {
+		if f.Destination != nil {
+			set.StringVar(f.Destination, name, f.Value, f.Usage)
+			return
+		}
+		set.String(name, f.Value, f.Usage)
+	})
+}
+
+// GetName returns the name of the flag.
+func (f StringFlag) GetName() string {
+	return f.Name
+}
+
+// IntFlag is a flag that takes an integer
+// Errors if the value provided cannot be parsed
+type IntFlag struct {
+	Name        string
+	Value       int
+	Usage       string
+	EnvVar      string
+	Destination *int
+	Hidden      bool
+}
+
+// String returns the usage
+func (f IntFlag) String() string {
+	return FlagStringer(f)
+}
+
+// Apply populates the flag given the flag set and environment
+func (f IntFlag) Apply(set *flag.FlagSet) {
+	if f.EnvVar != "" {
+		for _, envVar := range strings.Split(f.EnvVar, ",") {
+			envVar = strings.TrimSpace(envVar)
+			if envVal := os.Getenv(envVar); envVal != "" {
+				envValInt, err := strconv.ParseInt(envVal, 0, 64)
+				if err == nil {
+					f.Value = int(envValInt)
+					break
+				}
+			}
+		}
+	}
+
+	eachName(f.Name, func(name string) {
+		if f.Destination != nil {
+			set.IntVar(f.Destination, name, f.Value, f.Usage)
+			return
+		}
+		set.Int(name, f.Value, f.Usage)
+	})
+}
+
+// GetName returns the name of the flag.
+func (f IntFlag) GetName() string {
+	return f.Name
+}
+
+// DurationFlag is a flag that takes a duration specified in Go's duration
+// format: https://golang.org/pkg/time/#ParseDuration
+type DurationFlag struct {
+	Name        string
+	Value       time.Duration
+	Usage       string
+	EnvVar      string
+	Destination *time.Duration
+	Hidden      bool
+}
+
+// String returns a readable representation of this value (for usage defaults)
+func (f DurationFlag) String() string {
+	return FlagStringer(f)
+}
+
+// Apply populates the flag given the flag set and environment
+func (f DurationFlag) Apply(set *flag.FlagSet) {
+	if f.EnvVar != "" {
+		for _, envVar := range strings.Split(f.EnvVar, ",") {
+			envVar = strings.TrimSpace(envVar)
+			if envVal := os.Getenv(envVar); envVal != "" {
+				envValDuration, err := time.ParseDuration(envVal)
+				if err == nil {
+					f.Value = envValDuration
+					break
+				}
+			}
+		}
+	}
+
+	eachName(f.Name, func(name string) {
+		if f.Destination != nil {
+			set.DurationVar(f.Destination, name, f.Value, f.Usage)
+			return
+		}
+		set.Duration(name, f.Value, f.Usage)
+	})
+}
+
+// GetName returns the name of the flag.
+func (f DurationFlag) GetName() string {
+	return f.Name
+}
+
+// Float64Flag is a flag that takes an float value
+// Errors if the value provided cannot be parsed
+type Float64Flag struct {
+	Name        string
+	Value       float64
+	Usage       string
+	EnvVar      string
+	Destination *float64
+	Hidden      bool
+}
+
+// String returns the usage
+func (f Float64Flag) String() string {
+	return FlagStringer(f)
+}
+
+// Apply populates the flag given the flag set and environment
+func (f Float64Flag) Apply(set *flag.FlagSet) {
+	if f.EnvVar != "" {
+		for _, envVar := range strings.Split(f.EnvVar, ",") {
+			envVar = strings.TrimSpace(envVar)
+			if envVal := os.Getenv(envVar); envVal != "" {
+				envValFloat, err := strconv.ParseFloat(envVal, 10)
+				if err == nil {
+					f.Value = float64(envValFloat)
+				}
+			}
+		}
+	}
+
+	eachName(f.Name, func(name string) {
+		if f.Destination != nil {
+			set.Float64Var(f.Destination, name, f.Value, f.Usage)
+			return
+		}
+		set.Float64(name, f.Value, f.Usage)
+	})
+}
+
+// GetName returns the name of the flag.
+func (f Float64Flag) GetName() string {
+	return f.Name
+}
+
+func visibleFlags(fl []Flag) []Flag {
+	visible := []Flag{}
+	for _, flag := range fl {
+		if !reflect.ValueOf(flag).FieldByName("Hidden").Bool() {
+			visible = append(visible, flag)
+		}
+	}
+	return visible
+}
+
+func prefixFor(name string) (prefix string) {
+	if len(name) == 1 {
+		prefix = "-"
+	} else {
+		prefix = "--"
+	}
+
+	return
+}
+
+// Returns the placeholder, if any, and the unquoted usage string.
+func unquoteUsage(usage string) (string, string) {
+	for i := 0; i < len(usage); i++ {
+		if usage[i] == '`' {
+			for j := i + 1; j < len(usage); j++ {
+				if usage[j] == '`' {
+					name := usage[i+1 : j]
+					usage = usage[:i] + name + usage[j+1:]
+					return name, usage
+				}
+			}
+			break
+		}
+	}
+	return "", usage
+}
+
+func prefixedNames(fullName, placeholder string) string {
+	var prefixed string
+	parts := strings.Split(fullName, ",")
+	for i, name := range parts {
+		name = strings.Trim(name, " ")
+		prefixed += prefixFor(name) + name
+		if placeholder != "" {
+			prefixed += " " + placeholder
+		}
+		if i < len(parts)-1 {
+			prefixed += ", "
+		}
+	}
+	return prefixed
+}
+
+func withEnvHint(envVar, str string) string {
+	envText := ""
+	if envVar != "" {
+		prefix := "$"
+		suffix := ""
+		sep := ", $"
+		if runtime.GOOS == "windows" {
+			prefix = "%"
+			suffix = "%"
+			sep = "%, %"
+		}
+		envText = fmt.Sprintf(" [%s%s%s]", prefix, strings.Join(strings.Split(envVar, ","), sep), suffix)
+	}
+	return str + envText
+}
+
+func stringifyFlag(f Flag) string {
+	fv := reflect.ValueOf(f)
+
+	switch f.(type) {
+	case IntSliceFlag:
+		return withEnvHint(fv.FieldByName("EnvVar").String(),
+			stringifyIntSliceFlag(f.(IntSliceFlag)))
+	case StringSliceFlag:
+		return withEnvHint(fv.FieldByName("EnvVar").String(),
+			stringifyStringSliceFlag(f.(StringSliceFlag)))
+	}
+
+	placeholder, usage := unquoteUsage(fv.FieldByName("Usage").String())
+
+	needsPlaceholder := false
+	defaultValueString := ""
+	val := fv.FieldByName("Value")
+
+	if val.IsValid() {
+		needsPlaceholder = true
+		defaultValueString = fmt.Sprintf(" (default: %v)", val.Interface())
+
+		if val.Kind() == reflect.String && val.String() != "" {
+			defaultValueString = fmt.Sprintf(" (default: %q)", val.String())
+		}
+	}
+
+	if defaultValueString == " (default: )" {
+		defaultValueString = ""
+	}
+
+	if needsPlaceholder && placeholder == "" {
+		placeholder = defaultPlaceholder
+	}
+
+	usageWithDefault := strings.TrimSpace(fmt.Sprintf("%s%s", usage, defaultValueString))
+
+	return withEnvHint(fv.FieldByName("EnvVar").String(),
+		fmt.Sprintf("%s\t%s", prefixedNames(fv.FieldByName("Name").String(), placeholder), usageWithDefault))
+}
+
+func stringifyIntSliceFlag(f IntSliceFlag) string {
+	defaultVals := []string{}
+	if f.Value != nil && len(f.Value.Value()) > 0 {
+		for _, i := range f.Value.Value() {
+			defaultVals = append(defaultVals, fmt.Sprintf("%d", i))
+		}
+	}
+
+	return stringifySliceFlag(f.Usage, f.Name, defaultVals)
+}
+
+func stringifyStringSliceFlag(f StringSliceFlag) string {
+	defaultVals := []string{}
+	if f.Value != nil && len(f.Value.Value()) > 0 {
+		for _, s := range f.Value.Value() {
+			if len(s) > 0 {
+				defaultVals = append(defaultVals, fmt.Sprintf("%q", s))
+			}
+		}
+	}
+
+	return stringifySliceFlag(f.Usage, f.Name, defaultVals)
+}
+
+func stringifySliceFlag(usage, name string, defaultVals []string) string {
+	placeholder, usage := unquoteUsage(usage)
+	if placeholder == "" {
+		placeholder = defaultPlaceholder
+	}
+
+	defaultVal := ""
+	if len(defaultVals) > 0 {
+		defaultVal = fmt.Sprintf(" (default: %s)", strings.Join(defaultVals, ", "))
+	}
+
+	usageWithDefault := strings.TrimSpace(fmt.Sprintf("%s%s", usage, defaultVal))
+	return fmt.Sprintf("%s\t%s", prefixedNames(name, placeholder), usageWithDefault)
+}

+ 884 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/flag_test.go

@@ -0,0 +1,884 @@
+package cli
+
+import (
+	"fmt"
+	"os"
+	"reflect"
+	"runtime"
+	"strings"
+	"testing"
+	"time"
+)
+
+var boolFlagTests = []struct {
+	name     string
+	expected string
+}{
+	{"help", "--help\t"},
+	{"h", "-h\t"},
+}
+
+func TestBoolFlagHelpOutput(t *testing.T) {
+	for _, test := range boolFlagTests {
+		flag := BoolFlag{Name: test.name}
+		output := flag.String()
+
+		if output != test.expected {
+			t.Errorf("%q does not match %q", output, test.expected)
+		}
+	}
+}
+
+var stringFlagTests = []struct {
+	name     string
+	usage    string
+	value    string
+	expected string
+}{
+	{"foo", "", "", "--foo value\t"},
+	{"f", "", "", "-f value\t"},
+	{"f", "The total `foo` desired", "all", "-f foo\tThe total foo desired (default: \"all\")"},
+	{"test", "", "Something", "--test value\t(default: \"Something\")"},
+	{"config,c", "Load configuration from `FILE`", "", "--config FILE, -c FILE\tLoad configuration from FILE"},
+	{"config,c", "Load configuration from `CONFIG`", "config.json", "--config CONFIG, -c CONFIG\tLoad configuration from CONFIG (default: \"config.json\")"},
+}
+
+func TestStringFlagHelpOutput(t *testing.T) {
+	for _, test := range stringFlagTests {
+		flag := StringFlag{Name: test.name, Usage: test.usage, Value: test.value}
+		output := flag.String()
+
+		if output != test.expected {
+			t.Errorf("%q does not match %q", output, test.expected)
+		}
+	}
+}
+
+func TestStringFlagWithEnvVarHelpOutput(t *testing.T) {
+	os.Clearenv()
+	os.Setenv("APP_FOO", "derp")
+	for _, test := range stringFlagTests {
+		flag := StringFlag{Name: test.name, Value: test.value, EnvVar: "APP_FOO"}
+		output := flag.String()
+
+		expectedSuffix := " [$APP_FOO]"
+		if runtime.GOOS == "windows" {
+			expectedSuffix = " [%APP_FOO%]"
+		}
+		if !strings.HasSuffix(output, expectedSuffix) {
+			t.Errorf("%s does not end with"+expectedSuffix, output)
+		}
+	}
+}
+
+var stringSliceFlagTests = []struct {
+	name     string
+	value    *StringSlice
+	expected string
+}{
+	{"foo", func() *StringSlice {
+		s := &StringSlice{}
+		s.Set("")
+		return s
+	}(), "--foo value\t"},
+	{"f", func() *StringSlice {
+		s := &StringSlice{}
+		s.Set("")
+		return s
+	}(), "-f value\t"},
+	{"f", func() *StringSlice {
+		s := &StringSlice{}
+		s.Set("Lipstick")
+		return s
+	}(), "-f value\t(default: \"Lipstick\")"},
+	{"test", func() *StringSlice {
+		s := &StringSlice{}
+		s.Set("Something")
+		return s
+	}(), "--test value\t(default: \"Something\")"},
+}
+
+func TestStringSliceFlagHelpOutput(t *testing.T) {
+	for _, test := range stringSliceFlagTests {
+		flag := StringSliceFlag{Name: test.name, Value: test.value}
+		output := flag.String()
+
+		if output != test.expected {
+			t.Errorf("%q does not match %q", output, test.expected)
+		}
+	}
+}
+
+func TestStringSliceFlagWithEnvVarHelpOutput(t *testing.T) {
+	os.Clearenv()
+	os.Setenv("APP_QWWX", "11,4")
+	for _, test := range stringSliceFlagTests {
+		flag := StringSliceFlag{Name: test.name, Value: test.value, EnvVar: "APP_QWWX"}
+		output := flag.String()
+
+		expectedSuffix := " [$APP_QWWX]"
+		if runtime.GOOS == "windows" {
+			expectedSuffix = " [%APP_QWWX%]"
+		}
+		if !strings.HasSuffix(output, expectedSuffix) {
+			t.Errorf("%q does not end with"+expectedSuffix, output)
+		}
+	}
+}
+
+var intFlagTests = []struct {
+	name     string
+	expected string
+}{
+	{"hats", "--hats value\t(default: 9)"},
+	{"H", "-H value\t(default: 9)"},
+}
+
+func TestIntFlagHelpOutput(t *testing.T) {
+	for _, test := range intFlagTests {
+		flag := IntFlag{Name: test.name, Value: 9}
+		output := flag.String()
+
+		if output != test.expected {
+			t.Errorf("%s does not match %s", output, test.expected)
+		}
+	}
+}
+
+func TestIntFlagWithEnvVarHelpOutput(t *testing.T) {
+	os.Clearenv()
+	os.Setenv("APP_BAR", "2")
+	for _, test := range intFlagTests {
+		flag := IntFlag{Name: test.name, EnvVar: "APP_BAR"}
+		output := flag.String()
+
+		expectedSuffix := " [$APP_BAR]"
+		if runtime.GOOS == "windows" {
+			expectedSuffix = " [%APP_BAR%]"
+		}
+		if !strings.HasSuffix(output, expectedSuffix) {
+			t.Errorf("%s does not end with"+expectedSuffix, output)
+		}
+	}
+}
+
+var durationFlagTests = []struct {
+	name     string
+	expected string
+}{
+	{"hooting", "--hooting value\t(default: 1s)"},
+	{"H", "-H value\t(default: 1s)"},
+}
+
+func TestDurationFlagHelpOutput(t *testing.T) {
+	for _, test := range durationFlagTests {
+		flag := DurationFlag{Name: test.name, Value: 1 * time.Second}
+		output := flag.String()
+
+		if output != test.expected {
+			t.Errorf("%q does not match %q", output, test.expected)
+		}
+	}
+}
+
+func TestDurationFlagWithEnvVarHelpOutput(t *testing.T) {
+	os.Clearenv()
+	os.Setenv("APP_BAR", "2h3m6s")
+	for _, test := range durationFlagTests {
+		flag := DurationFlag{Name: test.name, EnvVar: "APP_BAR"}
+		output := flag.String()
+
+		expectedSuffix := " [$APP_BAR]"
+		if runtime.GOOS == "windows" {
+			expectedSuffix = " [%APP_BAR%]"
+		}
+		if !strings.HasSuffix(output, expectedSuffix) {
+			t.Errorf("%s does not end with"+expectedSuffix, output)
+		}
+	}
+}
+
+var intSliceFlagTests = []struct {
+	name     string
+	value    *IntSlice
+	expected string
+}{
+	{"heads", &IntSlice{}, "--heads value\t"},
+	{"H", &IntSlice{}, "-H value\t"},
+	{"H, heads", func() *IntSlice {
+		i := &IntSlice{}
+		i.Set("9")
+		i.Set("3")
+		return i
+	}(), "-H value, --heads value\t(default: 9, 3)"},
+}
+
+func TestIntSliceFlagHelpOutput(t *testing.T) {
+	for _, test := range intSliceFlagTests {
+		flag := IntSliceFlag{Name: test.name, Value: test.value}
+		output := flag.String()
+
+		if output != test.expected {
+			t.Errorf("%q does not match %q", output, test.expected)
+		}
+	}
+}
+
+func TestIntSliceFlagWithEnvVarHelpOutput(t *testing.T) {
+	os.Clearenv()
+	os.Setenv("APP_SMURF", "42,3")
+	for _, test := range intSliceFlagTests {
+		flag := IntSliceFlag{Name: test.name, Value: test.value, EnvVar: "APP_SMURF"}
+		output := flag.String()
+
+		expectedSuffix := " [$APP_SMURF]"
+		if runtime.GOOS == "windows" {
+			expectedSuffix = " [%APP_SMURF%]"
+		}
+		if !strings.HasSuffix(output, expectedSuffix) {
+			t.Errorf("%q does not end with"+expectedSuffix, output)
+		}
+	}
+}
+
+var float64FlagTests = []struct {
+	name     string
+	expected string
+}{
+	{"hooting", "--hooting value\t(default: 0.1)"},
+	{"H", "-H value\t(default: 0.1)"},
+}
+
+func TestFloat64FlagHelpOutput(t *testing.T) {
+	for _, test := range float64FlagTests {
+		flag := Float64Flag{Name: test.name, Value: float64(0.1)}
+		output := flag.String()
+
+		if output != test.expected {
+			t.Errorf("%q does not match %q", output, test.expected)
+		}
+	}
+}
+
+func TestFloat64FlagWithEnvVarHelpOutput(t *testing.T) {
+	os.Clearenv()
+	os.Setenv("APP_BAZ", "99.4")
+	for _, test := range float64FlagTests {
+		flag := Float64Flag{Name: test.name, EnvVar: "APP_BAZ"}
+		output := flag.String()
+
+		expectedSuffix := " [$APP_BAZ]"
+		if runtime.GOOS == "windows" {
+			expectedSuffix = " [%APP_BAZ%]"
+		}
+		if !strings.HasSuffix(output, expectedSuffix) {
+			t.Errorf("%s does not end with"+expectedSuffix, output)
+		}
+	}
+}
+
+var genericFlagTests = []struct {
+	name     string
+	value    Generic
+	expected string
+}{
+	{"toads", &Parser{"abc", "def"}, "--toads value\ttest flag (default: abc,def)"},
+	{"t", &Parser{"abc", "def"}, "-t value\ttest flag (default: abc,def)"},
+}
+
+func TestGenericFlagHelpOutput(t *testing.T) {
+	for _, test := range genericFlagTests {
+		flag := GenericFlag{Name: test.name, Value: test.value, Usage: "test flag"}
+		output := flag.String()
+
+		if output != test.expected {
+			t.Errorf("%q does not match %q", output, test.expected)
+		}
+	}
+}
+
+func TestGenericFlagWithEnvVarHelpOutput(t *testing.T) {
+	os.Clearenv()
+	os.Setenv("APP_ZAP", "3")
+	for _, test := range genericFlagTests {
+		flag := GenericFlag{Name: test.name, EnvVar: "APP_ZAP"}
+		output := flag.String()
+
+		expectedSuffix := " [$APP_ZAP]"
+		if runtime.GOOS == "windows" {
+			expectedSuffix = " [%APP_ZAP%]"
+		}
+		if !strings.HasSuffix(output, expectedSuffix) {
+			t.Errorf("%s does not end with"+expectedSuffix, output)
+		}
+	}
+}
+
+func TestParseMultiString(t *testing.T) {
+	(&App{
+		Flags: []Flag{
+			StringFlag{Name: "serve, s"},
+		},
+		Action: func(ctx *Context) error {
+			if ctx.String("serve") != "10" {
+				t.Errorf("main name not set")
+			}
+			if ctx.String("s") != "10" {
+				t.Errorf("short name not set")
+			}
+			return nil
+		},
+	}).Run([]string{"run", "-s", "10"})
+}
+
+func TestParseDestinationString(t *testing.T) {
+	var dest string
+	a := App{
+		Flags: []Flag{
+			StringFlag{
+				Name:        "dest",
+				Destination: &dest,
+			},
+		},
+		Action: func(ctx *Context) error {
+			if dest != "10" {
+				t.Errorf("expected destination String 10")
+			}
+			return nil
+		},
+	}
+	a.Run([]string{"run", "--dest", "10"})
+}
+
+func TestParseMultiStringFromEnv(t *testing.T) {
+	os.Clearenv()
+	os.Setenv("APP_COUNT", "20")
+	(&App{
+		Flags: []Flag{
+			StringFlag{Name: "count, c", EnvVar: "APP_COUNT"},
+		},
+		Action: func(ctx *Context) error {
+			if ctx.String("count") != "20" {
+				t.Errorf("main name not set")
+			}
+			if ctx.String("c") != "20" {
+				t.Errorf("short name not set")
+			}
+			return nil
+		},
+	}).Run([]string{"run"})
+}
+
+func TestParseMultiStringFromEnvCascade(t *testing.T) {
+	os.Clearenv()
+	os.Setenv("APP_COUNT", "20")
+	(&App{
+		Flags: []Flag{
+			StringFlag{Name: "count, c", EnvVar: "COMPAT_COUNT,APP_COUNT"},
+		},
+		Action: func(ctx *Context) error {
+			if ctx.String("count") != "20" {
+				t.Errorf("main name not set")
+			}
+			if ctx.String("c") != "20" {
+				t.Errorf("short name not set")
+			}
+			return nil
+		},
+	}).Run([]string{"run"})
+}
+
+func TestParseMultiStringSlice(t *testing.T) {
+	(&App{
+		Flags: []Flag{
+			StringSliceFlag{Name: "serve, s", Value: &StringSlice{}},
+		},
+		Action: func(ctx *Context) error {
+			if !reflect.DeepEqual(ctx.StringSlice("serve"), []string{"10", "20"}) {
+				t.Errorf("main name not set")
+			}
+			if !reflect.DeepEqual(ctx.StringSlice("s"), []string{"10", "20"}) {
+				t.Errorf("short name not set")
+			}
+			return nil
+		},
+	}).Run([]string{"run", "-s", "10", "-s", "20"})
+}
+
+func TestParseMultiStringSliceFromEnv(t *testing.T) {
+	os.Clearenv()
+	os.Setenv("APP_INTERVALS", "20,30,40")
+
+	(&App{
+		Flags: []Flag{
+			StringSliceFlag{Name: "intervals, i", Value: &StringSlice{}, EnvVar: "APP_INTERVALS"},
+		},
+		Action: func(ctx *Context) error {
+			if !reflect.DeepEqual(ctx.StringSlice("intervals"), []string{"20", "30", "40"}) {
+				t.Errorf("main name not set from env")
+			}
+			if !reflect.DeepEqual(ctx.StringSlice("i"), []string{"20", "30", "40"}) {
+				t.Errorf("short name not set from env")
+			}
+			return nil
+		},
+	}).Run([]string{"run"})
+}
+
+func TestParseMultiStringSliceFromEnvCascade(t *testing.T) {
+	os.Clearenv()
+	os.Setenv("APP_INTERVALS", "20,30,40")
+
+	(&App{
+		Flags: []Flag{
+			StringSliceFlag{Name: "intervals, i", Value: &StringSlice{}, EnvVar: "COMPAT_INTERVALS,APP_INTERVALS"},
+		},
+		Action: func(ctx *Context) error {
+			if !reflect.DeepEqual(ctx.StringSlice("intervals"), []string{"20", "30", "40"}) {
+				t.Errorf("main name not set from env")
+			}
+			if !reflect.DeepEqual(ctx.StringSlice("i"), []string{"20", "30", "40"}) {
+				t.Errorf("short name not set from env")
+			}
+			return nil
+		},
+	}).Run([]string{"run"})
+}
+
+func TestParseMultiInt(t *testing.T) {
+	a := App{
+		Flags: []Flag{
+			IntFlag{Name: "serve, s"},
+		},
+		Action: func(ctx *Context) error {
+			if ctx.Int("serve") != 10 {
+				t.Errorf("main name not set")
+			}
+			if ctx.Int("s") != 10 {
+				t.Errorf("short name not set")
+			}
+			return nil
+		},
+	}
+	a.Run([]string{"run", "-s", "10"})
+}
+
+func TestParseDestinationInt(t *testing.T) {
+	var dest int
+	a := App{
+		Flags: []Flag{
+			IntFlag{
+				Name:        "dest",
+				Destination: &dest,
+			},
+		},
+		Action: func(ctx *Context) error {
+			if dest != 10 {
+				t.Errorf("expected destination Int 10")
+			}
+			return nil
+		},
+	}
+	a.Run([]string{"run", "--dest", "10"})
+}
+
+func TestParseMultiIntFromEnv(t *testing.T) {
+	os.Clearenv()
+	os.Setenv("APP_TIMEOUT_SECONDS", "10")
+	a := App{
+		Flags: []Flag{
+			IntFlag{Name: "timeout, t", EnvVar: "APP_TIMEOUT_SECONDS"},
+		},
+		Action: func(ctx *Context) error {
+			if ctx.Int("timeout") != 10 {
+				t.Errorf("main name not set")
+			}
+			if ctx.Int("t") != 10 {
+				t.Errorf("short name not set")
+			}
+			return nil
+		},
+	}
+	a.Run([]string{"run"})
+}
+
+func TestParseMultiIntFromEnvCascade(t *testing.T) {
+	os.Clearenv()
+	os.Setenv("APP_TIMEOUT_SECONDS", "10")
+	a := App{
+		Flags: []Flag{
+			IntFlag{Name: "timeout, t", EnvVar: "COMPAT_TIMEOUT_SECONDS,APP_TIMEOUT_SECONDS"},
+		},
+		Action: func(ctx *Context) error {
+			if ctx.Int("timeout") != 10 {
+				t.Errorf("main name not set")
+			}
+			if ctx.Int("t") != 10 {
+				t.Errorf("short name not set")
+			}
+			return nil
+		},
+	}
+	a.Run([]string{"run"})
+}
+
+func TestParseMultiIntSlice(t *testing.T) {
+	(&App{
+		Flags: []Flag{
+			IntSliceFlag{Name: "serve, s", Value: &IntSlice{}},
+		},
+		Action: func(ctx *Context) error {
+			if !reflect.DeepEqual(ctx.IntSlice("serve"), []int{10, 20}) {
+				t.Errorf("main name not set")
+			}
+			if !reflect.DeepEqual(ctx.IntSlice("s"), []int{10, 20}) {
+				t.Errorf("short name not set")
+			}
+			return nil
+		},
+	}).Run([]string{"run", "-s", "10", "-s", "20"})
+}
+
+func TestParseMultiIntSliceFromEnv(t *testing.T) {
+	os.Clearenv()
+	os.Setenv("APP_INTERVALS", "20,30,40")
+
+	(&App{
+		Flags: []Flag{
+			IntSliceFlag{Name: "intervals, i", Value: &IntSlice{}, EnvVar: "APP_INTERVALS"},
+		},
+		Action: func(ctx *Context) error {
+			if !reflect.DeepEqual(ctx.IntSlice("intervals"), []int{20, 30, 40}) {
+				t.Errorf("main name not set from env")
+			}
+			if !reflect.DeepEqual(ctx.IntSlice("i"), []int{20, 30, 40}) {
+				t.Errorf("short name not set from env")
+			}
+			return nil
+		},
+	}).Run([]string{"run"})
+}
+
+func TestParseMultiIntSliceFromEnvCascade(t *testing.T) {
+	os.Clearenv()
+	os.Setenv("APP_INTERVALS", "20,30,40")
+
+	(&App{
+		Flags: []Flag{
+			IntSliceFlag{Name: "intervals, i", Value: &IntSlice{}, EnvVar: "COMPAT_INTERVALS,APP_INTERVALS"},
+		},
+		Action: func(ctx *Context) error {
+			if !reflect.DeepEqual(ctx.IntSlice("intervals"), []int{20, 30, 40}) {
+				t.Errorf("main name not set from env")
+			}
+			if !reflect.DeepEqual(ctx.IntSlice("i"), []int{20, 30, 40}) {
+				t.Errorf("short name not set from env")
+			}
+			return nil
+		},
+	}).Run([]string{"run"})
+}
+
+func TestParseMultiFloat64(t *testing.T) {
+	a := App{
+		Flags: []Flag{
+			Float64Flag{Name: "serve, s"},
+		},
+		Action: func(ctx *Context) error {
+			if ctx.Float64("serve") != 10.2 {
+				t.Errorf("main name not set")
+			}
+			if ctx.Float64("s") != 10.2 {
+				t.Errorf("short name not set")
+			}
+			return nil
+		},
+	}
+	a.Run([]string{"run", "-s", "10.2"})
+}
+
+func TestParseDestinationFloat64(t *testing.T) {
+	var dest float64
+	a := App{
+		Flags: []Flag{
+			Float64Flag{
+				Name:        "dest",
+				Destination: &dest,
+			},
+		},
+		Action: func(ctx *Context) error {
+			if dest != 10.2 {
+				t.Errorf("expected destination Float64 10.2")
+			}
+			return nil
+		},
+	}
+	a.Run([]string{"run", "--dest", "10.2"})
+}
+
+func TestParseMultiFloat64FromEnv(t *testing.T) {
+	os.Clearenv()
+	os.Setenv("APP_TIMEOUT_SECONDS", "15.5")
+	a := App{
+		Flags: []Flag{
+			Float64Flag{Name: "timeout, t", EnvVar: "APP_TIMEOUT_SECONDS"},
+		},
+		Action: func(ctx *Context) error {
+			if ctx.Float64("timeout") != 15.5 {
+				t.Errorf("main name not set")
+			}
+			if ctx.Float64("t") != 15.5 {
+				t.Errorf("short name not set")
+			}
+			return nil
+		},
+	}
+	a.Run([]string{"run"})
+}
+
+func TestParseMultiFloat64FromEnvCascade(t *testing.T) {
+	os.Clearenv()
+	os.Setenv("APP_TIMEOUT_SECONDS", "15.5")
+	a := App{
+		Flags: []Flag{
+			Float64Flag{Name: "timeout, t", EnvVar: "COMPAT_TIMEOUT_SECONDS,APP_TIMEOUT_SECONDS"},
+		},
+		Action: func(ctx *Context) error {
+			if ctx.Float64("timeout") != 15.5 {
+				t.Errorf("main name not set")
+			}
+			if ctx.Float64("t") != 15.5 {
+				t.Errorf("short name not set")
+			}
+			return nil
+		},
+	}
+	a.Run([]string{"run"})
+}
+
+func TestParseMultiBool(t *testing.T) {
+	a := App{
+		Flags: []Flag{
+			BoolFlag{Name: "serve, s"},
+		},
+		Action: func(ctx *Context) error {
+			if ctx.Bool("serve") != true {
+				t.Errorf("main name not set")
+			}
+			if ctx.Bool("s") != true {
+				t.Errorf("short name not set")
+			}
+			return nil
+		},
+	}
+	a.Run([]string{"run", "--serve"})
+}
+
+func TestParseDestinationBool(t *testing.T) {
+	var dest bool
+	a := App{
+		Flags: []Flag{
+			BoolFlag{
+				Name:        "dest",
+				Destination: &dest,
+			},
+		},
+		Action: func(ctx *Context) error {
+			if dest != true {
+				t.Errorf("expected destination Bool true")
+			}
+			return nil
+		},
+	}
+	a.Run([]string{"run", "--dest"})
+}
+
+func TestParseMultiBoolFromEnv(t *testing.T) {
+	os.Clearenv()
+	os.Setenv("APP_DEBUG", "1")
+	a := App{
+		Flags: []Flag{
+			BoolFlag{Name: "debug, d", EnvVar: "APP_DEBUG"},
+		},
+		Action: func(ctx *Context) error {
+			if ctx.Bool("debug") != true {
+				t.Errorf("main name not set from env")
+			}
+			if ctx.Bool("d") != true {
+				t.Errorf("short name not set from env")
+			}
+			return nil
+		},
+	}
+	a.Run([]string{"run"})
+}
+
+func TestParseMultiBoolFromEnvCascade(t *testing.T) {
+	os.Clearenv()
+	os.Setenv("APP_DEBUG", "1")
+	a := App{
+		Flags: []Flag{
+			BoolFlag{Name: "debug, d", EnvVar: "COMPAT_DEBUG,APP_DEBUG"},
+		},
+		Action: func(ctx *Context) error {
+			if ctx.Bool("debug") != true {
+				t.Errorf("main name not set from env")
+			}
+			if ctx.Bool("d") != true {
+				t.Errorf("short name not set from env")
+			}
+			return nil
+		},
+	}
+	a.Run([]string{"run"})
+}
+
+func TestParseMultiBoolT(t *testing.T) {
+	a := App{
+		Flags: []Flag{
+			BoolTFlag{Name: "serve, s"},
+		},
+		Action: func(ctx *Context) error {
+			if ctx.BoolT("serve") != true {
+				t.Errorf("main name not set")
+			}
+			if ctx.BoolT("s") != true {
+				t.Errorf("short name not set")
+			}
+			return nil
+		},
+	}
+	a.Run([]string{"run", "--serve"})
+}
+
+func TestParseDestinationBoolT(t *testing.T) {
+	var dest bool
+	a := App{
+		Flags: []Flag{
+			BoolTFlag{
+				Name:        "dest",
+				Destination: &dest,
+			},
+		},
+		Action: func(ctx *Context) error {
+			if dest != true {
+				t.Errorf("expected destination BoolT true")
+			}
+			return nil
+		},
+	}
+	a.Run([]string{"run", "--dest"})
+}
+
+func TestParseMultiBoolTFromEnv(t *testing.T) {
+	os.Clearenv()
+	os.Setenv("APP_DEBUG", "0")
+	a := App{
+		Flags: []Flag{
+			BoolTFlag{Name: "debug, d", EnvVar: "APP_DEBUG"},
+		},
+		Action: func(ctx *Context) error {
+			if ctx.BoolT("debug") != false {
+				t.Errorf("main name not set from env")
+			}
+			if ctx.BoolT("d") != false {
+				t.Errorf("short name not set from env")
+			}
+			return nil
+		},
+	}
+	a.Run([]string{"run"})
+}
+
+func TestParseMultiBoolTFromEnvCascade(t *testing.T) {
+	os.Clearenv()
+	os.Setenv("APP_DEBUG", "0")
+	a := App{
+		Flags: []Flag{
+			BoolTFlag{Name: "debug, d", EnvVar: "COMPAT_DEBUG,APP_DEBUG"},
+		},
+		Action: func(ctx *Context) error {
+			if ctx.BoolT("debug") != false {
+				t.Errorf("main name not set from env")
+			}
+			if ctx.BoolT("d") != false {
+				t.Errorf("short name not set from env")
+			}
+			return nil
+		},
+	}
+	a.Run([]string{"run"})
+}
+
+type Parser [2]string
+
+func (p *Parser) Set(value string) error {
+	parts := strings.Split(value, ",")
+	if len(parts) != 2 {
+		return fmt.Errorf("invalid format")
+	}
+
+	(*p)[0] = parts[0]
+	(*p)[1] = parts[1]
+
+	return nil
+}
+
+func (p *Parser) String() string {
+	return fmt.Sprintf("%s,%s", p[0], p[1])
+}
+
+func TestParseGeneric(t *testing.T) {
+	a := App{
+		Flags: []Flag{
+			GenericFlag{Name: "serve, s", Value: &Parser{}},
+		},
+		Action: func(ctx *Context) error {
+			if !reflect.DeepEqual(ctx.Generic("serve"), &Parser{"10", "20"}) {
+				t.Errorf("main name not set")
+			}
+			if !reflect.DeepEqual(ctx.Generic("s"), &Parser{"10", "20"}) {
+				t.Errorf("short name not set")
+			}
+			return nil
+		},
+	}
+	a.Run([]string{"run", "-s", "10,20"})
+}
+
+func TestParseGenericFromEnv(t *testing.T) {
+	os.Clearenv()
+	os.Setenv("APP_SERVE", "20,30")
+	a := App{
+		Flags: []Flag{
+			GenericFlag{Name: "serve, s", Value: &Parser{}, EnvVar: "APP_SERVE"},
+		},
+		Action: func(ctx *Context) error {
+			if !reflect.DeepEqual(ctx.Generic("serve"), &Parser{"20", "30"}) {
+				t.Errorf("main name not set from env")
+			}
+			if !reflect.DeepEqual(ctx.Generic("s"), &Parser{"20", "30"}) {
+				t.Errorf("short name not set from env")
+			}
+			return nil
+		},
+	}
+	a.Run([]string{"run"})
+}
+
+func TestParseGenericFromEnvCascade(t *testing.T) {
+	os.Clearenv()
+	os.Setenv("APP_FOO", "99,2000")
+	a := App{
+		Flags: []Flag{
+			GenericFlag{Name: "foos", Value: &Parser{}, EnvVar: "COMPAT_FOO,APP_FOO"},
+		},
+		Action: func(ctx *Context) error {
+			if !reflect.DeepEqual(ctx.Generic("foos"), &Parser{"99", "2000"}) {
+				t.Errorf("value not set from env")
+			}
+			return nil
+		},
+	}
+	a.Run([]string{"run"})
+}

+ 28 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/funcs.go

@@ -0,0 +1,28 @@
+package cli
+
+// BashCompleteFunc is an action to execute when the bash-completion flag is set
+type BashCompleteFunc func(*Context)
+
+// BeforeFunc is an action to execute before any subcommands are run, but after
+// the context is ready if a non-nil error is returned, no subcommands are run
+type BeforeFunc func(*Context) error
+
+// AfterFunc is an action to execute after any subcommands are run, but after the
+// subcommand has finished it is run even if Action() panics
+type AfterFunc func(*Context) error
+
+// ActionFunc is the action to execute when no subcommands are specified
+type ActionFunc func(*Context) error
+
+// CommandNotFoundFunc is executed if the proper command cannot be found
+type CommandNotFoundFunc func(*Context, string)
+
+// OnUsageErrorFunc is executed if an usage error occurs. This is useful for displaying
+// customized usage error messages.  This function is able to replace the
+// original error messages.  If this function is not set, the "Incorrect usage"
+// is displayed and the execution is interrupted.
+type OnUsageErrorFunc func(context *Context, err error, isSubcommand bool) error
+
+// FlagStringFunc is used by the help generation to display a flag, which is
+// expected to be a single line.
+type FlagStringFunc func(Flag) string

+ 266 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/help.go

@@ -0,0 +1,266 @@
+package cli
+
+import (
+	"fmt"
+	"io"
+	"os"
+	"strings"
+	"text/tabwriter"
+	"text/template"
+)
+
+// AppHelpTemplate is the text template for the Default help topic.
+// cli.go uses text/template to render templates. You can
+// render custom help text by setting this variable.
+var AppHelpTemplate = `NAME:
+   {{.Name}} - {{.Usage}}
+
+USAGE:
+   {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}
+   {{if .Version}}{{if not .HideVersion}}
+VERSION:
+   {{.Version}}
+   {{end}}{{end}}{{if len .Authors}}
+AUTHOR(S):
+   {{range .Authors}}{{.}}{{end}}
+   {{end}}{{if .VisibleCommands}}
+COMMANDS:{{range .VisibleCategories}}{{if .Name}}
+   {{.Name}}:{{end}}{{range .VisibleCommands}}
+     {{.Name}}{{with .ShortName}}, {{.}}{{end}}{{"\t"}}{{.Usage}}{{end}}
+{{end}}{{end}}{{if .VisibleFlags}}
+GLOBAL OPTIONS:
+   {{range .VisibleFlags}}{{.}}
+   {{end}}{{end}}{{if .Copyright}}
+COPYRIGHT:
+   {{.Copyright}}
+   {{end}}
+`
+
+// CommandHelpTemplate is the text template for the command help topic.
+// cli.go uses text/template to render templates. You can
+// render custom help text by setting this variable.
+var CommandHelpTemplate = `NAME:
+   {{.HelpName}} - {{.Usage}}
+
+USAGE:
+   {{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{if .Category}}
+
+CATEGORY:
+   {{.Category}}{{end}}{{if .Description}}
+
+DESCRIPTION:
+   {{.Description}}{{end}}{{if .VisibleFlags}}
+
+OPTIONS:
+   {{range .VisibleFlags}}{{.}}
+   {{end}}{{end}}
+`
+
+// SubcommandHelpTemplate is the text template for the subcommand help topic.
+// cli.go uses text/template to render templates. You can
+// render custom help text by setting this variable.
+var SubcommandHelpTemplate = `NAME:
+   {{.HelpName}} - {{.Usage}}
+
+USAGE:
+   {{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}
+
+COMMANDS:{{range .VisibleCategories}}{{if .Name}}
+   {{.Name}}:{{end}}{{range .VisibleCommands}}
+     {{.Name}}{{with .ShortName}}, {{.}}{{end}}{{"\t"}}{{.Usage}}{{end}}
+{{end}}{{if .VisibleFlags}}
+OPTIONS:
+   {{range .VisibleFlags}}{{.}}
+   {{end}}{{end}}
+`
+
+var helpCommand = Command{
+	Name:      "help",
+	Aliases:   []string{"h"},
+	Usage:     "Shows a list of commands or help for one command",
+	ArgsUsage: "[command]",
+	Action: func(c *Context) error {
+		args := c.Args()
+		if args.Present() {
+			return ShowCommandHelp(c, args.First())
+		}
+
+		ShowAppHelp(c)
+		return nil
+	},
+}
+
+var helpSubcommand = Command{
+	Name:      "help",
+	Aliases:   []string{"h"},
+	Usage:     "Shows a list of commands or help for one command",
+	ArgsUsage: "[command]",
+	Action: func(c *Context) error {
+		args := c.Args()
+		if args.Present() {
+			return ShowCommandHelp(c, args.First())
+		}
+
+		return ShowSubcommandHelp(c)
+	},
+}
+
+// Prints help for the App or Command
+type helpPrinter func(w io.Writer, templ string, data interface{})
+
+// HelpPrinter is a function that writes the help output. If not set a default
+// is used. The function signature is:
+// func(w io.Writer, templ string, data interface{})
+var HelpPrinter helpPrinter = printHelp
+
+// VersionPrinter prints the version for the App
+var VersionPrinter = printVersion
+
+// ShowAppHelp is an action that displays the help.
+func ShowAppHelp(c *Context) {
+	HelpPrinter(c.App.Writer, AppHelpTemplate, c.App)
+}
+
+// DefaultAppComplete prints the list of subcommands as the default app completion method
+func DefaultAppComplete(c *Context) {
+	for _, command := range c.App.Commands {
+		if command.Hidden {
+			continue
+		}
+		for _, name := range command.Names() {
+			fmt.Fprintln(c.App.Writer, name)
+		}
+	}
+}
+
+// ShowCommandHelp prints help for the given command
+func ShowCommandHelp(ctx *Context, command string) error {
+	// show the subcommand help for a command with subcommands
+	if command == "" {
+		HelpPrinter(ctx.App.Writer, SubcommandHelpTemplate, ctx.App)
+		return nil
+	}
+
+	for _, c := range ctx.App.Commands {
+		if c.HasName(command) {
+			HelpPrinter(ctx.App.Writer, CommandHelpTemplate, c)
+			return nil
+		}
+	}
+
+	if ctx.App.CommandNotFound == nil {
+		return NewExitError(fmt.Sprintf("No help topic for '%v'", command), 3)
+	}
+
+	ctx.App.CommandNotFound(ctx, command)
+	return nil
+}
+
+// ShowSubcommandHelp prints help for the given subcommand
+func ShowSubcommandHelp(c *Context) error {
+	return ShowCommandHelp(c, c.Command.Name)
+}
+
+// ShowVersion prints the version number of the App
+func ShowVersion(c *Context) {
+	VersionPrinter(c)
+}
+
+func printVersion(c *Context) {
+	fmt.Fprintf(c.App.Writer, "%v version %v\n", c.App.Name, c.App.Version)
+}
+
+// ShowCompletions prints the lists of commands within a given context
+func ShowCompletions(c *Context) {
+	a := c.App
+	if a != nil && a.BashComplete != nil {
+		a.BashComplete(c)
+	}
+}
+
+// ShowCommandCompletions prints the custom completions for a given command
+func ShowCommandCompletions(ctx *Context, command string) {
+	c := ctx.App.Command(command)
+	if c != nil && c.BashComplete != nil {
+		c.BashComplete(ctx)
+	}
+}
+
+func printHelp(out io.Writer, templ string, data interface{}) {
+	funcMap := template.FuncMap{
+		"join": strings.Join,
+	}
+
+	w := tabwriter.NewWriter(out, 0, 8, 1, '\t', 0)
+	t := template.Must(template.New("help").Funcs(funcMap).Parse(templ))
+	err := t.Execute(w, data)
+	if err != nil {
+		// If the writer is closed, t.Execute will fail, and there's nothing
+		// we can do to recover.
+		if os.Getenv("CLI_TEMPLATE_ERROR_DEBUG") != "" {
+			fmt.Fprintf(ErrWriter, "CLI TEMPLATE ERROR: %#v\n", err)
+		}
+		return
+	}
+	w.Flush()
+}
+
+func checkVersion(c *Context) bool {
+	found := false
+	if VersionFlag.Name != "" {
+		eachName(VersionFlag.Name, func(name string) {
+			if c.GlobalBool(name) || c.Bool(name) {
+				found = true
+			}
+		})
+	}
+	return found
+}
+
+func checkHelp(c *Context) bool {
+	found := false
+	if HelpFlag.Name != "" {
+		eachName(HelpFlag.Name, func(name string) {
+			if c.GlobalBool(name) || c.Bool(name) {
+				found = true
+			}
+		})
+	}
+	return found
+}
+
+func checkCommandHelp(c *Context, name string) bool {
+	if c.Bool("h") || c.Bool("help") {
+		ShowCommandHelp(c, name)
+		return true
+	}
+
+	return false
+}
+
+func checkSubcommandHelp(c *Context) bool {
+	if c.GlobalBool("h") || c.GlobalBool("help") {
+		ShowSubcommandHelp(c)
+		return true
+	}
+
+	return false
+}
+
+func checkCompletions(c *Context) bool {
+	if (c.GlobalBool(BashCompletionFlag.Name) || c.Bool(BashCompletionFlag.Name)) && c.App.EnableBashCompletion {
+		ShowCompletions(c)
+		return true
+	}
+
+	return false
+}
+
+func checkCommandCompletions(c *Context, name string) bool {
+	if c.Bool(BashCompletionFlag.Name) && c.App.EnableBashCompletion {
+		ShowCommandCompletions(c, name)
+		return true
+	}
+
+	return false
+}

+ 202 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/help_test.go

@@ -0,0 +1,202 @@
+package cli
+
+import (
+	"bytes"
+	"flag"
+	"strings"
+	"testing"
+)
+
+func Test_ShowAppHelp_NoAuthor(t *testing.T) {
+	output := new(bytes.Buffer)
+	app := NewApp()
+	app.Writer = output
+
+	c := NewContext(app, nil, nil)
+
+	ShowAppHelp(c)
+
+	if bytes.Index(output.Bytes(), []byte("AUTHOR(S):")) != -1 {
+		t.Errorf("expected\n%snot to include %s", output.String(), "AUTHOR(S):")
+	}
+}
+
+func Test_ShowAppHelp_NoVersion(t *testing.T) {
+	output := new(bytes.Buffer)
+	app := NewApp()
+	app.Writer = output
+
+	app.Version = ""
+
+	c := NewContext(app, nil, nil)
+
+	ShowAppHelp(c)
+
+	if bytes.Index(output.Bytes(), []byte("VERSION:")) != -1 {
+		t.Errorf("expected\n%snot to include %s", output.String(), "VERSION:")
+	}
+}
+
+func Test_ShowAppHelp_HideVersion(t *testing.T) {
+	output := new(bytes.Buffer)
+	app := NewApp()
+	app.Writer = output
+
+	app.HideVersion = true
+
+	c := NewContext(app, nil, nil)
+
+	ShowAppHelp(c)
+
+	if bytes.Index(output.Bytes(), []byte("VERSION:")) != -1 {
+		t.Errorf("expected\n%snot to include %s", output.String(), "VERSION:")
+	}
+}
+
+func Test_Help_Custom_Flags(t *testing.T) {
+	oldFlag := HelpFlag
+	defer func() {
+		HelpFlag = oldFlag
+	}()
+
+	HelpFlag = BoolFlag{
+		Name:  "help, x",
+		Usage: "show help",
+	}
+
+	app := App{
+		Flags: []Flag{
+			BoolFlag{Name: "foo, h"},
+		},
+		Action: func(ctx *Context) error {
+			if ctx.Bool("h") != true {
+				t.Errorf("custom help flag not set")
+			}
+			return nil
+		},
+	}
+	output := new(bytes.Buffer)
+	app.Writer = output
+	app.Run([]string{"test", "-h"})
+	if output.Len() > 0 {
+		t.Errorf("unexpected output: %s", output.String())
+	}
+}
+
+func Test_Version_Custom_Flags(t *testing.T) {
+	oldFlag := VersionFlag
+	defer func() {
+		VersionFlag = oldFlag
+	}()
+
+	VersionFlag = BoolFlag{
+		Name:  "version, V",
+		Usage: "show version",
+	}
+
+	app := App{
+		Flags: []Flag{
+			BoolFlag{Name: "foo, v"},
+		},
+		Action: func(ctx *Context) error {
+			if ctx.Bool("v") != true {
+				t.Errorf("custom version flag not set")
+			}
+			return nil
+		},
+	}
+	output := new(bytes.Buffer)
+	app.Writer = output
+	app.Run([]string{"test", "-v"})
+	if output.Len() > 0 {
+		t.Errorf("unexpected output: %s", output.String())
+	}
+}
+
+func Test_helpCommand_Action_ErrorIfNoTopic(t *testing.T) {
+	app := NewApp()
+
+	set := flag.NewFlagSet("test", 0)
+	set.Parse([]string{"foo"})
+
+	c := NewContext(app, set, nil)
+
+	err := helpCommand.Action.(func(*Context) error)(c)
+
+	if err == nil {
+		t.Fatalf("expected error from helpCommand.Action(), but got nil")
+	}
+
+	exitErr, ok := err.(*ExitError)
+	if !ok {
+		t.Fatalf("expected ExitError from helpCommand.Action(), but instead got: %v", err.Error())
+	}
+
+	if !strings.HasPrefix(exitErr.Error(), "No help topic for") {
+		t.Fatalf("expected an unknown help topic error, but got: %v", exitErr.Error())
+	}
+
+	if exitErr.exitCode != 3 {
+		t.Fatalf("expected exit value = 3, got %d instead", exitErr.exitCode)
+	}
+}
+
+func Test_helpSubcommand_Action_ErrorIfNoTopic(t *testing.T) {
+	app := NewApp()
+
+	set := flag.NewFlagSet("test", 0)
+	set.Parse([]string{"foo"})
+
+	c := NewContext(app, set, nil)
+
+	err := helpSubcommand.Action.(func(*Context) error)(c)
+
+	if err == nil {
+		t.Fatalf("expected error from helpCommand.Action(), but got nil")
+	}
+
+	exitErr, ok := err.(*ExitError)
+	if !ok {
+		t.Fatalf("expected ExitError from helpCommand.Action(), but instead got: %v", err.Error())
+	}
+
+	if !strings.HasPrefix(exitErr.Error(), "No help topic for") {
+		t.Fatalf("expected an unknown help topic error, but got: %v", exitErr.Error())
+	}
+
+	if exitErr.exitCode != 3 {
+		t.Fatalf("expected exit value = 3, got %d instead", exitErr.exitCode)
+	}
+}
+
+func TestShowAppHelp_HiddenCommand(t *testing.T) {
+	app := &App{
+		Commands: []Command{
+			{
+				Name: "frobbly",
+				Action: func(ctx *Context) error {
+					return nil
+				},
+			},
+			{
+				Name:   "secretfrob",
+				Hidden: true,
+				Action: func(ctx *Context) error {
+					return nil
+				},
+			},
+		},
+	}
+
+	output := &bytes.Buffer{}
+	app.Writer = output
+	app.Run([]string{"app", "--help"})
+
+	if strings.Contains(output.String(), "secretfrob") {
+		t.Errorf("expected output to exclude \"secretfrob\"; got: %q", output.String())
+	}
+
+	if !strings.Contains(output.String(), "frobbly") {
+		t.Errorf("expected output to include \"frobbly\"; got: %q", output.String())
+	}
+}

+ 28 - 0
bashbrew/go/vendor/src/github.com/codegangsta/cli/helpers_test.go

@@ -0,0 +1,28 @@
+package cli
+
+import (
+	"os"
+	"reflect"
+	"runtime"
+	"strings"
+	"testing"
+)
+
+var (
+	wd, _ = os.Getwd()
+)
+
+func expect(t *testing.T, a interface{}, b interface{}) {
+	_, fn, line, _ := runtime.Caller(1)
+	fn = strings.Replace(fn, wd+"/", "", -1)
+
+	if !reflect.DeepEqual(a, b) {
+		t.Errorf("(%s:%d) Expected %v (type %v) - Got %v (type %v)", fn, line, b, reflect.TypeOf(b), a, reflect.TypeOf(a))
+	}
+}
+
+func refute(t *testing.T, a interface{}, b interface{}) {
+	if reflect.DeepEqual(a, b) {
+		t.Errorf("Did not expect %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
+	}
+}

+ 191 - 0
bashbrew/go/vendor/src/github.com/docker-library/go-dockerlibrary/LICENSE

@@ -0,0 +1,191 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   Copyright 2014 Docker, Inc.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 67 - 0
bashbrew/go/vendor/src/github.com/docker-library/go-dockerlibrary/manifest/example.go

@@ -0,0 +1,67 @@
+// +build ignore
+
+package main
+
+import (
+	"bufio"
+	"fmt"
+	"strings"
+
+	"github.com/docker-library/go-dockerlibrary/manifest"
+)
+
+func main() {
+	// TODO comment parsing
+	man, err := manifest.Parse(bufio.NewReader(strings.NewReader(`# RFC 2822
+
+	# I LOVE CAKE
+
+Maintainers: InfoSiftr <[email protected]> (@infosiftr),
+             Johan Euphrosine <[email protected]> (@proppy)
+GitRepo: https://github.com/docker-library/golang.git
+GitFetch: refs/heads/master
+
+
+ # hi
+
+
+ 	 # blasphemer
+
+
+# Go 1.6
+Tags: 1.6.1, 1.6, 1, latest
+GitCommit: 0ce80411b9f41e9c3a21fc0a1bffba6ae761825a
+Directory: 1.6
+
+
+# Go 1.5
+Tags: 1.5.3
+GitCommit: d7e2a8d90a9b8f5dfd5bcd428e0c33b68c40cc19
+Directory: 1.5
+
+
+Tags: 1.5
+GitCommit: d7e2a8d90a9b8f5dfd5bcd428e0c33b68c40cc19
+Directory: 1.5
+
+
+`)))
+	if err != nil {
+		panic(err)
+	}
+	fmt.Printf("-------------\n2822:\n%s\n", man)
+
+	man, err = manifest.Parse(bufio.NewReader(strings.NewReader(`
+# first set
+a: b@c d
+e: b@c d
+
+ # second set
+f: g@h
+i: g@h j
+`)))
+	if err != nil {
+		panic(err)
+	}
+	fmt.Printf("-------------\nline-based:\n%v\n", man)
+}

+ 67 - 0
bashbrew/go/vendor/src/github.com/docker-library/go-dockerlibrary/manifest/fetch.go

@@ -0,0 +1,67 @@
+package manifest
+
+import (
+	"fmt"
+	"net/http"
+	"net/url"
+	"os"
+	"path"
+	"path/filepath"
+	"strings"
+)
+
+// "library" is the default "library directory"
+// returns the parsed version of (in order):
+//   if "repo" is a URL, the remote contents of that URL
+//   if "repo" is a relative path like "./repo", that file
+//   the file "library/repo"
+// (repoName, tagName, man, err)
+func Fetch(library, repo string) (string, string, *Manifest2822, error) {
+	repoName := path.Base(repo)
+	tagName := ""
+	if tagIndex := strings.IndexRune(repoName, ':'); tagIndex > 0 {
+		tagName = repoName[tagIndex+1:]
+		repoName = repoName[:tagIndex]
+		repo = strings.TrimSuffix(repo, ":"+tagName)
+	}
+
+	u, err := url.Parse(repo)
+	if err == nil && u.IsAbs() {
+		// must be remote URL!
+		resp, err := http.Get(repo)
+		if err != nil {
+			return repoName, tagName, nil, err
+		}
+		defer resp.Body.Close()
+		man, err := Parse(resp.Body)
+		if tagName != "" && man.GetTag(tagName) == nil {
+			return repoName, tagName, man, fmt.Errorf("tag not found in manifest for %q: %q", repoName, tagName)
+		}
+		return repoName, tagName, man, err
+	}
+
+	// try file paths
+	filePaths := []string{}
+	if filepath.IsAbs(repo) || strings.IndexRune(repo, filepath.Separator) >= 0 || strings.IndexRune(repo, '/') >= 0 {
+		filePaths = append(filePaths, repo)
+	}
+	if !filepath.IsAbs(repo) {
+		filePaths = append(filePaths, filepath.Join(library, repo))
+	}
+	for _, fileName := range filePaths {
+		f, err := os.Open(fileName)
+		if err != nil && !os.IsNotExist(err) {
+			return repoName, tagName, nil, err
+		}
+		if err == nil {
+			defer f.Close()
+			man, err := Parse(f)
+			if tagName != "" && man.GetTag(tagName) == nil {
+				return repoName, tagName, man, fmt.Errorf("tag not found in manifest for %q: %q", repoName, tagName)
+			}
+			return repoName, tagName, man, err
+		}
+	}
+
+	return repoName, tagName, nil, fmt.Errorf("unable to find a manifest named %q (in %q or as a remote URL)", repo, library)
+}

+ 77 - 0
bashbrew/go/vendor/src/github.com/docker-library/go-dockerlibrary/manifest/line-based.go

@@ -0,0 +1,77 @@
+package manifest
+
+import (
+	"bufio"
+	"fmt"
+	"io"
+	"strings"
+)
+
+const DefaultLineBasedFetch = "refs/heads/*" // backwards compatibility
+
+// TODO write more of a proper parser? (probably not worthwhile given that 2822 is the preferred format)
+func ParseLineBasedLine(line string, defaults Manifest2822Entry) (*Manifest2822Entry, error) {
+	entry := defaults.Clone()
+
+	parts := strings.SplitN(line, ":", 2)
+	if len(parts) < 2 {
+		return nil, fmt.Errorf("manifest line missing ':': %s", line)
+	}
+	entry.Tags = []string{strings.TrimSpace(parts[0])}
+
+	parts = strings.SplitN(parts[1], "@", 2)
+	if len(parts) < 2 {
+		return nil, fmt.Errorf("manifest line missing '@': %s", line)
+	}
+	entry.GitRepo = strings.TrimSpace(parts[0])
+
+	parts = strings.SplitN(parts[1], " ", 2)
+	entry.GitCommit = strings.TrimSpace(parts[0])
+	if len(parts) > 1 {
+		entry.Directory = strings.TrimSpace(parts[1])
+	}
+
+	if entry.GitFetch == DefaultLineBasedFetch && !GitCommitRegex.MatchString(entry.GitCommit) {
+		// doesn't look like a commit, must be a tag
+		entry.GitFetch = "refs/tags/" + entry.GitCommit
+		entry.GitCommit = "FETCH_HEAD"
+	}
+
+	return &entry, nil
+}
+
+func ParseLineBased(readerIn io.Reader) (*Manifest2822, error) {
+	reader := bufio.NewReader(readerIn)
+
+	manifest := &Manifest2822{
+		Global: DefaultManifestEntry.Clone(),
+	}
+	manifest.Global.Maintainers = []string{`TODO parse old-style "maintainer:" comment lines?`}
+	manifest.Global.GitFetch = DefaultLineBasedFetch
+
+	for {
+		line, err := reader.ReadString('\n')
+
+		line = strings.TrimSpace(line)
+		if len(line) > 0 && line[0] != '#' {
+			entry, parseErr := ParseLineBasedLine(line, manifest.Global)
+			if parseErr != nil {
+				return nil, parseErr
+			}
+
+			err = manifest.AddEntry(*entry)
+			if err != nil {
+				return nil, err
+			}
+		}
+
+		if err == io.EOF {
+			break
+		}
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	return manifest, nil
+}

+ 24 - 0
bashbrew/go/vendor/src/github.com/docker-library/go-dockerlibrary/manifest/parse.go

@@ -0,0 +1,24 @@
+package manifest
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+)
+
+// try parsing as a 2822 manifest, but fallback to line-based if that fails
+func Parse(reader io.Reader) (*Manifest2822, error) {
+	buf := &bytes.Buffer{}
+
+	// try parsing as 2822, but also copy back into a new buffer so that if it fails, we can re-parse as line-based
+	manifest, err2822 := Parse2822(io.TeeReader(reader, buf))
+	if err2822 != nil {
+		manifest, err := ParseLineBased(buf)
+		if err != nil {
+			return nil, fmt.Errorf("cannot parse manifest in either format:\nRFC 2822 error: %v\nLine-based error: %v", err2822, err)
+		}
+		return manifest, nil
+	}
+
+	return manifest, nil
+}

+ 269 - 0
bashbrew/go/vendor/src/github.com/docker-library/go-dockerlibrary/manifest/rfc2822.go

@@ -0,0 +1,269 @@
+package manifest
+
+import (
+	"bufio"
+	"fmt"
+	"io"
+	"regexp"
+	"strings"
+
+	"github.com/docker-library/go-dockerlibrary/pkg/stripper"
+
+	"pault.ag/go/debian/control"
+)
+
+var (
+	GitCommitRegex = regexp.MustCompile(`^[0-9a-f]{1,40}$`)
+	GitFetchRegex  = regexp.MustCompile(`^refs/(heads|tags)/[^*?:]+$`)
+)
+
+type Manifest2822 struct {
+	Global  Manifest2822Entry
+	Entries []Manifest2822Entry
+}
+
+type Manifest2822Entry struct {
+	control.Paragraph
+
+	Maintainers []string `delim:"," strip:"\n\r\t "`
+	Tags        []string `delim:"," strip:"\n\r\t "`
+	GitRepo     string
+	GitFetch    string
+	GitCommit   string
+	Directory   string
+	Constraints []string `delim:"," strip:"\n\r\t "`
+}
+
+var DefaultManifestEntry = Manifest2822Entry{
+	GitFetch:  "refs/heads/master",
+	Directory: ".",
+}
+
+func (entry Manifest2822Entry) Clone() Manifest2822Entry {
+	// SLICES! grr
+	entry.Maintainers = append([]string{}, entry.Maintainers...)
+	entry.Tags = append([]string{}, entry.Tags...)
+	entry.Constraints = append([]string{}, entry.Constraints...)
+	return entry
+}
+
+const StringSeparator2822 = ", "
+
+func (entry Manifest2822Entry) MaintainersString() string {
+	return strings.Join(entry.Maintainers, StringSeparator2822)
+}
+
+func (entry Manifest2822Entry) TagsString() string {
+	return strings.Join(entry.Tags, StringSeparator2822)
+}
+
+func (entry Manifest2822Entry) ConstraintsString() string {
+	return strings.Join(entry.Constraints, StringSeparator2822)
+}
+
+// if this method returns "true", then a.Tags and b.Tags can safely be combined (for the purposes of building)
+func (a Manifest2822Entry) SameBuildArtifacts(b Manifest2822Entry) bool {
+	return a.GitRepo == b.GitRepo && a.GitFetch == b.GitFetch && a.GitCommit == b.GitCommit && a.Directory == b.Directory && a.ConstraintsString() == b.ConstraintsString()
+}
+
+// returns a new Entry with any of the values that are equal to the values in "defaults" cleared
+func (entry Manifest2822Entry) ClearDefaults(defaults Manifest2822Entry) Manifest2822Entry {
+	if entry.MaintainersString() == defaults.MaintainersString() {
+		entry.Maintainers = nil
+	}
+	if entry.TagsString() == defaults.TagsString() {
+		entry.Tags = nil
+	}
+	if entry.GitRepo == defaults.GitRepo {
+		entry.GitRepo = ""
+	}
+	if entry.GitFetch == defaults.GitFetch {
+		entry.GitFetch = ""
+	}
+	if entry.GitCommit == defaults.GitCommit {
+		entry.GitCommit = ""
+	}
+	if entry.Directory == defaults.Directory {
+		entry.Directory = ""
+	}
+	if entry.ConstraintsString() == defaults.ConstraintsString() {
+		entry.Constraints = nil
+	}
+	return entry
+}
+
+func (entry Manifest2822Entry) String() string {
+	ret := []string{}
+	if str := entry.MaintainersString(); str != "" {
+		ret = append(ret, "Maintainers: "+str)
+	}
+	if str := entry.TagsString(); str != "" {
+		ret = append(ret, "Tags: "+str)
+	}
+	if str := entry.GitRepo; str != "" {
+		ret = append(ret, "GitRepo: "+str)
+	}
+	if str := entry.GitFetch; str != "" {
+		ret = append(ret, "GitFetch: "+str)
+	}
+	if str := entry.GitCommit; str != "" {
+		ret = append(ret, "GitCommit: "+str)
+	}
+	if str := entry.Directory; str != "" {
+		ret = append(ret, "Directory: "+str)
+	}
+	if str := entry.ConstraintsString(); str != "" {
+		ret = append(ret, "Constraints: "+str)
+	}
+	return strings.Join(ret, "\n")
+}
+
+func (manifest Manifest2822) String() string {
+	entries := []Manifest2822Entry{manifest.Global.ClearDefaults(DefaultManifestEntry)}
+	entries = append(entries, manifest.Entries...)
+
+	ret := []string{}
+	for i, entry := range entries {
+		if i > 0 {
+			entry = entry.ClearDefaults(manifest.Global)
+		}
+		ret = append(ret, entry.String())
+	}
+
+	return strings.Join(ret, "\n\n")
+}
+
+func (entry Manifest2822Entry) HasTag(tag string) bool {
+	for _, existingTag := range entry.Tags {
+		if tag == existingTag {
+			return true
+		}
+	}
+	return false
+}
+
+func (manifest Manifest2822) GetTag(tag string) *Manifest2822Entry {
+	for _, entry := range manifest.Entries {
+		if entry.HasTag(tag) {
+			return &entry
+		}
+	}
+	return nil
+}
+
+func (manifest *Manifest2822) AddEntry(entry Manifest2822Entry) error {
+	for _, tag := range entry.Tags {
+		if manifest.GetTag(tag) != nil {
+			return fmt.Errorf("Tags %q includes duplicate tag: %s", entry.TagsString(), tag)
+		}
+	}
+
+	for i, existingEntry := range manifest.Entries {
+		if existingEntry.SameBuildArtifacts(entry) {
+			manifest.Entries[i].Tags = append(existingEntry.Tags, entry.Tags...)
+			return nil
+		}
+	}
+
+	manifest.Entries = append(manifest.Entries, entry)
+
+	return nil
+}
+
+const (
+	MaintainersNameRegex   = `[^\s<>()][^<>()]*`
+	MaintainersEmailRegex  = `[^\s<>()]+`
+	MaintainersGitHubRegex = `[^\s<>()]+`
+
+	MaintainersFormat = `Full Name <contact-email-or-url> (@github-handle) OR Full Name (@github-handle)`
+)
+
+var (
+	MaintainersRegex = regexp.MustCompile(`^(` + MaintainersNameRegex + `)(?:\s+<(` + MaintainersEmailRegex + `)>)?\s+[(]@(` + MaintainersGitHubRegex + `)[)]$`)
+)
+
+func (entry Manifest2822Entry) InvalidMaintainers() []string {
+	invalid := []string{}
+	for _, maintainer := range entry.Maintainers {
+		if !MaintainersRegex.MatchString(maintainer) {
+			invalid = append(invalid, maintainer)
+		}
+	}
+	return invalid
+}
+
+type decoderWrapper struct {
+	*control.Decoder
+}
+
+func (decoder *decoderWrapper) Decode(entry *Manifest2822Entry) error {
+	for {
+		err := decoder.Decoder.Decode(entry)
+		if err != nil {
+			return err
+		}
+		// ignore empty paragraphs (blank lines at the start, excess blank lines between paragraphs, excess blank lines at EOF)
+		if len(entry.Paragraph.Order) > 0 {
+			return nil
+		}
+	}
+}
+
+func Parse2822(readerIn io.Reader) (*Manifest2822, error) {
+	reader := stripper.NewCommentStripper(readerIn)
+
+	realDecoder, err := control.NewDecoder(bufio.NewReader(reader), nil)
+	if err != nil {
+		return nil, err
+	}
+	decoder := decoderWrapper{realDecoder}
+
+	manifest := Manifest2822{
+		Global: DefaultManifestEntry.Clone(),
+	}
+
+	if err := decoder.Decode(&manifest.Global); err != nil {
+		return nil, err
+	}
+	if len(manifest.Global.Maintainers) < 1 {
+		return nil, fmt.Errorf("missing Maintainers")
+	}
+	if invalidMaintainers := manifest.Global.InvalidMaintainers(); len(invalidMaintainers) > 0 {
+		return nil, fmt.Errorf("invalid Maintainers: %q (expected format %q)", strings.Join(invalidMaintainers, ", "), MaintainersFormat)
+	}
+	if len(manifest.Global.Tags) > 0 {
+		return nil, fmt.Errorf("global Tags not permitted")
+	}
+
+	for {
+		entry := manifest.Global.Clone()
+
+		err := decoder.Decode(&entry)
+		if err == io.EOF {
+			break
+		}
+		if err != nil {
+			return nil, err
+		}
+
+		if len(entry.Tags) < 1 {
+			return nil, fmt.Errorf("missing Tags")
+		}
+		if entry.GitRepo == "" || entry.GitFetch == "" || entry.GitCommit == "" {
+			return nil, fmt.Errorf("Tags %q missing one of GitRepo, GitFetch, or GitCommit", entry.TagsString())
+		}
+		if !GitFetchRegex.MatchString(entry.GitFetch) {
+			return nil, fmt.Errorf(`Tags %q has invalid GitFetch (must be "refs/heads/..." or "refs/tags/..."): %q`, entry.TagsString(), entry.GitFetch)
+		}
+		if !GitCommitRegex.MatchString(entry.GitCommit) {
+			return nil, fmt.Errorf(`Tags %q has invalid GitCommit (must be a commit, not a tag or ref): %q`, entry.TagsString(), entry.GitCommit)
+		}
+
+		err = manifest.AddEntry(entry)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	return &manifest, nil
+}

+ 54 - 0
bashbrew/go/vendor/src/github.com/docker-library/go-dockerlibrary/pkg/stripper/comments.go

@@ -0,0 +1,54 @@
+package stripper
+
+import (
+	"bufio"
+	"bytes"
+	"io"
+	"strings"
+	"unicode"
+)
+
+type CommentStripper struct {
+	Comment    string
+	Delimiter  byte
+	Whitespace bool
+
+	r   *bufio.Reader
+	buf bytes.Buffer
+}
+
+func NewCommentStripper(r io.Reader) *CommentStripper {
+	return &CommentStripper{
+		Comment:    "#",
+		Delimiter:  '\n',
+		Whitespace: true,
+
+		r: bufio.NewReader(r),
+	}
+}
+
+func (r *CommentStripper) Read(p []byte) (int, error) {
+	for {
+		if r.buf.Len() >= len(p) {
+			return r.buf.Read(p)
+		}
+		line, err := r.r.ReadString(r.Delimiter)
+		if len(line) > 0 {
+			checkLine := line
+			if r.Whitespace {
+				checkLine = strings.TrimLeftFunc(checkLine, unicode.IsSpace)
+			}
+			if strings.HasPrefix(checkLine, r.Comment) {
+				// yay, skip this line
+				continue
+			}
+			r.buf.WriteString(line)
+		}
+		if err != nil {
+			if r.buf.Len() > 0 {
+				return r.buf.Read(p)
+			}
+			return 0, err
+		}
+	}
+}

+ 99 - 0
bashbrew/go/vendor/src/github.com/docker-library/go-dockerlibrary/pkg/templatelib/lib.go

@@ -0,0 +1,99 @@
+package templatelib
+
+import (
+	"encoding/json"
+	"fmt"
+	"reflect"
+	"strings"
+	"text/template"
+)
+
+func swapStringsFuncBoolArgsOrder(a func(string, string) bool) func(string, string) bool {
+	return func(str1 string, str2 string) bool {
+		return a(str2, str1)
+	}
+}
+
+func thingsActionFactory(name string, actOnFirst bool, action func([]interface{}, interface{}) interface{}) func(args ...interface{}) interface{} {
+	return func(args ...interface{}) interface{} {
+		if len(args) < 1 {
+			panic(fmt.Sprintf(`%q requires at least one argument`, name))
+		}
+
+		actArgs := []interface{}{}
+		for _, val := range args {
+			v := reflect.ValueOf(val)
+
+			switch v.Kind() {
+			case reflect.Slice, reflect.Array:
+				for i := 0; i < v.Len(); i++ {
+					actArgs = append(actArgs, v.Index(i).Interface())
+				}
+			default:
+				actArgs = append(actArgs, v.Interface())
+			}
+		}
+
+		var arg interface{}
+		if actOnFirst {
+			arg = actArgs[0]
+			actArgs = actArgs[1:]
+		} else {
+			arg = actArgs[len(actArgs)-1]
+			actArgs = actArgs[:len(actArgs)-1]
+		}
+
+		return action(actArgs, arg)
+	}
+}
+
+func stringsActionFactory(name string, actOnFirst bool, action func([]string, string) string) func(args ...interface{}) interface{} {
+	return thingsActionFactory(name, actOnFirst, func(args []interface{}, arg interface{}) interface{} {
+		str := arg.(string)
+		strs := []string{}
+		for _, val := range args {
+			strs = append(strs, val.(string))
+		}
+		return action(strs, str)
+	})
+}
+
+func stringsModifierActionFactory(a func(string, string) string) func([]string, string) string {
+	return func(strs []string, str string) string {
+		for _, mod := range strs {
+			str = a(str, mod)
+		}
+		return str
+	}
+}
+
+// TODO write some tests for these
+
+var FuncMap = template.FuncMap{
+	"hasPrefix": swapStringsFuncBoolArgsOrder(strings.HasPrefix),
+	"hasSuffix": swapStringsFuncBoolArgsOrder(strings.HasSuffix),
+
+	"ternary": func(truthy interface{}, falsey interface{}, val interface{}) interface{} {
+		if t, ok := template.IsTrue(val); !ok {
+			panic(fmt.Sprintf(`template.IsTrue(%+v) says things are NOT OK`, val))
+		} else if t {
+			return truthy
+		} else {
+			return falsey
+		}
+	},
+
+	"first": thingsActionFactory("first", true, func(args []interface{}, arg interface{}) interface{} { return arg }),
+	"last":  thingsActionFactory("last", false, func(args []interface{}, arg interface{}) interface{} { return arg }),
+
+	"json": func(v interface{}) (string, error) {
+		j, err := json.Marshal(v)
+		return string(j), err
+	},
+	"join":         stringsActionFactory("join", true, strings.Join),
+	"trimPrefixes": stringsActionFactory("trimPrefixes", false, stringsModifierActionFactory(strings.TrimPrefix)),
+	"trimSuffixes": stringsActionFactory("trimSuffixes", false, stringsModifierActionFactory(strings.TrimSuffix)),
+	"replace": stringsActionFactory("replace", false, func(strs []string, str string) string {
+		return strings.NewReplacer(strs...).Replace(str)
+	}),
+}

+ 526 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/cast5/cast5.go

@@ -0,0 +1,526 @@
+// Copyright 2010 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 cast5 implements CAST5, as defined in RFC 2144. CAST5 is a common
+// OpenPGP cipher.
+package cast5 // import "golang.org/x/crypto/cast5"
+
+import "errors"
+
+const BlockSize = 8
+const KeySize = 16
+
+type Cipher struct {
+	masking [16]uint32
+	rotate  [16]uint8
+}
+
+func NewCipher(key []byte) (c *Cipher, err error) {
+	if len(key) != KeySize {
+		return nil, errors.New("CAST5: keys must be 16 bytes")
+	}
+
+	c = new(Cipher)
+	c.keySchedule(key)
+	return
+}
+
+func (c *Cipher) BlockSize() int {
+	return BlockSize
+}
+
+func (c *Cipher) Encrypt(dst, src []byte) {
+	l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
+	r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
+
+	l, r = r, l^f1(r, c.masking[0], c.rotate[0])
+	l, r = r, l^f2(r, c.masking[1], c.rotate[1])
+	l, r = r, l^f3(r, c.masking[2], c.rotate[2])
+	l, r = r, l^f1(r, c.masking[3], c.rotate[3])
+
+	l, r = r, l^f2(r, c.masking[4], c.rotate[4])
+	l, r = r, l^f3(r, c.masking[5], c.rotate[5])
+	l, r = r, l^f1(r, c.masking[6], c.rotate[6])
+	l, r = r, l^f2(r, c.masking[7], c.rotate[7])
+
+	l, r = r, l^f3(r, c.masking[8], c.rotate[8])
+	l, r = r, l^f1(r, c.masking[9], c.rotate[9])
+	l, r = r, l^f2(r, c.masking[10], c.rotate[10])
+	l, r = r, l^f3(r, c.masking[11], c.rotate[11])
+
+	l, r = r, l^f1(r, c.masking[12], c.rotate[12])
+	l, r = r, l^f2(r, c.masking[13], c.rotate[13])
+	l, r = r, l^f3(r, c.masking[14], c.rotate[14])
+	l, r = r, l^f1(r, c.masking[15], c.rotate[15])
+
+	dst[0] = uint8(r >> 24)
+	dst[1] = uint8(r >> 16)
+	dst[2] = uint8(r >> 8)
+	dst[3] = uint8(r)
+	dst[4] = uint8(l >> 24)
+	dst[5] = uint8(l >> 16)
+	dst[6] = uint8(l >> 8)
+	dst[7] = uint8(l)
+}
+
+func (c *Cipher) Decrypt(dst, src []byte) {
+	l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
+	r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
+
+	l, r = r, l^f1(r, c.masking[15], c.rotate[15])
+	l, r = r, l^f3(r, c.masking[14], c.rotate[14])
+	l, r = r, l^f2(r, c.masking[13], c.rotate[13])
+	l, r = r, l^f1(r, c.masking[12], c.rotate[12])
+
+	l, r = r, l^f3(r, c.masking[11], c.rotate[11])
+	l, r = r, l^f2(r, c.masking[10], c.rotate[10])
+	l, r = r, l^f1(r, c.masking[9], c.rotate[9])
+	l, r = r, l^f3(r, c.masking[8], c.rotate[8])
+
+	l, r = r, l^f2(r, c.masking[7], c.rotate[7])
+	l, r = r, l^f1(r, c.masking[6], c.rotate[6])
+	l, r = r, l^f3(r, c.masking[5], c.rotate[5])
+	l, r = r, l^f2(r, c.masking[4], c.rotate[4])
+
+	l, r = r, l^f1(r, c.masking[3], c.rotate[3])
+	l, r = r, l^f3(r, c.masking[2], c.rotate[2])
+	l, r = r, l^f2(r, c.masking[1], c.rotate[1])
+	l, r = r, l^f1(r, c.masking[0], c.rotate[0])
+
+	dst[0] = uint8(r >> 24)
+	dst[1] = uint8(r >> 16)
+	dst[2] = uint8(r >> 8)
+	dst[3] = uint8(r)
+	dst[4] = uint8(l >> 24)
+	dst[5] = uint8(l >> 16)
+	dst[6] = uint8(l >> 8)
+	dst[7] = uint8(l)
+}
+
+type keyScheduleA [4][7]uint8
+type keyScheduleB [4][5]uint8
+
+// keyScheduleRound contains the magic values for a round of the key schedule.
+// The keyScheduleA deals with the lines like:
+//   z0z1z2z3 = x0x1x2x3 ^ S5[xD] ^ S6[xF] ^ S7[xC] ^ S8[xE] ^ S7[x8]
+// Conceptually, both x and z are in the same array, x first. The first
+// element describes which word of this array gets written to and the
+// second, which word gets read. So, for the line above, it's "4, 0", because
+// it's writing to the first word of z, which, being after x, is word 4, and
+// reading from the first word of x: word 0.
+//
+// Next are the indexes into the S-boxes. Now the array is treated as bytes. So
+// "xD" is 0xd. The first byte of z is written as "16 + 0", just to be clear
+// that it's z that we're indexing.
+//
+// keyScheduleB deals with lines like:
+//   K1 = S5[z8] ^ S6[z9] ^ S7[z7] ^ S8[z6] ^ S5[z2]
+// "K1" is ignored because key words are always written in order. So the five
+// elements are the S-box indexes. They use the same form as in keyScheduleA,
+// above.
+
+type keyScheduleRound struct{}
+type keySchedule []keyScheduleRound
+
+var schedule = []struct {
+	a keyScheduleA
+	b keyScheduleB
+}{
+	{
+		keyScheduleA{
+			{4, 0, 0xd, 0xf, 0xc, 0xe, 0x8},
+			{5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa},
+			{6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9},
+			{7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb},
+		},
+		keyScheduleB{
+			{16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2},
+			{16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6},
+			{16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9},
+			{16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc},
+		},
+	},
+	{
+		keyScheduleA{
+			{0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0},
+			{1, 4, 0, 2, 1, 3, 16 + 2},
+			{2, 5, 7, 6, 5, 4, 16 + 1},
+			{3, 7, 0xa, 9, 0xb, 8, 16 + 3},
+		},
+		keyScheduleB{
+			{3, 2, 0xc, 0xd, 8},
+			{1, 0, 0xe, 0xf, 0xd},
+			{7, 6, 8, 9, 3},
+			{5, 4, 0xa, 0xb, 7},
+		},
+	},
+	{
+		keyScheduleA{
+			{4, 0, 0xd, 0xf, 0xc, 0xe, 8},
+			{5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa},
+			{6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9},
+			{7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb},
+		},
+		keyScheduleB{
+			{16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9},
+			{16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc},
+			{16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2},
+			{16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6},
+		},
+	},
+	{
+		keyScheduleA{
+			{0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0},
+			{1, 4, 0, 2, 1, 3, 16 + 2},
+			{2, 5, 7, 6, 5, 4, 16 + 1},
+			{3, 7, 0xa, 9, 0xb, 8, 16 + 3},
+		},
+		keyScheduleB{
+			{8, 9, 7, 6, 3},
+			{0xa, 0xb, 5, 4, 7},
+			{0xc, 0xd, 3, 2, 8},
+			{0xe, 0xf, 1, 0, 0xd},
+		},
+	},
+}
+
+func (c *Cipher) keySchedule(in []byte) {
+	var t [8]uint32
+	var k [32]uint32
+
+	for i := 0; i < 4; i++ {
+		j := i * 4
+		t[i] = uint32(in[j])<<24 | uint32(in[j+1])<<16 | uint32(in[j+2])<<8 | uint32(in[j+3])
+	}
+
+	x := []byte{6, 7, 4, 5}
+	ki := 0
+
+	for half := 0; half < 2; half++ {
+		for _, round := range schedule {
+			for j := 0; j < 4; j++ {
+				var a [7]uint8
+				copy(a[:], round.a[j][:])
+				w := t[a[1]]
+				w ^= sBox[4][(t[a[2]>>2]>>(24-8*(a[2]&3)))&0xff]
+				w ^= sBox[5][(t[a[3]>>2]>>(24-8*(a[3]&3)))&0xff]
+				w ^= sBox[6][(t[a[4]>>2]>>(24-8*(a[4]&3)))&0xff]
+				w ^= sBox[7][(t[a[5]>>2]>>(24-8*(a[5]&3)))&0xff]
+				w ^= sBox[x[j]][(t[a[6]>>2]>>(24-8*(a[6]&3)))&0xff]
+				t[a[0]] = w
+			}
+
+			for j := 0; j < 4; j++ {
+				var b [5]uint8
+				copy(b[:], round.b[j][:])
+				w := sBox[4][(t[b[0]>>2]>>(24-8*(b[0]&3)))&0xff]
+				w ^= sBox[5][(t[b[1]>>2]>>(24-8*(b[1]&3)))&0xff]
+				w ^= sBox[6][(t[b[2]>>2]>>(24-8*(b[2]&3)))&0xff]
+				w ^= sBox[7][(t[b[3]>>2]>>(24-8*(b[3]&3)))&0xff]
+				w ^= sBox[4+j][(t[b[4]>>2]>>(24-8*(b[4]&3)))&0xff]
+				k[ki] = w
+				ki++
+			}
+		}
+	}
+
+	for i := 0; i < 16; i++ {
+		c.masking[i] = k[i]
+		c.rotate[i] = uint8(k[16+i] & 0x1f)
+	}
+}
+
+// These are the three 'f' functions. See RFC 2144, section 2.2.
+func f1(d, m uint32, r uint8) uint32 {
+	t := m + d
+	I := (t << r) | (t >> (32 - r))
+	return ((sBox[0][I>>24] ^ sBox[1][(I>>16)&0xff]) - sBox[2][(I>>8)&0xff]) + sBox[3][I&0xff]
+}
+
+func f2(d, m uint32, r uint8) uint32 {
+	t := m ^ d
+	I := (t << r) | (t >> (32 - r))
+	return ((sBox[0][I>>24] - sBox[1][(I>>16)&0xff]) + sBox[2][(I>>8)&0xff]) ^ sBox[3][I&0xff]
+}
+
+func f3(d, m uint32, r uint8) uint32 {
+	t := m - d
+	I := (t << r) | (t >> (32 - r))
+	return ((sBox[0][I>>24] + sBox[1][(I>>16)&0xff]) ^ sBox[2][(I>>8)&0xff]) - sBox[3][I&0xff]
+}
+
+var sBox = [8][256]uint32{
+	{
+		0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949,
+		0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
+		0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
+		0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0,
+		0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7,
+		0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,
+		0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d,
+		0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
+		0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,
+		0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3,
+		0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167,
+		0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,
+		0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779,
+		0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2,
+		0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,
+		0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d,
+		0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5,
+		0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,
+		0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
+		0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc,
+		0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,
+		0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96,
+		0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a,
+		0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
+		0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
+		0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6,
+		0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
+		0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872,
+		0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c,
+		0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,
+		0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9,
+		0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf,
+	},
+	{
+		0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651,
+		0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
+		0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,
+		0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
+		0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b,
+		0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,
+		0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b,
+		0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c,
+		0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,
+		0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb,
+		0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd,
+		0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,
+		0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b,
+		0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
+		0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,
+		0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
+		0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c,
+		0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,
+		0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f,
+		0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
+		0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,
+		0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58,
+		0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
+		0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
+		0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6,
+		0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
+		0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,
+		0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f,
+		0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
+		0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
+		0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9,
+		0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1,
+	},
+	{
+		0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90,
+		0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5,
+		0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,
+		0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240,
+		0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
+		0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
+		0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71,
+		0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
+		0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
+		0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15,
+		0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2,
+		0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,
+		0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148,
+		0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc,
+		0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
+		0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e,
+		0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
+		0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,
+		0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a,
+		0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b,
+		0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
+		0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
+		0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
+		0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,
+		0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
+		0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
+		0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,
+		0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
+		0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49,
+		0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,
+		0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a,
+		0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783,
+	},
+	{
+		0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1,
+		0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf,
+		0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,
+		0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121,
+		0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25,
+		0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
+		0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb,
+		0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5,
+		0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,
+		0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6,
+		0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23,
+		0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,
+		0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
+		0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119,
+		0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
+		0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a,
+		0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79,
+		0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,
+		0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
+		0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab,
+		0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,
+		0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
+		0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2,
+		0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,
+		0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
+		0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919,
+		0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
+		0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
+		0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab,
+		0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,
+		0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282,
+		0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2,
+	},
+	{
+		0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f,
+		0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a,
+		0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,
+		0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02,
+		0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a,
+		0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,
+		0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9,
+		0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981,
+		0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,
+		0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655,
+		0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2,
+		0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,
+		0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1,
+		0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da,
+		0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,
+		0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f,
+		0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba,
+		0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
+		0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3,
+		0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840,
+		0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,
+		0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2,
+		0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7,
+		0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,
+		0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e,
+		0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e,
+		0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,
+		0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad,
+		0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,
+		0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,
+		0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8,
+		0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4,
+	},
+	{
+		0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac,
+		0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138,
+		0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,
+		0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98,
+		0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072,
+		0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
+		0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd,
+		0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8,
+		0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,
+		0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54,
+		0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387,
+		0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,
+		0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf,
+		0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf,
+		0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,
+		0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289,
+		0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950,
+		0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
+		0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b,
+		0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be,
+		0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
+		0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976,
+		0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0,
+		0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,
+		0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da,
+		0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc,
+		0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,
+		0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25,
+		0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121,
+		0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
+		0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd,
+		0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f,
+	},
+	{
+		0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f,
+		0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de,
+		0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
+		0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19,
+		0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2,
+		0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,
+		0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,
+		0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816,
+		0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,
+		0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a,
+		0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264,
+		0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,
+		0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28,
+		0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3,
+		0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,
+		0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,
+		0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,
+		0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,
+		0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566,
+		0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,
+		0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,
+		0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e,
+		0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c,
+		0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
+		0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285,
+		0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301,
+		0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,
+		0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767,
+		0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647,
+		0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,
+		0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c,
+		0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3,
+	},
+	{
+		0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5,
+		0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc,
+		0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,
+		0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d,
+		0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2,
+		0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,
+		0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc,
+		0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c,
+		0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,
+		0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039,
+		0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8,
+		0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,
+		0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5,
+		0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472,
+		0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,
+		0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c,
+		0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb,
+		0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,
+		0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70,
+		0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc,
+		0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
+		0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3,
+		0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4,
+		0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,
+		0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f,
+		0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e,
+		0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
+		0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c,
+		0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384,
+		0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,
+		0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82,
+		0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e,
+	},
+}

+ 106 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/cast5/cast5_test.go

@@ -0,0 +1,106 @@
+// Copyright 2010 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 cast5
+
+import (
+	"bytes"
+	"encoding/hex"
+	"testing"
+)
+
+// This test vector is taken from RFC 2144, App B.1.
+// Since the other two test vectors are for reduced-round variants, we can't
+// use them.
+var basicTests = []struct {
+	key, plainText, cipherText string
+}{
+	{
+		"0123456712345678234567893456789a",
+		"0123456789abcdef",
+		"238b4fe5847e44b2",
+	},
+}
+
+func TestBasic(t *testing.T) {
+	for i, test := range basicTests {
+		key, _ := hex.DecodeString(test.key)
+		plainText, _ := hex.DecodeString(test.plainText)
+		expected, _ := hex.DecodeString(test.cipherText)
+
+		c, err := NewCipher(key)
+		if err != nil {
+			t.Errorf("#%d: failed to create Cipher: %s", i, err)
+			continue
+		}
+		var cipherText [BlockSize]byte
+		c.Encrypt(cipherText[:], plainText)
+		if !bytes.Equal(cipherText[:], expected) {
+			t.Errorf("#%d: got:%x want:%x", i, cipherText, expected)
+		}
+
+		var plainTextAgain [BlockSize]byte
+		c.Decrypt(plainTextAgain[:], cipherText[:])
+		if !bytes.Equal(plainTextAgain[:], plainText) {
+			t.Errorf("#%d: got:%x want:%x", i, plainTextAgain, plainText)
+		}
+	}
+}
+
+// TestFull performs the test specified in RFC 2144, App B.2.
+// However, due to the length of time taken, it's disabled here and a more
+// limited version is included, below.
+func TestFull(t *testing.T) {
+	if testing.Short() {
+		// This is too slow for normal testing
+		return
+	}
+
+	a, b := iterate(1000000)
+
+	const expectedA = "eea9d0a249fd3ba6b3436fb89d6dca92"
+	const expectedB = "b2c95eb00c31ad7180ac05b8e83d696e"
+
+	if hex.EncodeToString(a) != expectedA {
+		t.Errorf("a: got:%x want:%s", a, expectedA)
+	}
+	if hex.EncodeToString(b) != expectedB {
+		t.Errorf("b: got:%x want:%s", b, expectedB)
+	}
+}
+
+func iterate(iterations int) ([]byte, []byte) {
+	const initValueHex = "0123456712345678234567893456789a"
+
+	initValue, _ := hex.DecodeString(initValueHex)
+
+	var a, b [16]byte
+	copy(a[:], initValue)
+	copy(b[:], initValue)
+
+	for i := 0; i < iterations; i++ {
+		c, _ := NewCipher(b[:])
+		c.Encrypt(a[:8], a[:8])
+		c.Encrypt(a[8:], a[8:])
+		c, _ = NewCipher(a[:])
+		c.Encrypt(b[:8], b[:8])
+		c.Encrypt(b[8:], b[8:])
+	}
+
+	return a[:], b[:]
+}
+
+func TestLimited(t *testing.T) {
+	a, b := iterate(1000)
+
+	const expectedA = "23f73b14b02a2ad7dfb9f2c35644798d"
+	const expectedB = "e5bf37eff14c456a40b21ce369370a9f"
+
+	if hex.EncodeToString(a) != expectedA {
+		t.Errorf("a: got:%x want:%s", a, expectedA)
+	}
+	if hex.EncodeToString(b) != expectedB {
+		t.Errorf("b: got:%x want:%s", b, expectedB)
+	}
+}

+ 219 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/armor/armor.go

@@ -0,0 +1,219 @@
+// Copyright 2010 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 armor implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is
+// very similar to PEM except that it has an additional CRC checksum.
+package armor // import "golang.org/x/crypto/openpgp/armor"
+
+import (
+	"bufio"
+	"bytes"
+	"encoding/base64"
+	"golang.org/x/crypto/openpgp/errors"
+	"io"
+)
+
+// A Block represents an OpenPGP armored structure.
+//
+// The encoded form is:
+//    -----BEGIN Type-----
+//    Headers
+//
+//    base64-encoded Bytes
+//    '=' base64 encoded checksum
+//    -----END Type-----
+// where Headers is a possibly empty sequence of Key: Value lines.
+//
+// Since the armored data can be very large, this package presents a streaming
+// interface.
+type Block struct {
+	Type    string            // The type, taken from the preamble (i.e. "PGP SIGNATURE").
+	Header  map[string]string // Optional headers.
+	Body    io.Reader         // A Reader from which the contents can be read
+	lReader lineReader
+	oReader openpgpReader
+}
+
+var ArmorCorrupt error = errors.StructuralError("armor invalid")
+
+const crc24Init = 0xb704ce
+const crc24Poly = 0x1864cfb
+const crc24Mask = 0xffffff
+
+// crc24 calculates the OpenPGP checksum as specified in RFC 4880, section 6.1
+func crc24(crc uint32, d []byte) uint32 {
+	for _, b := range d {
+		crc ^= uint32(b) << 16
+		for i := 0; i < 8; i++ {
+			crc <<= 1
+			if crc&0x1000000 != 0 {
+				crc ^= crc24Poly
+			}
+		}
+	}
+	return crc
+}
+
+var armorStart = []byte("-----BEGIN ")
+var armorEnd = []byte("-----END ")
+var armorEndOfLine = []byte("-----")
+
+// lineReader wraps a line based reader. It watches for the end of an armor
+// block and records the expected CRC value.
+type lineReader struct {
+	in  *bufio.Reader
+	buf []byte
+	eof bool
+	crc uint32
+}
+
+func (l *lineReader) Read(p []byte) (n int, err error) {
+	if l.eof {
+		return 0, io.EOF
+	}
+
+	if len(l.buf) > 0 {
+		n = copy(p, l.buf)
+		l.buf = l.buf[n:]
+		return
+	}
+
+	line, isPrefix, err := l.in.ReadLine()
+	if err != nil {
+		return
+	}
+	if isPrefix {
+		return 0, ArmorCorrupt
+	}
+
+	if len(line) == 5 && line[0] == '=' {
+		// This is the checksum line
+		var expectedBytes [3]byte
+		var m int
+		m, err = base64.StdEncoding.Decode(expectedBytes[0:], line[1:])
+		if m != 3 || err != nil {
+			return
+		}
+		l.crc = uint32(expectedBytes[0])<<16 |
+			uint32(expectedBytes[1])<<8 |
+			uint32(expectedBytes[2])
+
+		line, _, err = l.in.ReadLine()
+		if err != nil && err != io.EOF {
+			return
+		}
+		if !bytes.HasPrefix(line, armorEnd) {
+			return 0, ArmorCorrupt
+		}
+
+		l.eof = true
+		return 0, io.EOF
+	}
+
+	if len(line) > 96 {
+		return 0, ArmorCorrupt
+	}
+
+	n = copy(p, line)
+	bytesToSave := len(line) - n
+	if bytesToSave > 0 {
+		if cap(l.buf) < bytesToSave {
+			l.buf = make([]byte, 0, bytesToSave)
+		}
+		l.buf = l.buf[0:bytesToSave]
+		copy(l.buf, line[n:])
+	}
+
+	return
+}
+
+// openpgpReader passes Read calls to the underlying base64 decoder, but keeps
+// a running CRC of the resulting data and checks the CRC against the value
+// found by the lineReader at EOF.
+type openpgpReader struct {
+	lReader    *lineReader
+	b64Reader  io.Reader
+	currentCRC uint32
+}
+
+func (r *openpgpReader) Read(p []byte) (n int, err error) {
+	n, err = r.b64Reader.Read(p)
+	r.currentCRC = crc24(r.currentCRC, p[:n])
+
+	if err == io.EOF {
+		if r.lReader.crc != uint32(r.currentCRC&crc24Mask) {
+			return 0, ArmorCorrupt
+		}
+	}
+
+	return
+}
+
+// Decode reads a PGP armored block from the given Reader. It will ignore
+// leading garbage. If it doesn't find a block, it will return nil, io.EOF. The
+// given Reader is not usable after calling this function: an arbitrary amount
+// of data may have been read past the end of the block.
+func Decode(in io.Reader) (p *Block, err error) {
+	r := bufio.NewReaderSize(in, 100)
+	var line []byte
+	ignoreNext := false
+
+TryNextBlock:
+	p = nil
+
+	// Skip leading garbage
+	for {
+		ignoreThis := ignoreNext
+		line, ignoreNext, err = r.ReadLine()
+		if err != nil {
+			return
+		}
+		if ignoreNext || ignoreThis {
+			continue
+		}
+		line = bytes.TrimSpace(line)
+		if len(line) > len(armorStart)+len(armorEndOfLine) && bytes.HasPrefix(line, armorStart) {
+			break
+		}
+	}
+
+	p = new(Block)
+	p.Type = string(line[len(armorStart) : len(line)-len(armorEndOfLine)])
+	p.Header = make(map[string]string)
+	nextIsContinuation := false
+	var lastKey string
+
+	// Read headers
+	for {
+		isContinuation := nextIsContinuation
+		line, nextIsContinuation, err = r.ReadLine()
+		if err != nil {
+			p = nil
+			return
+		}
+		if isContinuation {
+			p.Header[lastKey] += string(line)
+			continue
+		}
+		line = bytes.TrimSpace(line)
+		if len(line) == 0 {
+			break
+		}
+
+		i := bytes.Index(line, []byte(": "))
+		if i == -1 {
+			goto TryNextBlock
+		}
+		lastKey = string(line[:i])
+		p.Header[lastKey] = string(line[i+2:])
+	}
+
+	p.lReader.in = r
+	p.oReader.currentCRC = crc24Init
+	p.oReader.lReader = &p.lReader
+	p.oReader.b64Reader = base64.NewDecoder(base64.StdEncoding, &p.lReader)
+	p.Body = &p.oReader
+
+	return
+}

+ 95 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/armor/armor_test.go

@@ -0,0 +1,95 @@
+// Copyright 2010 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 armor
+
+import (
+	"bytes"
+	"hash/adler32"
+	"io/ioutil"
+	"testing"
+)
+
+func TestDecodeEncode(t *testing.T) {
+	buf := bytes.NewBuffer([]byte(armorExample1))
+	result, err := Decode(buf)
+	if err != nil {
+		t.Error(err)
+	}
+	expectedType := "PGP SIGNATURE"
+	if result.Type != expectedType {
+		t.Errorf("result.Type: got:%s want:%s", result.Type, expectedType)
+	}
+	if len(result.Header) != 1 {
+		t.Errorf("len(result.Header): got:%d want:1", len(result.Header))
+	}
+	v, ok := result.Header["Version"]
+	if !ok || v != "GnuPG v1.4.10 (GNU/Linux)" {
+		t.Errorf("result.Header: got:%#v", result.Header)
+	}
+
+	contents, err := ioutil.ReadAll(result.Body)
+	if err != nil {
+		t.Error(err)
+	}
+
+	if adler32.Checksum(contents) != 0x27b144be {
+		t.Errorf("contents: got: %x", contents)
+	}
+
+	buf = bytes.NewBuffer(nil)
+	w, err := Encode(buf, result.Type, result.Header)
+	if err != nil {
+		t.Error(err)
+	}
+	_, err = w.Write(contents)
+	if err != nil {
+		t.Error(err)
+	}
+	w.Close()
+
+	if !bytes.Equal(buf.Bytes(), []byte(armorExample1)) {
+		t.Errorf("got: %s\nwant: %s", string(buf.Bytes()), armorExample1)
+	}
+}
+
+func TestLongHeader(t *testing.T) {
+	buf := bytes.NewBuffer([]byte(armorLongLine))
+	result, err := Decode(buf)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	value, ok := result.Header["Version"]
+	if !ok {
+		t.Errorf("missing Version header")
+	}
+	if value != longValueExpected {
+		t.Errorf("got: %s want: %s", value, longValueExpected)
+	}
+}
+
+const armorExample1 = `-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.10 (GNU/Linux)
+
+iJwEAAECAAYFAk1Fv/0ACgkQo01+GMIMMbsYTwQAiAw+QAaNfY6WBdplZ/uMAccm
+4g+81QPmTSGHnetSb6WBiY13kVzK4HQiZH8JSkmmroMLuGeJwsRTEL4wbjRyUKEt
+p1xwUZDECs234F1xiG5enc5SGlRtP7foLBz9lOsjx+LEcA4sTl5/2eZR9zyFZqWW
+TxRjs+fJCIFuo71xb1g=
+=/teI
+-----END PGP SIGNATURE-----`
+
+const armorLongLine = `-----BEGIN PGP SIGNATURE-----
+Version: 0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz
+
+iQEcBAABAgAGBQJMtFESAAoJEKsQXJGvOPsVj40H/1WW6jaMXv4BW+1ueDSMDwM8
+kx1fLOXbVM5/Kn5LStZNt1jWWnpxdz7eq3uiqeCQjmqUoRde3YbB2EMnnwRbAhpp
+cacnAvy9ZQ78OTxUdNW1mhX5bS6q1MTEJnl+DcyigD70HG/yNNQD7sOPMdYQw0TA
+byQBwmLwmTsuZsrYqB68QyLHI+DUugn+kX6Hd2WDB62DKa2suoIUIHQQCd/ofwB3
+WfCYInXQKKOSxu2YOg2Eb4kLNhSMc1i9uKUWAH+sdgJh7NBgdoE4MaNtBFkHXRvv
+okWuf3+xA9ksp1npSY/mDvgHijmjvtpRDe6iUeqfCn8N9u9CBg8geANgaG8+QA4=
+=wfQG
+-----END PGP SIGNATURE-----`
+
+const longValueExpected = "0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz"

+ 160 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/armor/encode.go

@@ -0,0 +1,160 @@
+// Copyright 2010 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 armor
+
+import (
+	"encoding/base64"
+	"io"
+)
+
+var armorHeaderSep = []byte(": ")
+var blockEnd = []byte("\n=")
+var newline = []byte("\n")
+var armorEndOfLineOut = []byte("-----\n")
+
+// writeSlices writes its arguments to the given Writer.
+func writeSlices(out io.Writer, slices ...[]byte) (err error) {
+	for _, s := range slices {
+		_, err = out.Write(s)
+		if err != nil {
+			return err
+		}
+	}
+	return
+}
+
+// lineBreaker breaks data across several lines, all of the same byte length
+// (except possibly the last). Lines are broken with a single '\n'.
+type lineBreaker struct {
+	lineLength  int
+	line        []byte
+	used        int
+	out         io.Writer
+	haveWritten bool
+}
+
+func newLineBreaker(out io.Writer, lineLength int) *lineBreaker {
+	return &lineBreaker{
+		lineLength: lineLength,
+		line:       make([]byte, lineLength),
+		used:       0,
+		out:        out,
+	}
+}
+
+func (l *lineBreaker) Write(b []byte) (n int, err error) {
+	n = len(b)
+
+	if n == 0 {
+		return
+	}
+
+	if l.used == 0 && l.haveWritten {
+		_, err = l.out.Write([]byte{'\n'})
+		if err != nil {
+			return
+		}
+	}
+
+	if l.used+len(b) < l.lineLength {
+		l.used += copy(l.line[l.used:], b)
+		return
+	}
+
+	l.haveWritten = true
+	_, err = l.out.Write(l.line[0:l.used])
+	if err != nil {
+		return
+	}
+	excess := l.lineLength - l.used
+	l.used = 0
+
+	_, err = l.out.Write(b[0:excess])
+	if err != nil {
+		return
+	}
+
+	_, err = l.Write(b[excess:])
+	return
+}
+
+func (l *lineBreaker) Close() (err error) {
+	if l.used > 0 {
+		_, err = l.out.Write(l.line[0:l.used])
+		if err != nil {
+			return
+		}
+	}
+
+	return
+}
+
+// encoding keeps track of a running CRC24 over the data which has been written
+// to it and outputs a OpenPGP checksum when closed, followed by an armor
+// trailer.
+//
+// It's built into a stack of io.Writers:
+//    encoding -> base64 encoder -> lineBreaker -> out
+type encoding struct {
+	out       io.Writer
+	breaker   *lineBreaker
+	b64       io.WriteCloser
+	crc       uint32
+	blockType []byte
+}
+
+func (e *encoding) Write(data []byte) (n int, err error) {
+	e.crc = crc24(e.crc, data)
+	return e.b64.Write(data)
+}
+
+func (e *encoding) Close() (err error) {
+	err = e.b64.Close()
+	if err != nil {
+		return
+	}
+	e.breaker.Close()
+
+	var checksumBytes [3]byte
+	checksumBytes[0] = byte(e.crc >> 16)
+	checksumBytes[1] = byte(e.crc >> 8)
+	checksumBytes[2] = byte(e.crc)
+
+	var b64ChecksumBytes [4]byte
+	base64.StdEncoding.Encode(b64ChecksumBytes[:], checksumBytes[:])
+
+	return writeSlices(e.out, blockEnd, b64ChecksumBytes[:], newline, armorEnd, e.blockType, armorEndOfLine)
+}
+
+// Encode returns a WriteCloser which will encode the data written to it in
+// OpenPGP armor.
+func Encode(out io.Writer, blockType string, headers map[string]string) (w io.WriteCloser, err error) {
+	bType := []byte(blockType)
+	err = writeSlices(out, armorStart, bType, armorEndOfLineOut)
+	if err != nil {
+		return
+	}
+
+	for k, v := range headers {
+		err = writeSlices(out, []byte(k), armorHeaderSep, []byte(v), newline)
+		if err != nil {
+			return
+		}
+	}
+
+	_, err = out.Write(newline)
+	if err != nil {
+		return
+	}
+
+	e := &encoding{
+		out:       out,
+		breaker:   newLineBreaker(out, 64),
+		crc:       crc24Init,
+		blockType: bType,
+	}
+	e.b64 = base64.NewEncoder(base64.StdEncoding, e.breaker)
+	return e, nil
+}

+ 59 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/canonical_text.go

@@ -0,0 +1,59 @@
+// Copyright 2011 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 openpgp
+
+import "hash"
+
+// NewCanonicalTextHash reformats text written to it into the canonical
+// form and then applies the hash h.  See RFC 4880, section 5.2.1.
+func NewCanonicalTextHash(h hash.Hash) hash.Hash {
+	return &canonicalTextHash{h, 0}
+}
+
+type canonicalTextHash struct {
+	h hash.Hash
+	s int
+}
+
+var newline = []byte{'\r', '\n'}
+
+func (cth *canonicalTextHash) Write(buf []byte) (int, error) {
+	start := 0
+
+	for i, c := range buf {
+		switch cth.s {
+		case 0:
+			if c == '\r' {
+				cth.s = 1
+			} else if c == '\n' {
+				cth.h.Write(buf[start:i])
+				cth.h.Write(newline)
+				start = i + 1
+			}
+		case 1:
+			cth.s = 0
+		}
+	}
+
+	cth.h.Write(buf[start:])
+	return len(buf), nil
+}
+
+func (cth *canonicalTextHash) Sum(in []byte) []byte {
+	return cth.h.Sum(in)
+}
+
+func (cth *canonicalTextHash) Reset() {
+	cth.h.Reset()
+	cth.s = 0
+}
+
+func (cth *canonicalTextHash) Size() int {
+	return cth.h.Size()
+}
+
+func (cth *canonicalTextHash) BlockSize() int {
+	return cth.h.BlockSize()
+}

+ 52 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/canonical_text_test.go

@@ -0,0 +1,52 @@
+// Copyright 2011 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 openpgp
+
+import (
+	"bytes"
+	"testing"
+)
+
+type recordingHash struct {
+	buf *bytes.Buffer
+}
+
+func (r recordingHash) Write(b []byte) (n int, err error) {
+	return r.buf.Write(b)
+}
+
+func (r recordingHash) Sum(in []byte) []byte {
+	return append(in, r.buf.Bytes()...)
+}
+
+func (r recordingHash) Reset() {
+	panic("shouldn't be called")
+}
+
+func (r recordingHash) Size() int {
+	panic("shouldn't be called")
+}
+
+func (r recordingHash) BlockSize() int {
+	panic("shouldn't be called")
+}
+
+func testCanonicalText(t *testing.T, input, expected string) {
+	r := recordingHash{bytes.NewBuffer(nil)}
+	c := NewCanonicalTextHash(r)
+	c.Write([]byte(input))
+	result := c.Sum(nil)
+	if expected != string(result) {
+		t.Errorf("input: %x got: %x want: %x", input, result, expected)
+	}
+}
+
+func TestCanonicalText(t *testing.T) {
+	testCanonicalText(t, "foo\n", "foo\r\n")
+	testCanonicalText(t, "foo", "foo")
+	testCanonicalText(t, "foo\r\n", "foo\r\n")
+	testCanonicalText(t, "foo\r\nbar", "foo\r\nbar")
+	testCanonicalText(t, "foo\r\nbar\n\n", "foo\r\nbar\r\n\r\n")
+}

+ 376 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/clearsign/clearsign.go

@@ -0,0 +1,376 @@
+// Copyright 2012 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 clearsign generates and processes OpenPGP, clear-signed data. See
+// RFC 4880, section 7.
+//
+// Clearsigned messages are cryptographically signed, but the contents of the
+// message are kept in plaintext so that it can be read without special tools.
+package clearsign // import "golang.org/x/crypto/openpgp/clearsign"
+
+import (
+	"bufio"
+	"bytes"
+	"crypto"
+	"hash"
+	"io"
+	"net/textproto"
+	"strconv"
+
+	"golang.org/x/crypto/openpgp/armor"
+	"golang.org/x/crypto/openpgp/errors"
+	"golang.org/x/crypto/openpgp/packet"
+)
+
+// A Block represents a clearsigned message. A signature on a Block can
+// be checked by passing Bytes into openpgp.CheckDetachedSignature.
+type Block struct {
+	Headers          textproto.MIMEHeader // Optional message headers
+	Plaintext        []byte               // The original message text
+	Bytes            []byte               // The signed message
+	ArmoredSignature *armor.Block         // The signature block
+}
+
+// start is the marker which denotes the beginning of a clearsigned message.
+var start = []byte("\n-----BEGIN PGP SIGNED MESSAGE-----")
+
+// dashEscape is prefixed to any lines that begin with a hyphen so that they
+// can't be confused with endText.
+var dashEscape = []byte("- ")
+
+// endText is a marker which denotes the end of the message and the start of
+// an armored signature.
+var endText = []byte("-----BEGIN PGP SIGNATURE-----")
+
+// end is a marker which denotes the end of the armored signature.
+var end = []byte("\n-----END PGP SIGNATURE-----")
+
+var crlf = []byte("\r\n")
+var lf = byte('\n')
+
+// getLine returns the first \r\n or \n delineated line from the given byte
+// array. The line does not include the \r\n or \n. The remainder of the byte
+// array (also not including the new line bytes) is also returned and this will
+// always be smaller than the original argument.
+func getLine(data []byte) (line, rest []byte) {
+	i := bytes.Index(data, []byte{'\n'})
+	var j int
+	if i < 0 {
+		i = len(data)
+		j = i
+	} else {
+		j = i + 1
+		if i > 0 && data[i-1] == '\r' {
+			i--
+		}
+	}
+	return data[0:i], data[j:]
+}
+
+// Decode finds the first clearsigned message in data and returns it, as well
+// as the suffix of data which remains after the message.
+func Decode(data []byte) (b *Block, rest []byte) {
+	// start begins with a newline. However, at the very beginning of
+	// the byte array, we'll accept the start string without it.
+	rest = data
+	if bytes.HasPrefix(data, start[1:]) {
+		rest = rest[len(start)-1:]
+	} else if i := bytes.Index(data, start); i >= 0 {
+		rest = rest[i+len(start):]
+	} else {
+		return nil, data
+	}
+
+	// Consume the start line.
+	_, rest = getLine(rest)
+
+	var line []byte
+	b = &Block{
+		Headers: make(textproto.MIMEHeader),
+	}
+
+	// Next come a series of header lines.
+	for {
+		// This loop terminates because getLine's second result is
+		// always smaller than its argument.
+		if len(rest) == 0 {
+			return nil, data
+		}
+		// An empty line marks the end of the headers.
+		if line, rest = getLine(rest); len(line) == 0 {
+			break
+		}
+
+		i := bytes.Index(line, []byte{':'})
+		if i == -1 {
+			return nil, data
+		}
+
+		key, val := line[0:i], line[i+1:]
+		key = bytes.TrimSpace(key)
+		val = bytes.TrimSpace(val)
+		b.Headers.Add(string(key), string(val))
+	}
+
+	firstLine := true
+	for {
+		start := rest
+
+		line, rest = getLine(rest)
+		if len(line) == 0 && len(rest) == 0 {
+			// No armored data was found, so this isn't a complete message.
+			return nil, data
+		}
+		if bytes.Equal(line, endText) {
+			// Back up to the start of the line because armor expects to see the
+			// header line.
+			rest = start
+			break
+		}
+
+		// The final CRLF isn't included in the hash so we don't write it until
+		// we've seen the next line.
+		if firstLine {
+			firstLine = false
+		} else {
+			b.Bytes = append(b.Bytes, crlf...)
+		}
+
+		if bytes.HasPrefix(line, dashEscape) {
+			line = line[2:]
+		}
+		line = bytes.TrimRight(line, " \t")
+		b.Bytes = append(b.Bytes, line...)
+
+		b.Plaintext = append(b.Plaintext, line...)
+		b.Plaintext = append(b.Plaintext, lf)
+	}
+
+	// We want to find the extent of the armored data (including any newlines at
+	// the end).
+	i := bytes.Index(rest, end)
+	if i == -1 {
+		return nil, data
+	}
+	i += len(end)
+	for i < len(rest) && (rest[i] == '\r' || rest[i] == '\n') {
+		i++
+	}
+	armored := rest[:i]
+	rest = rest[i:]
+
+	var err error
+	b.ArmoredSignature, err = armor.Decode(bytes.NewBuffer(armored))
+	if err != nil {
+		return nil, data
+	}
+
+	return b, rest
+}
+
+// A dashEscaper is an io.WriteCloser which processes the body of a clear-signed
+// message. The clear-signed message is written to buffered and a hash, suitable
+// for signing, is maintained in h.
+//
+// When closed, an armored signature is created and written to complete the
+// message.
+type dashEscaper struct {
+	buffered *bufio.Writer
+	h        hash.Hash
+	hashType crypto.Hash
+
+	atBeginningOfLine bool
+	isFirstLine       bool
+
+	whitespace []byte
+	byteBuf    []byte // a one byte buffer to save allocations
+
+	privateKey *packet.PrivateKey
+	config     *packet.Config
+}
+
+func (d *dashEscaper) Write(data []byte) (n int, err error) {
+	for _, b := range data {
+		d.byteBuf[0] = b
+
+		if d.atBeginningOfLine {
+			// The final CRLF isn't included in the hash so we have to wait
+			// until this point (the start of the next line) before writing it.
+			if !d.isFirstLine {
+				d.h.Write(crlf)
+			}
+			d.isFirstLine = false
+		}
+
+		// Any whitespace at the end of the line has to be removed so we
+		// buffer it until we find out whether there's more on this line.
+		if b == ' ' || b == '\t' || b == '\r' {
+			d.whitespace = append(d.whitespace, b)
+			d.atBeginningOfLine = false
+			continue
+		}
+
+		if d.atBeginningOfLine {
+			// At the beginning of a line, hyphens have to be escaped.
+			if b == '-' {
+				// The signature isn't calculated over the dash-escaped text so
+				// the escape is only written to buffered.
+				if _, err = d.buffered.Write(dashEscape); err != nil {
+					return
+				}
+				d.h.Write(d.byteBuf)
+				d.atBeginningOfLine = false
+			} else if b == '\n' {
+				// Nothing to do because we delay writing CRLF to the hash.
+			} else {
+				d.h.Write(d.byteBuf)
+				d.atBeginningOfLine = false
+			}
+			if err = d.buffered.WriteByte(b); err != nil {
+				return
+			}
+		} else {
+			if b == '\n' {
+				// We got a raw \n. Drop any trailing whitespace and write a
+				// CRLF.
+				d.whitespace = d.whitespace[:0]
+				// We delay writing CRLF to the hash until the start of the
+				// next line.
+				if err = d.buffered.WriteByte(b); err != nil {
+					return
+				}
+				d.atBeginningOfLine = true
+			} else {
+				// Any buffered whitespace wasn't at the end of the line so
+				// we need to write it out.
+				if len(d.whitespace) > 0 {
+					d.h.Write(d.whitespace)
+					if _, err = d.buffered.Write(d.whitespace); err != nil {
+						return
+					}
+					d.whitespace = d.whitespace[:0]
+				}
+				d.h.Write(d.byteBuf)
+				if err = d.buffered.WriteByte(b); err != nil {
+					return
+				}
+			}
+		}
+	}
+
+	n = len(data)
+	return
+}
+
+func (d *dashEscaper) Close() (err error) {
+	if !d.atBeginningOfLine {
+		if err = d.buffered.WriteByte(lf); err != nil {
+			return
+		}
+	}
+	sig := new(packet.Signature)
+	sig.SigType = packet.SigTypeText
+	sig.PubKeyAlgo = d.privateKey.PubKeyAlgo
+	sig.Hash = d.hashType
+	sig.CreationTime = d.config.Now()
+	sig.IssuerKeyId = &d.privateKey.KeyId
+
+	if err = sig.Sign(d.h, d.privateKey, d.config); err != nil {
+		return
+	}
+
+	out, err := armor.Encode(d.buffered, "PGP SIGNATURE", nil)
+	if err != nil {
+		return
+	}
+
+	if err = sig.Serialize(out); err != nil {
+		return
+	}
+	if err = out.Close(); err != nil {
+		return
+	}
+	if err = d.buffered.Flush(); err != nil {
+		return
+	}
+	return
+}
+
+// Encode returns a WriteCloser which will clear-sign a message with privateKey
+// and write it to w. If config is nil, sensible defaults are used.
+func Encode(w io.Writer, privateKey *packet.PrivateKey, config *packet.Config) (plaintext io.WriteCloser, err error) {
+	if privateKey.Encrypted {
+		return nil, errors.InvalidArgumentError("signing key is encrypted")
+	}
+
+	hashType := config.Hash()
+	name := nameOfHash(hashType)
+	if len(name) == 0 {
+		return nil, errors.UnsupportedError("unknown hash type: " + strconv.Itoa(int(hashType)))
+	}
+
+	if !hashType.Available() {
+		return nil, errors.UnsupportedError("unsupported hash type: " + strconv.Itoa(int(hashType)))
+	}
+	h := hashType.New()
+
+	buffered := bufio.NewWriter(w)
+	// start has a \n at the beginning that we don't want here.
+	if _, err = buffered.Write(start[1:]); err != nil {
+		return
+	}
+	if err = buffered.WriteByte(lf); err != nil {
+		return
+	}
+	if _, err = buffered.WriteString("Hash: "); err != nil {
+		return
+	}
+	if _, err = buffered.WriteString(name); err != nil {
+		return
+	}
+	if err = buffered.WriteByte(lf); err != nil {
+		return
+	}
+	if err = buffered.WriteByte(lf); err != nil {
+		return
+	}
+
+	plaintext = &dashEscaper{
+		buffered: buffered,
+		h:        h,
+		hashType: hashType,
+
+		atBeginningOfLine: true,
+		isFirstLine:       true,
+
+		byteBuf: make([]byte, 1),
+
+		privateKey: privateKey,
+		config:     config,
+	}
+
+	return
+}
+
+// nameOfHash returns the OpenPGP name for the given hash, or the empty string
+// if the name isn't known. See RFC 4880, section 9.4.
+func nameOfHash(h crypto.Hash) string {
+	switch h {
+	case crypto.MD5:
+		return "MD5"
+	case crypto.SHA1:
+		return "SHA1"
+	case crypto.RIPEMD160:
+		return "RIPEMD160"
+	case crypto.SHA224:
+		return "SHA224"
+	case crypto.SHA256:
+		return "SHA256"
+	case crypto.SHA384:
+		return "SHA384"
+	case crypto.SHA512:
+		return "SHA512"
+	}
+	return ""
+}

+ 210 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go

@@ -0,0 +1,210 @@
+// Copyright 2012 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 clearsign
+
+import (
+	"bytes"
+	"golang.org/x/crypto/openpgp"
+	"testing"
+)
+
+func testParse(t *testing.T, input []byte, expected, expectedPlaintext string) {
+	b, rest := Decode(input)
+	if b == nil {
+		t.Fatal("failed to decode clearsign message")
+	}
+	if !bytes.Equal(rest, []byte("trailing")) {
+		t.Errorf("unexpected remaining bytes returned: %s", string(rest))
+	}
+	if b.ArmoredSignature.Type != "PGP SIGNATURE" {
+		t.Errorf("bad armor type, got:%s, want:PGP SIGNATURE", b.ArmoredSignature.Type)
+	}
+	if !bytes.Equal(b.Bytes, []byte(expected)) {
+		t.Errorf("bad body, got:%x want:%x", b.Bytes, expected)
+	}
+
+	if !bytes.Equal(b.Plaintext, []byte(expectedPlaintext)) {
+		t.Errorf("bad plaintext, got:%x want:%x", b.Plaintext, expectedPlaintext)
+	}
+
+	keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(signingKey))
+	if err != nil {
+		t.Errorf("failed to parse public key: %s", err)
+	}
+
+	if _, err := openpgp.CheckDetachedSignature(keyring, bytes.NewBuffer(b.Bytes), b.ArmoredSignature.Body); err != nil {
+		t.Errorf("failed to check signature: %s", err)
+	}
+}
+
+func TestParse(t *testing.T) {
+	testParse(t, clearsignInput, "Hello world\r\nline 2", "Hello world\nline 2\n")
+	testParse(t, clearsignInput2, "\r\n\r\n(This message has a couple of blank lines at the start and end.)\r\n\r\n", "\n\n(This message has a couple of blank lines at the start and end.)\n\n\n")
+}
+
+func TestParseInvalid(t *testing.T) {
+	if b, _ := Decode(clearsignInput3); b != nil {
+		t.Fatal("decoded a bad clearsigned message without any error")
+	}
+}
+
+func TestParseWithNoNewlineAtEnd(t *testing.T) {
+	input := clearsignInput
+	input = input[:len(input)-len("trailing")-1]
+	b, rest := Decode(input)
+	if b == nil {
+		t.Fatal("failed to decode clearsign message")
+	}
+	if len(rest) > 0 {
+		t.Errorf("unexpected remaining bytes returned: %s", string(rest))
+	}
+}
+
+var signingTests = []struct {
+	in, signed, plaintext string
+}{
+	{"", "", ""},
+	{"a", "a", "a\n"},
+	{"a\n", "a", "a\n"},
+	{"-a\n", "-a", "-a\n"},
+	{"--a\nb", "--a\r\nb", "--a\nb\n"},
+	// leading whitespace
+	{" a\n", " a", " a\n"},
+	{"  a\n", "  a", "  a\n"},
+	// trailing whitespace (should be stripped)
+	{"a \n", "a", "a\n"},
+	{"a ", "a", "a\n"},
+	// whitespace-only lines (should be stripped)
+	{"  \n", "", "\n"},
+	{"  ", "", "\n"},
+	{"a\n  \n  \nb\n", "a\r\n\r\n\r\nb", "a\n\n\nb\n"},
+}
+
+func TestSigning(t *testing.T) {
+	keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(signingKey))
+	if err != nil {
+		t.Errorf("failed to parse public key: %s", err)
+	}
+
+	for i, test := range signingTests {
+		var buf bytes.Buffer
+
+		plaintext, err := Encode(&buf, keyring[0].PrivateKey, nil)
+		if err != nil {
+			t.Errorf("#%d: error from Encode: %s", i, err)
+			continue
+		}
+		if _, err := plaintext.Write([]byte(test.in)); err != nil {
+			t.Errorf("#%d: error from Write: %s", i, err)
+			continue
+		}
+		if err := plaintext.Close(); err != nil {
+			t.Fatalf("#%d: error from Close: %s", i, err)
+			continue
+		}
+
+		b, _ := Decode(buf.Bytes())
+		if b == nil {
+			t.Errorf("#%d: failed to decode clearsign message", i)
+			continue
+		}
+		if !bytes.Equal(b.Bytes, []byte(test.signed)) {
+			t.Errorf("#%d: bad result, got:%x, want:%x", i, b.Bytes, test.signed)
+			continue
+		}
+		if !bytes.Equal(b.Plaintext, []byte(test.plaintext)) {
+			t.Errorf("#%d: bad result, got:%x, want:%x", i, b.Plaintext, test.plaintext)
+			continue
+		}
+
+		if _, err := openpgp.CheckDetachedSignature(keyring, bytes.NewBuffer(b.Bytes), b.ArmoredSignature.Body); err != nil {
+			t.Errorf("#%d: failed to check signature: %s", i, err)
+		}
+	}
+}
+
+var clearsignInput = []byte(`
+;lasjlkfdsa
+
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+Hello world
+line 2
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.10 (GNU/Linux)
+
+iJwEAQECAAYFAk8kMuEACgkQO9o98PRieSpMsAQAhmY/vwmNpflrPgmfWsYhk5O8
+pjnBUzZwqTDoDeINjZEoPDSpQAHGhjFjgaDx/Gj4fAl0dM4D0wuUEBb6QOrwflog
+2A2k9kfSOMOtk0IH/H5VuFN1Mie9L/erYXjTQIptv9t9J7NoRBMU0QOOaFU0JaO9
+MyTpno24AjIAGb+mH1U=
+=hIJ6
+-----END PGP SIGNATURE-----
+trailing`)
+
+var clearsignInput2 = []byte(`
+asdlfkjasdlkfjsadf
+
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA256
+
+
+
+(This message has a couple of blank lines at the start and end.)
+
+
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.11 (GNU/Linux)
+
+iJwEAQEIAAYFAlPpSREACgkQO9o98PRieSpZTAP+M8QUoCt/7Rf3YbXPcdzIL32v
+pt1I+cMNeopzfLy0u4ioEFi8s5VkwpL1AFmirvgViCwlf82inoRxzZRiW05JQ5LI
+ESEzeCoy2LIdRCQ2hcrG8pIUPzUO4TqO5D/dMbdHwNH4h5nNmGJUAEG6FpURlPm+
+qZg6BaTvOxepqOxnhVU=
+=e+C6
+-----END PGP SIGNATURE-----
+
+trailing`)
+
+var clearsignInput3 = []byte(`
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA256
+
+(This message was truncated.)
+`)
+
+var signingKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v1.4.10 (GNU/Linux)
+
+lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp
+idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn
+vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB
+AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X
+0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL
+IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk
+VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn
+gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9
+TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx
+q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz
+dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA
+CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1
+ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+
+eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid
+AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV
+bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK
+/UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA
+A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX
+TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc
+lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6
+rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN
+oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8
+QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU
+nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC
+AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp
+BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad
+AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL
+VrM0m72/jnpKo04=
+=zNCn
+-----END PGP PRIVATE KEY BLOCK-----
+`

+ 122 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/elgamal/elgamal.go

@@ -0,0 +1,122 @@
+// Copyright 2011 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 elgamal implements ElGamal encryption, suitable for OpenPGP,
+// as specified in "A Public-Key Cryptosystem and a Signature Scheme Based on
+// Discrete Logarithms," IEEE Transactions on Information Theory, v. IT-31,
+// n. 4, 1985, pp. 469-472.
+//
+// This form of ElGamal embeds PKCS#1 v1.5 padding, which may make it
+// unsuitable for other protocols. RSA should be used in preference in any
+// case.
+package elgamal // import "golang.org/x/crypto/openpgp/elgamal"
+
+import (
+	"crypto/rand"
+	"crypto/subtle"
+	"errors"
+	"io"
+	"math/big"
+)
+
+// PublicKey represents an ElGamal public key.
+type PublicKey struct {
+	G, P, Y *big.Int
+}
+
+// PrivateKey represents an ElGamal private key.
+type PrivateKey struct {
+	PublicKey
+	X *big.Int
+}
+
+// Encrypt encrypts the given message to the given public key. The result is a
+// pair of integers. Errors can result from reading random, or because msg is
+// too large to be encrypted to the public key.
+func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err error) {
+	pLen := (pub.P.BitLen() + 7) / 8
+	if len(msg) > pLen-11 {
+		err = errors.New("elgamal: message too long")
+		return
+	}
+
+	// EM = 0x02 || PS || 0x00 || M
+	em := make([]byte, pLen-1)
+	em[0] = 2
+	ps, mm := em[1:len(em)-len(msg)-1], em[len(em)-len(msg):]
+	err = nonZeroRandomBytes(ps, random)
+	if err != nil {
+		return
+	}
+	em[len(em)-len(msg)-1] = 0
+	copy(mm, msg)
+
+	m := new(big.Int).SetBytes(em)
+
+	k, err := rand.Int(random, pub.P)
+	if err != nil {
+		return
+	}
+
+	c1 = new(big.Int).Exp(pub.G, k, pub.P)
+	s := new(big.Int).Exp(pub.Y, k, pub.P)
+	c2 = s.Mul(s, m)
+	c2.Mod(c2, pub.P)
+
+	return
+}
+
+// Decrypt takes two integers, resulting from an ElGamal encryption, and
+// returns the plaintext of the message. An error can result only if the
+// ciphertext is invalid. Users should keep in mind that this is a padding
+// oracle and thus, if exposed to an adaptive chosen ciphertext attack, can
+// be used to break the cryptosystem.  See ``Chosen Ciphertext Attacks
+// Against Protocols Based on the RSA Encryption Standard PKCS #1'', Daniel
+// Bleichenbacher, Advances in Cryptology (Crypto '98),
+func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) {
+	s := new(big.Int).Exp(c1, priv.X, priv.P)
+	s.ModInverse(s, priv.P)
+	s.Mul(s, c2)
+	s.Mod(s, priv.P)
+	em := s.Bytes()
+
+	firstByteIsTwo := subtle.ConstantTimeByteEq(em[0], 2)
+
+	// The remainder of the plaintext must be a string of non-zero random
+	// octets, followed by a 0, followed by the message.
+	//   lookingForIndex: 1 iff we are still looking for the zero.
+	//   index: the offset of the first zero byte.
+	var lookingForIndex, index int
+	lookingForIndex = 1
+
+	for i := 1; i < len(em); i++ {
+		equals0 := subtle.ConstantTimeByteEq(em[i], 0)
+		index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index)
+		lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex)
+	}
+
+	if firstByteIsTwo != 1 || lookingForIndex != 0 || index < 9 {
+		return nil, errors.New("elgamal: decryption error")
+	}
+	return em[index+1:], nil
+}
+
+// nonZeroRandomBytes fills the given slice with non-zero random octets.
+func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) {
+	_, err = io.ReadFull(rand, s)
+	if err != nil {
+		return
+	}
+
+	for i := 0; i < len(s); i++ {
+		for s[i] == 0 {
+			_, err = io.ReadFull(rand, s[i:i+1])
+			if err != nil {
+				return
+			}
+		}
+	}
+
+	return
+}

+ 49 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go

@@ -0,0 +1,49 @@
+// Copyright 2011 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 elgamal
+
+import (
+	"bytes"
+	"crypto/rand"
+	"math/big"
+	"testing"
+)
+
+// This is the 1024-bit MODP group from RFC 5114, section 2.1:
+const primeHex = "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C69A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C013ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD7098488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708DF1FB2BC2E4A4371"
+
+const generatorHex = "A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507FD6406CFF14266D31266FEA1E5C41564B777E690F5504F213160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28AD662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24855E6EEB22B3B2E5"
+
+func fromHex(hex string) *big.Int {
+	n, ok := new(big.Int).SetString(hex, 16)
+	if !ok {
+		panic("failed to parse hex number")
+	}
+	return n
+}
+
+func TestEncryptDecrypt(t *testing.T) {
+	priv := &PrivateKey{
+		PublicKey: PublicKey{
+			G: fromHex(generatorHex),
+			P: fromHex(primeHex),
+		},
+		X: fromHex("42"),
+	}
+	priv.Y = new(big.Int).Exp(priv.G, priv.X, priv.P)
+
+	message := []byte("hello world")
+	c1, c2, err := Encrypt(rand.Reader, &priv.PublicKey, message)
+	if err != nil {
+		t.Errorf("error encrypting: %s", err)
+	}
+	message2, err := Decrypt(priv, c1, c2)
+	if err != nil {
+		t.Errorf("error decrypting: %s", err)
+	}
+	if !bytes.Equal(message2, message) {
+		t.Errorf("decryption failed, got: %x, want: %x", message2, message)
+	}
+}

+ 72 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/errors/errors.go

@@ -0,0 +1,72 @@
+// Copyright 2010 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 errors contains common error types for the OpenPGP packages.
+package errors // import "golang.org/x/crypto/openpgp/errors"
+
+import (
+	"strconv"
+)
+
+// A StructuralError is returned when OpenPGP data is found to be syntactically
+// invalid.
+type StructuralError string
+
+func (s StructuralError) Error() string {
+	return "openpgp: invalid data: " + string(s)
+}
+
+// UnsupportedError indicates that, although the OpenPGP data is valid, it
+// makes use of currently unimplemented features.
+type UnsupportedError string
+
+func (s UnsupportedError) Error() string {
+	return "openpgp: unsupported feature: " + string(s)
+}
+
+// InvalidArgumentError indicates that the caller is in error and passed an
+// incorrect value.
+type InvalidArgumentError string
+
+func (i InvalidArgumentError) Error() string {
+	return "openpgp: invalid argument: " + string(i)
+}
+
+// SignatureError indicates that a syntactically valid signature failed to
+// validate.
+type SignatureError string
+
+func (b SignatureError) Error() string {
+	return "openpgp: invalid signature: " + string(b)
+}
+
+type keyIncorrectError int
+
+func (ki keyIncorrectError) Error() string {
+	return "openpgp: incorrect key"
+}
+
+var ErrKeyIncorrect error = keyIncorrectError(0)
+
+type unknownIssuerError int
+
+func (unknownIssuerError) Error() string {
+	return "openpgp: signature made by unknown entity"
+}
+
+var ErrUnknownIssuer error = unknownIssuerError(0)
+
+type keyRevokedError int
+
+func (keyRevokedError) Error() string {
+	return "openpgp: signature made by revoked key"
+}
+
+var ErrKeyRevoked error = keyRevokedError(0)
+
+type UnknownPacketTypeError uint8
+
+func (upte UnknownPacketTypeError) Error() string {
+	return "openpgp: unknown packet type: " + strconv.Itoa(int(upte))
+}

+ 633 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/keys.go

@@ -0,0 +1,633 @@
+// Copyright 2011 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 openpgp
+
+import (
+	"crypto/rsa"
+	"io"
+	"time"
+
+	"golang.org/x/crypto/openpgp/armor"
+	"golang.org/x/crypto/openpgp/errors"
+	"golang.org/x/crypto/openpgp/packet"
+)
+
+// PublicKeyType is the armor type for a PGP public key.
+var PublicKeyType = "PGP PUBLIC KEY BLOCK"
+
+// PrivateKeyType is the armor type for a PGP private key.
+var PrivateKeyType = "PGP PRIVATE KEY BLOCK"
+
+// An Entity represents the components of an OpenPGP key: a primary public key
+// (which must be a signing key), one or more identities claimed by that key,
+// and zero or more subkeys, which may be encryption keys.
+type Entity struct {
+	PrimaryKey  *packet.PublicKey
+	PrivateKey  *packet.PrivateKey
+	Identities  map[string]*Identity // indexed by Identity.Name
+	Revocations []*packet.Signature
+	Subkeys     []Subkey
+}
+
+// An Identity represents an identity claimed by an Entity and zero or more
+// assertions by other entities about that claim.
+type Identity struct {
+	Name          string // by convention, has the form "Full Name (comment) <[email protected]>"
+	UserId        *packet.UserId
+	SelfSignature *packet.Signature
+	Signatures    []*packet.Signature
+}
+
+// A Subkey is an additional public key in an Entity. Subkeys can be used for
+// encryption.
+type Subkey struct {
+	PublicKey  *packet.PublicKey
+	PrivateKey *packet.PrivateKey
+	Sig        *packet.Signature
+}
+
+// A Key identifies a specific public key in an Entity. This is either the
+// Entity's primary key or a subkey.
+type Key struct {
+	Entity        *Entity
+	PublicKey     *packet.PublicKey
+	PrivateKey    *packet.PrivateKey
+	SelfSignature *packet.Signature
+}
+
+// A KeyRing provides access to public and private keys.
+type KeyRing interface {
+	// KeysById returns the set of keys that have the given key id.
+	KeysById(id uint64) []Key
+	// KeysByIdAndUsage returns the set of keys with the given id
+	// that also meet the key usage given by requiredUsage.
+	// The requiredUsage is expressed as the bitwise-OR of
+	// packet.KeyFlag* values.
+	KeysByIdUsage(id uint64, requiredUsage byte) []Key
+	// DecryptionKeys returns all private keys that are valid for
+	// decryption.
+	DecryptionKeys() []Key
+}
+
+// primaryIdentity returns the Identity marked as primary or the first identity
+// if none are so marked.
+func (e *Entity) primaryIdentity() *Identity {
+	var firstIdentity *Identity
+	for _, ident := range e.Identities {
+		if firstIdentity == nil {
+			firstIdentity = ident
+		}
+		if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId {
+			return ident
+		}
+	}
+	return firstIdentity
+}
+
+// encryptionKey returns the best candidate Key for encrypting a message to the
+// given Entity.
+func (e *Entity) encryptionKey(now time.Time) (Key, bool) {
+	candidateSubkey := -1
+
+	// Iterate the keys to find the newest key
+	var maxTime time.Time
+	for i, subkey := range e.Subkeys {
+		if subkey.Sig.FlagsValid &&
+			subkey.Sig.FlagEncryptCommunications &&
+			subkey.PublicKey.PubKeyAlgo.CanEncrypt() &&
+			!subkey.Sig.KeyExpired(now) &&
+			(maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) {
+			candidateSubkey = i
+			maxTime = subkey.Sig.CreationTime
+		}
+	}
+
+	if candidateSubkey != -1 {
+		subkey := e.Subkeys[candidateSubkey]
+		return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, true
+	}
+
+	// If we don't have any candidate subkeys for encryption and
+	// the primary key doesn't have any usage metadata then we
+	// assume that the primary key is ok. Or, if the primary key is
+	// marked as ok to encrypt to, then we can obviously use it.
+	i := e.primaryIdentity()
+	if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagEncryptCommunications &&
+		e.PrimaryKey.PubKeyAlgo.CanEncrypt() &&
+		!i.SelfSignature.KeyExpired(now) {
+		return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true
+	}
+
+	// This Entity appears to be signing only.
+	return Key{}, false
+}
+
+// signingKey return the best candidate Key for signing a message with this
+// Entity.
+func (e *Entity) signingKey(now time.Time) (Key, bool) {
+	candidateSubkey := -1
+
+	for i, subkey := range e.Subkeys {
+		if subkey.Sig.FlagsValid &&
+			subkey.Sig.FlagSign &&
+			subkey.PublicKey.PubKeyAlgo.CanSign() &&
+			!subkey.Sig.KeyExpired(now) {
+			candidateSubkey = i
+			break
+		}
+	}
+
+	if candidateSubkey != -1 {
+		subkey := e.Subkeys[candidateSubkey]
+		return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, true
+	}
+
+	// If we have no candidate subkey then we assume that it's ok to sign
+	// with the primary key.
+	i := e.primaryIdentity()
+	if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagSign &&
+		!i.SelfSignature.KeyExpired(now) {
+		return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true
+	}
+
+	return Key{}, false
+}
+
+// An EntityList contains one or more Entities.
+type EntityList []*Entity
+
+// KeysById returns the set of keys that have the given key id.
+func (el EntityList) KeysById(id uint64) (keys []Key) {
+	for _, e := range el {
+		if e.PrimaryKey.KeyId == id {
+			var selfSig *packet.Signature
+			for _, ident := range e.Identities {
+				if selfSig == nil {
+					selfSig = ident.SelfSignature
+				} else if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId {
+					selfSig = ident.SelfSignature
+					break
+				}
+			}
+			keys = append(keys, Key{e, e.PrimaryKey, e.PrivateKey, selfSig})
+		}
+
+		for _, subKey := range e.Subkeys {
+			if subKey.PublicKey.KeyId == id {
+				keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig})
+			}
+		}
+	}
+	return
+}
+
+// KeysByIdAndUsage returns the set of keys with the given id that also meet
+// the key usage given by requiredUsage.  The requiredUsage is expressed as
+// the bitwise-OR of packet.KeyFlag* values.
+func (el EntityList) KeysByIdUsage(id uint64, requiredUsage byte) (keys []Key) {
+	for _, key := range el.KeysById(id) {
+		if len(key.Entity.Revocations) > 0 {
+			continue
+		}
+
+		if key.SelfSignature.RevocationReason != nil {
+			continue
+		}
+
+		if key.SelfSignature.FlagsValid && requiredUsage != 0 {
+			var usage byte
+			if key.SelfSignature.FlagCertify {
+				usage |= packet.KeyFlagCertify
+			}
+			if key.SelfSignature.FlagSign {
+				usage |= packet.KeyFlagSign
+			}
+			if key.SelfSignature.FlagEncryptCommunications {
+				usage |= packet.KeyFlagEncryptCommunications
+			}
+			if key.SelfSignature.FlagEncryptStorage {
+				usage |= packet.KeyFlagEncryptStorage
+			}
+			if usage&requiredUsage != requiredUsage {
+				continue
+			}
+		}
+
+		keys = append(keys, key)
+	}
+	return
+}
+
+// DecryptionKeys returns all private keys that are valid for decryption.
+func (el EntityList) DecryptionKeys() (keys []Key) {
+	for _, e := range el {
+		for _, subKey := range e.Subkeys {
+			if subKey.PrivateKey != nil && (!subKey.Sig.FlagsValid || subKey.Sig.FlagEncryptStorage || subKey.Sig.FlagEncryptCommunications) {
+				keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig})
+			}
+		}
+	}
+	return
+}
+
+// ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file.
+func ReadArmoredKeyRing(r io.Reader) (EntityList, error) {
+	block, err := armor.Decode(r)
+	if err == io.EOF {
+		return nil, errors.InvalidArgumentError("no armored data found")
+	}
+	if err != nil {
+		return nil, err
+	}
+	if block.Type != PublicKeyType && block.Type != PrivateKeyType {
+		return nil, errors.InvalidArgumentError("expected public or private key block, got: " + block.Type)
+	}
+
+	return ReadKeyRing(block.Body)
+}
+
+// ReadKeyRing reads one or more public/private keys. Unsupported keys are
+// ignored as long as at least a single valid key is found.
+func ReadKeyRing(r io.Reader) (el EntityList, err error) {
+	packets := packet.NewReader(r)
+	var lastUnsupportedError error
+
+	for {
+		var e *Entity
+		e, err = ReadEntity(packets)
+		if err != nil {
+			// TODO: warn about skipped unsupported/unreadable keys
+			if _, ok := err.(errors.UnsupportedError); ok {
+				lastUnsupportedError = err
+				err = readToNextPublicKey(packets)
+			} else if _, ok := err.(errors.StructuralError); ok {
+				// Skip unreadable, badly-formatted keys
+				lastUnsupportedError = err
+				err = readToNextPublicKey(packets)
+			}
+			if err == io.EOF {
+				err = nil
+				break
+			}
+			if err != nil {
+				el = nil
+				break
+			}
+		} else {
+			el = append(el, e)
+		}
+	}
+
+	if len(el) == 0 && err == nil {
+		err = lastUnsupportedError
+	}
+	return
+}
+
+// readToNextPublicKey reads packets until the start of the entity and leaves
+// the first packet of the new entity in the Reader.
+func readToNextPublicKey(packets *packet.Reader) (err error) {
+	var p packet.Packet
+	for {
+		p, err = packets.Next()
+		if err == io.EOF {
+			return
+		} else if err != nil {
+			if _, ok := err.(errors.UnsupportedError); ok {
+				err = nil
+				continue
+			}
+			return
+		}
+
+		if pk, ok := p.(*packet.PublicKey); ok && !pk.IsSubkey {
+			packets.Unread(p)
+			return
+		}
+	}
+
+	panic("unreachable")
+}
+
+// ReadEntity reads an entity (public key, identities, subkeys etc) from the
+// given Reader.
+func ReadEntity(packets *packet.Reader) (*Entity, error) {
+	e := new(Entity)
+	e.Identities = make(map[string]*Identity)
+
+	p, err := packets.Next()
+	if err != nil {
+		return nil, err
+	}
+
+	var ok bool
+	if e.PrimaryKey, ok = p.(*packet.PublicKey); !ok {
+		if e.PrivateKey, ok = p.(*packet.PrivateKey); !ok {
+			packets.Unread(p)
+			return nil, errors.StructuralError("first packet was not a public/private key")
+		} else {
+			e.PrimaryKey = &e.PrivateKey.PublicKey
+		}
+	}
+
+	if !e.PrimaryKey.PubKeyAlgo.CanSign() {
+		return nil, errors.StructuralError("primary key cannot be used for signatures")
+	}
+
+	var current *Identity
+	var revocations []*packet.Signature
+EachPacket:
+	for {
+		p, err := packets.Next()
+		if err == io.EOF {
+			break
+		} else if err != nil {
+			return nil, err
+		}
+
+		switch pkt := p.(type) {
+		case *packet.UserId:
+			current = new(Identity)
+			current.Name = pkt.Id
+			current.UserId = pkt
+			e.Identities[pkt.Id] = current
+
+			for {
+				p, err = packets.Next()
+				if err == io.EOF {
+					return nil, io.ErrUnexpectedEOF
+				} else if err != nil {
+					return nil, err
+				}
+
+				sig, ok := p.(*packet.Signature)
+				if !ok {
+					return nil, errors.StructuralError("user ID packet not followed by self-signature")
+				}
+
+				if (sig.SigType == packet.SigTypePositiveCert || sig.SigType == packet.SigTypeGenericCert) && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId {
+					if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, e.PrimaryKey, sig); err != nil {
+						return nil, errors.StructuralError("user ID self-signature invalid: " + err.Error())
+					}
+					current.SelfSignature = sig
+					break
+				}
+				current.Signatures = append(current.Signatures, sig)
+			}
+		case *packet.Signature:
+			if pkt.SigType == packet.SigTypeKeyRevocation {
+				revocations = append(revocations, pkt)
+			} else if pkt.SigType == packet.SigTypeDirectSignature {
+				// TODO: RFC4880 5.2.1 permits signatures
+				// directly on keys (eg. to bind additional
+				// revocation keys).
+			} else if current == nil {
+				return nil, errors.StructuralError("signature packet found before user id packet")
+			} else {
+				current.Signatures = append(current.Signatures, pkt)
+			}
+		case *packet.PrivateKey:
+			if pkt.IsSubkey == false {
+				packets.Unread(p)
+				break EachPacket
+			}
+			err = addSubkey(e, packets, &pkt.PublicKey, pkt)
+			if err != nil {
+				return nil, err
+			}
+		case *packet.PublicKey:
+			if pkt.IsSubkey == false {
+				packets.Unread(p)
+				break EachPacket
+			}
+			err = addSubkey(e, packets, pkt, nil)
+			if err != nil {
+				return nil, err
+			}
+		default:
+			// we ignore unknown packets
+		}
+	}
+
+	if len(e.Identities) == 0 {
+		return nil, errors.StructuralError("entity without any identities")
+	}
+
+	for _, revocation := range revocations {
+		err = e.PrimaryKey.VerifyRevocationSignature(revocation)
+		if err == nil {
+			e.Revocations = append(e.Revocations, revocation)
+		} else {
+			// TODO: RFC 4880 5.2.3.15 defines revocation keys.
+			return nil, errors.StructuralError("revocation signature signed by alternate key")
+		}
+	}
+
+	return e, nil
+}
+
+func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *packet.PrivateKey) error {
+	var subKey Subkey
+	subKey.PublicKey = pub
+	subKey.PrivateKey = priv
+	p, err := packets.Next()
+	if err == io.EOF {
+		return io.ErrUnexpectedEOF
+	}
+	if err != nil {
+		return errors.StructuralError("subkey signature invalid: " + err.Error())
+	}
+	var ok bool
+	subKey.Sig, ok = p.(*packet.Signature)
+	if !ok {
+		return errors.StructuralError("subkey packet not followed by signature")
+	}
+	if subKey.Sig.SigType != packet.SigTypeSubkeyBinding && subKey.Sig.SigType != packet.SigTypeSubkeyRevocation {
+		return errors.StructuralError("subkey signature with wrong type")
+	}
+	err = e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, subKey.Sig)
+	if err != nil {
+		return errors.StructuralError("subkey signature invalid: " + err.Error())
+	}
+	e.Subkeys = append(e.Subkeys, subKey)
+	return nil
+}
+
+const defaultRSAKeyBits = 2048
+
+// NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a
+// single identity composed of the given full name, comment and email, any of
+// which may be empty but must not contain any of "()<>\x00".
+// If config is nil, sensible defaults will be used.
+func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) {
+	currentTime := config.Now()
+
+	bits := defaultRSAKeyBits
+	if config != nil && config.RSABits != 0 {
+		bits = config.RSABits
+	}
+
+	uid := packet.NewUserId(name, comment, email)
+	if uid == nil {
+		return nil, errors.InvalidArgumentError("user id field contained invalid characters")
+	}
+	signingPriv, err := rsa.GenerateKey(config.Random(), bits)
+	if err != nil {
+		return nil, err
+	}
+	encryptingPriv, err := rsa.GenerateKey(config.Random(), bits)
+	if err != nil {
+		return nil, err
+	}
+
+	e := &Entity{
+		PrimaryKey: packet.NewRSAPublicKey(currentTime, &signingPriv.PublicKey),
+		PrivateKey: packet.NewRSAPrivateKey(currentTime, signingPriv),
+		Identities: make(map[string]*Identity),
+	}
+	isPrimaryId := true
+	e.Identities[uid.Id] = &Identity{
+		Name:   uid.Name,
+		UserId: uid,
+		SelfSignature: &packet.Signature{
+			CreationTime: currentTime,
+			SigType:      packet.SigTypePositiveCert,
+			PubKeyAlgo:   packet.PubKeyAlgoRSA,
+			Hash:         config.Hash(),
+			IsPrimaryId:  &isPrimaryId,
+			FlagsValid:   true,
+			FlagSign:     true,
+			FlagCertify:  true,
+			IssuerKeyId:  &e.PrimaryKey.KeyId,
+		},
+	}
+
+	e.Subkeys = make([]Subkey, 1)
+	e.Subkeys[0] = Subkey{
+		PublicKey:  packet.NewRSAPublicKey(currentTime, &encryptingPriv.PublicKey),
+		PrivateKey: packet.NewRSAPrivateKey(currentTime, encryptingPriv),
+		Sig: &packet.Signature{
+			CreationTime:              currentTime,
+			SigType:                   packet.SigTypeSubkeyBinding,
+			PubKeyAlgo:                packet.PubKeyAlgoRSA,
+			Hash:                      config.Hash(),
+			FlagsValid:                true,
+			FlagEncryptStorage:        true,
+			FlagEncryptCommunications: true,
+			IssuerKeyId:               &e.PrimaryKey.KeyId,
+		},
+	}
+	e.Subkeys[0].PublicKey.IsSubkey = true
+	e.Subkeys[0].PrivateKey.IsSubkey = true
+
+	return e, nil
+}
+
+// SerializePrivate serializes an Entity, including private key material, to
+// the given Writer. For now, it must only be used on an Entity returned from
+// NewEntity.
+// If config is nil, sensible defaults will be used.
+func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error) {
+	err = e.PrivateKey.Serialize(w)
+	if err != nil {
+		return
+	}
+	for _, ident := range e.Identities {
+		err = ident.UserId.Serialize(w)
+		if err != nil {
+			return
+		}
+		err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey, config)
+		if err != nil {
+			return
+		}
+		err = ident.SelfSignature.Serialize(w)
+		if err != nil {
+			return
+		}
+	}
+	for _, subkey := range e.Subkeys {
+		err = subkey.PrivateKey.Serialize(w)
+		if err != nil {
+			return
+		}
+		err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config)
+		if err != nil {
+			return
+		}
+		err = subkey.Sig.Serialize(w)
+		if err != nil {
+			return
+		}
+	}
+	return nil
+}
+
+// Serialize writes the public part of the given Entity to w. (No private
+// key material will be output).
+func (e *Entity) Serialize(w io.Writer) error {
+	err := e.PrimaryKey.Serialize(w)
+	if err != nil {
+		return err
+	}
+	for _, ident := range e.Identities {
+		err = ident.UserId.Serialize(w)
+		if err != nil {
+			return err
+		}
+		err = ident.SelfSignature.Serialize(w)
+		if err != nil {
+			return err
+		}
+		for _, sig := range ident.Signatures {
+			err = sig.Serialize(w)
+			if err != nil {
+				return err
+			}
+		}
+	}
+	for _, subkey := range e.Subkeys {
+		err = subkey.PublicKey.Serialize(w)
+		if err != nil {
+			return err
+		}
+		err = subkey.Sig.Serialize(w)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// SignIdentity adds a signature to e, from signer, attesting that identity is
+// associated with e. The provided identity must already be an element of
+// e.Identities and the private key of signer must have been decrypted if
+// necessary.
+// If config is nil, sensible defaults will be used.
+func (e *Entity) SignIdentity(identity string, signer *Entity, config *packet.Config) error {
+	if signer.PrivateKey == nil {
+		return errors.InvalidArgumentError("signing Entity must have a private key")
+	}
+	if signer.PrivateKey.Encrypted {
+		return errors.InvalidArgumentError("signing Entity's private key must be decrypted")
+	}
+	ident, ok := e.Identities[identity]
+	if !ok {
+		return errors.InvalidArgumentError("given identity string not found in Entity")
+	}
+
+	sig := &packet.Signature{
+		SigType:      packet.SigTypeGenericCert,
+		PubKeyAlgo:   signer.PrivateKey.PubKeyAlgo,
+		Hash:         config.Hash(),
+		CreationTime: config.Now(),
+		IssuerKeyId:  &signer.PrivateKey.KeyId,
+	}
+	if err := sig.SignUserId(identity, e.PrimaryKey, signer.PrivateKey, config); err != nil {
+		return err
+	}
+	ident.Signatures = append(ident.Signatures, sig)
+	return nil
+}

文件差异内容过多而无法显示
+ 274 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/keys_test.go


+ 123 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/compressed.go

@@ -0,0 +1,123 @@
+// Copyright 2011 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 packet
+
+import (
+	"compress/bzip2"
+	"compress/flate"
+	"compress/zlib"
+	"golang.org/x/crypto/openpgp/errors"
+	"io"
+	"strconv"
+)
+
+// Compressed represents a compressed OpenPGP packet. The decompressed contents
+// will contain more OpenPGP packets. See RFC 4880, section 5.6.
+type Compressed struct {
+	Body io.Reader
+}
+
+const (
+	NoCompression      = flate.NoCompression
+	BestSpeed          = flate.BestSpeed
+	BestCompression    = flate.BestCompression
+	DefaultCompression = flate.DefaultCompression
+)
+
+// CompressionConfig contains compressor configuration settings.
+type CompressionConfig struct {
+	// Level is the compression level to use. It must be set to
+	// between -1 and 9, with -1 causing the compressor to use the
+	// default compression level, 0 causing the compressor to use
+	// no compression and 1 to 9 representing increasing (better,
+	// slower) compression levels. If Level is less than -1 or
+	// more then 9, a non-nil error will be returned during
+	// encryption. See the constants above for convenient common
+	// settings for Level.
+	Level int
+}
+
+func (c *Compressed) parse(r io.Reader) error {
+	var buf [1]byte
+	_, err := readFull(r, buf[:])
+	if err != nil {
+		return err
+	}
+
+	switch buf[0] {
+	case 1:
+		c.Body = flate.NewReader(r)
+	case 2:
+		c.Body, err = zlib.NewReader(r)
+	case 3:
+		c.Body = bzip2.NewReader(r)
+	default:
+		err = errors.UnsupportedError("unknown compression algorithm: " + strconv.Itoa(int(buf[0])))
+	}
+
+	return err
+}
+
+// compressedWriterCloser represents the serialized compression stream
+// header and the compressor. Its Close() method ensures that both the
+// compressor and serialized stream header are closed. Its Write()
+// method writes to the compressor.
+type compressedWriteCloser struct {
+	sh io.Closer      // Stream Header
+	c  io.WriteCloser // Compressor
+}
+
+func (cwc compressedWriteCloser) Write(p []byte) (int, error) {
+	return cwc.c.Write(p)
+}
+
+func (cwc compressedWriteCloser) Close() (err error) {
+	err = cwc.c.Close()
+	if err != nil {
+		return err
+	}
+
+	return cwc.sh.Close()
+}
+
+// SerializeCompressed serializes a compressed data packet to w and
+// returns a WriteCloser to which the literal data packets themselves
+// can be written and which MUST be closed on completion. If cc is
+// nil, sensible defaults will be used to configure the compression
+// algorithm.
+func SerializeCompressed(w io.WriteCloser, algo CompressionAlgo, cc *CompressionConfig) (literaldata io.WriteCloser, err error) {
+	compressed, err := serializeStreamHeader(w, packetTypeCompressed)
+	if err != nil {
+		return
+	}
+
+	_, err = compressed.Write([]byte{uint8(algo)})
+	if err != nil {
+		return
+	}
+
+	level := DefaultCompression
+	if cc != nil {
+		level = cc.Level
+	}
+
+	var compressor io.WriteCloser
+	switch algo {
+	case CompressionZIP:
+		compressor, err = flate.NewWriter(compressed, level)
+	case CompressionZLIB:
+		compressor, err = zlib.NewWriterLevel(compressed, level)
+	default:
+		s := strconv.Itoa(int(algo))
+		err = errors.UnsupportedError("Unsupported compression algorithm: " + s)
+	}
+	if err != nil {
+		return
+	}
+
+	literaldata = compressedWriteCloser{compressed, compressor}
+
+	return
+}

+ 41 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/compressed_test.go

@@ -0,0 +1,41 @@
+// Copyright 2011 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 packet
+
+import (
+	"bytes"
+	"encoding/hex"
+	"io"
+	"io/ioutil"
+	"testing"
+)
+
+func TestCompressed(t *testing.T) {
+	packet, err := Read(readerFromHex(compressedHex))
+	if err != nil {
+		t.Errorf("failed to read Compressed: %s", err)
+		return
+	}
+
+	c, ok := packet.(*Compressed)
+	if !ok {
+		t.Error("didn't find Compressed packet")
+		return
+	}
+
+	contents, err := ioutil.ReadAll(c.Body)
+	if err != nil && err != io.EOF {
+		t.Error(err)
+		return
+	}
+
+	expected, _ := hex.DecodeString(compressedExpectedHex)
+	if !bytes.Equal(expected, contents) {
+		t.Errorf("got:%x want:%x", contents, expected)
+	}
+}
+
+const compressedHex = "a3013b2d90c4e02b72e25f727e5e496a5e49b11e1700"
+const compressedExpectedHex = "cb1062004d14c8fe636f6e74656e74732e0a"

+ 91 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/config.go

@@ -0,0 +1,91 @@
+// Copyright 2012 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 packet
+
+import (
+	"crypto"
+	"crypto/rand"
+	"io"
+	"time"
+)
+
+// Config collects a number of parameters along with sensible defaults.
+// A nil *Config is valid and results in all default values.
+type Config struct {
+	// Rand provides the source of entropy.
+	// If nil, the crypto/rand Reader is used.
+	Rand io.Reader
+	// DefaultHash is the default hash function to be used.
+	// If zero, SHA-256 is used.
+	DefaultHash crypto.Hash
+	// DefaultCipher is the cipher to be used.
+	// If zero, AES-128 is used.
+	DefaultCipher CipherFunction
+	// Time returns the current time as the number of seconds since the
+	// epoch. If Time is nil, time.Now is used.
+	Time func() time.Time
+	// DefaultCompressionAlgo is the compression algorithm to be
+	// applied to the plaintext before encryption. If zero, no
+	// compression is done.
+	DefaultCompressionAlgo CompressionAlgo
+	// CompressionConfig configures the compression settings.
+	CompressionConfig *CompressionConfig
+	// S2KCount is only used for symmetric encryption. It
+	// determines the strength of the passphrase stretching when
+	// the said passphrase is hashed to produce a key. S2KCount
+	// should be between 1024 and 65011712, inclusive. If Config
+	// is nil or S2KCount is 0, the value 65536 used. Not all
+	// values in the above range can be represented. S2KCount will
+	// be rounded up to the next representable value if it cannot
+	// be encoded exactly. When set, it is strongly encrouraged to
+	// use a value that is at least 65536. See RFC 4880 Section
+	// 3.7.1.3.
+	S2KCount int
+	// RSABits is the number of bits in new RSA keys made with NewEntity.
+	// If zero, then 2048 bit keys are created.
+	RSABits int
+}
+
+func (c *Config) Random() io.Reader {
+	if c == nil || c.Rand == nil {
+		return rand.Reader
+	}
+	return c.Rand
+}
+
+func (c *Config) Hash() crypto.Hash {
+	if c == nil || uint(c.DefaultHash) == 0 {
+		return crypto.SHA256
+	}
+	return c.DefaultHash
+}
+
+func (c *Config) Cipher() CipherFunction {
+	if c == nil || uint8(c.DefaultCipher) == 0 {
+		return CipherAES128
+	}
+	return c.DefaultCipher
+}
+
+func (c *Config) Now() time.Time {
+	if c == nil || c.Time == nil {
+		return time.Now()
+	}
+	return c.Time()
+}
+
+func (c *Config) Compression() CompressionAlgo {
+	if c == nil {
+		return CompressionNone
+	}
+	return c.DefaultCompressionAlgo
+}
+
+func (c *Config) PasswordHashIterations() int {
+	if c == nil || c.S2KCount == 0 {
+		return 0
+	}
+	return c.S2KCount
+}

+ 199 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/encrypted_key.go

@@ -0,0 +1,199 @@
+// Copyright 2011 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 packet
+
+import (
+	"crypto/rsa"
+	"encoding/binary"
+	"io"
+	"math/big"
+	"strconv"
+
+	"golang.org/x/crypto/openpgp/elgamal"
+	"golang.org/x/crypto/openpgp/errors"
+)
+
+const encryptedKeyVersion = 3
+
+// EncryptedKey represents a public-key encrypted session key. See RFC 4880,
+// section 5.1.
+type EncryptedKey struct {
+	KeyId      uint64
+	Algo       PublicKeyAlgorithm
+	CipherFunc CipherFunction // only valid after a successful Decrypt
+	Key        []byte         // only valid after a successful Decrypt
+
+	encryptedMPI1, encryptedMPI2 parsedMPI
+}
+
+func (e *EncryptedKey) parse(r io.Reader) (err error) {
+	var buf [10]byte
+	_, err = readFull(r, buf[:])
+	if err != nil {
+		return
+	}
+	if buf[0] != encryptedKeyVersion {
+		return errors.UnsupportedError("unknown EncryptedKey version " + strconv.Itoa(int(buf[0])))
+	}
+	e.KeyId = binary.BigEndian.Uint64(buf[1:9])
+	e.Algo = PublicKeyAlgorithm(buf[9])
+	switch e.Algo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
+		e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r)
+	case PubKeyAlgoElGamal:
+		e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r)
+		if err != nil {
+			return
+		}
+		e.encryptedMPI2.bytes, e.encryptedMPI2.bitLength, err = readMPI(r)
+	}
+	_, err = consumeAll(r)
+	return
+}
+
+func checksumKeyMaterial(key []byte) uint16 {
+	var checksum uint16
+	for _, v := range key {
+		checksum += uint16(v)
+	}
+	return checksum
+}
+
+// Decrypt decrypts an encrypted session key with the given private key. The
+// private key must have been decrypted first.
+// If config is nil, sensible defaults will be used.
+func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error {
+	var err error
+	var b []byte
+
+	// TODO(agl): use session key decryption routines here to avoid
+	// padding oracle attacks.
+	switch priv.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
+		b, err = rsa.DecryptPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), e.encryptedMPI1.bytes)
+	case PubKeyAlgoElGamal:
+		c1 := new(big.Int).SetBytes(e.encryptedMPI1.bytes)
+		c2 := new(big.Int).SetBytes(e.encryptedMPI2.bytes)
+		b, err = elgamal.Decrypt(priv.PrivateKey.(*elgamal.PrivateKey), c1, c2)
+	default:
+		err = errors.InvalidArgumentError("cannot decrypted encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo)))
+	}
+
+	if err != nil {
+		return err
+	}
+
+	e.CipherFunc = CipherFunction(b[0])
+	e.Key = b[1 : len(b)-2]
+	expectedChecksum := uint16(b[len(b)-2])<<8 | uint16(b[len(b)-1])
+	checksum := checksumKeyMaterial(e.Key)
+	if checksum != expectedChecksum {
+		return errors.StructuralError("EncryptedKey checksum incorrect")
+	}
+
+	return nil
+}
+
+// Serialize writes the encrypted key packet, e, to w.
+func (e *EncryptedKey) Serialize(w io.Writer) error {
+	var mpiLen int
+	switch e.Algo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
+		mpiLen = 2 + len(e.encryptedMPI1.bytes)
+	case PubKeyAlgoElGamal:
+		mpiLen = 2 + len(e.encryptedMPI1.bytes) + 2 + len(e.encryptedMPI2.bytes)
+	default:
+		return errors.InvalidArgumentError("don't know how to serialize encrypted key type " + strconv.Itoa(int(e.Algo)))
+	}
+
+	serializeHeader(w, packetTypeEncryptedKey, 1 /* version */ +8 /* key id */ +1 /* algo */ +mpiLen)
+
+	w.Write([]byte{encryptedKeyVersion})
+	binary.Write(w, binary.BigEndian, e.KeyId)
+	w.Write([]byte{byte(e.Algo)})
+
+	switch e.Algo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
+		writeMPIs(w, e.encryptedMPI1)
+	case PubKeyAlgoElGamal:
+		writeMPIs(w, e.encryptedMPI1, e.encryptedMPI2)
+	default:
+		panic("internal error")
+	}
+
+	return nil
+}
+
+// SerializeEncryptedKey serializes an encrypted key packet to w that contains
+// key, encrypted to pub.
+// If config is nil, sensible defaults will be used.
+func SerializeEncryptedKey(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, key []byte, config *Config) error {
+	var buf [10]byte
+	buf[0] = encryptedKeyVersion
+	binary.BigEndian.PutUint64(buf[1:9], pub.KeyId)
+	buf[9] = byte(pub.PubKeyAlgo)
+
+	keyBlock := make([]byte, 1 /* cipher type */ +len(key)+2 /* checksum */)
+	keyBlock[0] = byte(cipherFunc)
+	copy(keyBlock[1:], key)
+	checksum := checksumKeyMaterial(key)
+	keyBlock[1+len(key)] = byte(checksum >> 8)
+	keyBlock[1+len(key)+1] = byte(checksum)
+
+	switch pub.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
+		return serializeEncryptedKeyRSA(w, config.Random(), buf, pub.PublicKey.(*rsa.PublicKey), keyBlock)
+	case PubKeyAlgoElGamal:
+		return serializeEncryptedKeyElGamal(w, config.Random(), buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock)
+	case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly:
+		return errors.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
+	}
+
+	return errors.UnsupportedError("encrypting a key to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
+}
+
+func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub *rsa.PublicKey, keyBlock []byte) error {
+	cipherText, err := rsa.EncryptPKCS1v15(rand, pub, keyBlock)
+	if err != nil {
+		return errors.InvalidArgumentError("RSA encryption failed: " + err.Error())
+	}
+
+	packetLen := 10 /* header length */ + 2 /* mpi size */ + len(cipherText)
+
+	err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
+	if err != nil {
+		return err
+	}
+	_, err = w.Write(header[:])
+	if err != nil {
+		return err
+	}
+	return writeMPI(w, 8*uint16(len(cipherText)), cipherText)
+}
+
+func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte, pub *elgamal.PublicKey, keyBlock []byte) error {
+	c1, c2, err := elgamal.Encrypt(rand, pub, keyBlock)
+	if err != nil {
+		return errors.InvalidArgumentError("ElGamal encryption failed: " + err.Error())
+	}
+
+	packetLen := 10 /* header length */
+	packetLen += 2 /* mpi size */ + (c1.BitLen()+7)/8
+	packetLen += 2 /* mpi size */ + (c2.BitLen()+7)/8
+
+	err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
+	if err != nil {
+		return err
+	}
+	_, err = w.Write(header[:])
+	if err != nil {
+		return err
+	}
+	err = writeBig(w, c1)
+	if err != nil {
+		return err
+	}
+	return writeBig(w, c2)
+}

+ 146 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go

@@ -0,0 +1,146 @@
+// Copyright 2011 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 packet
+
+import (
+	"bytes"
+	"crypto/rsa"
+	"encoding/hex"
+	"fmt"
+	"math/big"
+	"testing"
+)
+
+func bigFromBase10(s string) *big.Int {
+	b, ok := new(big.Int).SetString(s, 10)
+	if !ok {
+		panic("bigFromBase10 failed")
+	}
+	return b
+}
+
+var encryptedKeyPub = rsa.PublicKey{
+	E: 65537,
+	N: bigFromBase10("115804063926007623305902631768113868327816898845124614648849934718568541074358183759250136204762053879858102352159854352727097033322663029387610959884180306668628526686121021235757016368038585212410610742029286439607686208110250133174279811431933746643015923132833417396844716207301518956640020862630546868823"),
+}
+
+var encryptedKeyRSAPriv = &rsa.PrivateKey{
+	PublicKey: encryptedKeyPub,
+	D:         bigFromBase10("32355588668219869544751561565313228297765464314098552250409557267371233892496951383426602439009993875125222579159850054973310859166139474359774543943714622292329487391199285040721944491839695981199720170366763547754915493640685849961780092241140181198779299712578774460837139360803883139311171713302987058393"),
+}
+
+var encryptedKeyPriv = &PrivateKey{
+	PublicKey: PublicKey{
+		PubKeyAlgo: PubKeyAlgoRSA,
+	},
+	PrivateKey: encryptedKeyRSAPriv,
+}
+
+func TestDecryptingEncryptedKey(t *testing.T) {
+	const encryptedKeyHex = "c18c032a67d68660df41c70104005789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8"
+	const expectedKeyHex = "d930363f7e0308c333b9618617ea728963d8df993665ae7be1092d4926fd864b"
+
+	p, err := Read(readerFromHex(encryptedKeyHex))
+	if err != nil {
+		t.Errorf("error from Read: %s", err)
+		return
+	}
+	ek, ok := p.(*EncryptedKey)
+	if !ok {
+		t.Errorf("didn't parse an EncryptedKey, got %#v", p)
+		return
+	}
+
+	if ek.KeyId != 0x2a67d68660df41c7 || ek.Algo != PubKeyAlgoRSA {
+		t.Errorf("unexpected EncryptedKey contents: %#v", ek)
+		return
+	}
+
+	err = ek.Decrypt(encryptedKeyPriv, nil)
+	if err != nil {
+		t.Errorf("error from Decrypt: %s", err)
+		return
+	}
+
+	if ek.CipherFunc != CipherAES256 {
+		t.Errorf("unexpected EncryptedKey contents: %#v", ek)
+		return
+	}
+
+	keyHex := fmt.Sprintf("%x", ek.Key)
+	if keyHex != expectedKeyHex {
+		t.Errorf("bad key, got %s want %x", keyHex, expectedKeyHex)
+	}
+}
+
+func TestEncryptingEncryptedKey(t *testing.T) {
+	key := []byte{1, 2, 3, 4}
+	const expectedKeyHex = "01020304"
+	const keyId = 42
+
+	pub := &PublicKey{
+		PublicKey:  &encryptedKeyPub,
+		KeyId:      keyId,
+		PubKeyAlgo: PubKeyAlgoRSAEncryptOnly,
+	}
+
+	buf := new(bytes.Buffer)
+	err := SerializeEncryptedKey(buf, pub, CipherAES128, key, nil)
+	if err != nil {
+		t.Errorf("error writing encrypted key packet: %s", err)
+	}
+
+	p, err := Read(buf)
+	if err != nil {
+		t.Errorf("error from Read: %s", err)
+		return
+	}
+	ek, ok := p.(*EncryptedKey)
+	if !ok {
+		t.Errorf("didn't parse an EncryptedKey, got %#v", p)
+		return
+	}
+
+	if ek.KeyId != keyId || ek.Algo != PubKeyAlgoRSAEncryptOnly {
+		t.Errorf("unexpected EncryptedKey contents: %#v", ek)
+		return
+	}
+
+	err = ek.Decrypt(encryptedKeyPriv, nil)
+	if err != nil {
+		t.Errorf("error from Decrypt: %s", err)
+		return
+	}
+
+	if ek.CipherFunc != CipherAES128 {
+		t.Errorf("unexpected EncryptedKey contents: %#v", ek)
+		return
+	}
+
+	keyHex := fmt.Sprintf("%x", ek.Key)
+	if keyHex != expectedKeyHex {
+		t.Errorf("bad key, got %s want %x", keyHex, expectedKeyHex)
+	}
+}
+
+func TestSerializingEncryptedKey(t *testing.T) {
+	const encryptedKeyHex = "c18c032a67d68660df41c70104005789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8"
+
+	p, err := Read(readerFromHex(encryptedKeyHex))
+	if err != nil {
+		t.Fatalf("error from Read: %s", err)
+	}
+	ek, ok := p.(*EncryptedKey)
+	if !ok {
+		t.Fatalf("didn't parse an EncryptedKey, got %#v", p)
+	}
+
+	var buf bytes.Buffer
+	ek.Serialize(&buf)
+
+	if bufHex := hex.EncodeToString(buf.Bytes()); bufHex != encryptedKeyHex {
+		t.Fatalf("serialization of encrypted key differed from original. Original was %s, but reserialized as %s", encryptedKeyHex, bufHex)
+	}
+}

+ 89 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/literal.go

@@ -0,0 +1,89 @@
+// Copyright 2011 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 packet
+
+import (
+	"encoding/binary"
+	"io"
+)
+
+// LiteralData represents an encrypted file. See RFC 4880, section 5.9.
+type LiteralData struct {
+	IsBinary bool
+	FileName string
+	Time     uint32 // Unix epoch time. Either creation time or modification time. 0 means undefined.
+	Body     io.Reader
+}
+
+// ForEyesOnly returns whether the contents of the LiteralData have been marked
+// as especially sensitive.
+func (l *LiteralData) ForEyesOnly() bool {
+	return l.FileName == "_CONSOLE"
+}
+
+func (l *LiteralData) parse(r io.Reader) (err error) {
+	var buf [256]byte
+
+	_, err = readFull(r, buf[:2])
+	if err != nil {
+		return
+	}
+
+	l.IsBinary = buf[0] == 'b'
+	fileNameLen := int(buf[1])
+
+	_, err = readFull(r, buf[:fileNameLen])
+	if err != nil {
+		return
+	}
+
+	l.FileName = string(buf[:fileNameLen])
+
+	_, err = readFull(r, buf[:4])
+	if err != nil {
+		return
+	}
+
+	l.Time = binary.BigEndian.Uint32(buf[:4])
+	l.Body = r
+	return
+}
+
+// SerializeLiteral serializes a literal data packet to w and returns a
+// WriteCloser to which the data itself can be written and which MUST be closed
+// on completion. The fileName is truncated to 255 bytes.
+func SerializeLiteral(w io.WriteCloser, isBinary bool, fileName string, time uint32) (plaintext io.WriteCloser, err error) {
+	var buf [4]byte
+	buf[0] = 't'
+	if isBinary {
+		buf[0] = 'b'
+	}
+	if len(fileName) > 255 {
+		fileName = fileName[:255]
+	}
+	buf[1] = byte(len(fileName))
+
+	inner, err := serializeStreamHeader(w, packetTypeLiteralData)
+	if err != nil {
+		return
+	}
+
+	_, err = inner.Write(buf[:2])
+	if err != nil {
+		return
+	}
+	_, err = inner.Write([]byte(fileName))
+	if err != nil {
+		return
+	}
+	binary.BigEndian.PutUint32(buf[:], time)
+	_, err = inner.Write(buf[:])
+	if err != nil {
+		return
+	}
+
+	plaintext = inner
+	return
+}

+ 143 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/ocfb.go

@@ -0,0 +1,143 @@
+// Copyright 2010 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.
+
+// OpenPGP CFB Mode. http://tools.ietf.org/html/rfc4880#section-13.9
+
+package packet
+
+import (
+	"crypto/cipher"
+)
+
+type ocfbEncrypter struct {
+	b       cipher.Block
+	fre     []byte
+	outUsed int
+}
+
+// An OCFBResyncOption determines if the "resynchronization step" of OCFB is
+// performed.
+type OCFBResyncOption bool
+
+const (
+	OCFBResync   OCFBResyncOption = true
+	OCFBNoResync OCFBResyncOption = false
+)
+
+// NewOCFBEncrypter returns a cipher.Stream which encrypts data with OpenPGP's
+// cipher feedback mode using the given cipher.Block, and an initial amount of
+// ciphertext.  randData must be random bytes and be the same length as the
+// cipher.Block's block size. Resync determines if the "resynchronization step"
+// from RFC 4880, 13.9 step 7 is performed. Different parts of OpenPGP vary on
+// this point.
+func NewOCFBEncrypter(block cipher.Block, randData []byte, resync OCFBResyncOption) (cipher.Stream, []byte) {
+	blockSize := block.BlockSize()
+	if len(randData) != blockSize {
+		return nil, nil
+	}
+
+	x := &ocfbEncrypter{
+		b:       block,
+		fre:     make([]byte, blockSize),
+		outUsed: 0,
+	}
+	prefix := make([]byte, blockSize+2)
+
+	block.Encrypt(x.fre, x.fre)
+	for i := 0; i < blockSize; i++ {
+		prefix[i] = randData[i] ^ x.fre[i]
+	}
+
+	block.Encrypt(x.fre, prefix[:blockSize])
+	prefix[blockSize] = x.fre[0] ^ randData[blockSize-2]
+	prefix[blockSize+1] = x.fre[1] ^ randData[blockSize-1]
+
+	if resync {
+		block.Encrypt(x.fre, prefix[2:])
+	} else {
+		x.fre[0] = prefix[blockSize]
+		x.fre[1] = prefix[blockSize+1]
+		x.outUsed = 2
+	}
+	return x, prefix
+}
+
+func (x *ocfbEncrypter) XORKeyStream(dst, src []byte) {
+	for i := 0; i < len(src); i++ {
+		if x.outUsed == len(x.fre) {
+			x.b.Encrypt(x.fre, x.fre)
+			x.outUsed = 0
+		}
+
+		x.fre[x.outUsed] ^= src[i]
+		dst[i] = x.fre[x.outUsed]
+		x.outUsed++
+	}
+}
+
+type ocfbDecrypter struct {
+	b       cipher.Block
+	fre     []byte
+	outUsed int
+}
+
+// NewOCFBDecrypter returns a cipher.Stream which decrypts data with OpenPGP's
+// cipher feedback mode using the given cipher.Block. Prefix must be the first
+// blockSize + 2 bytes of the ciphertext, where blockSize is the cipher.Block's
+// block size. If an incorrect key is detected then nil is returned. On
+// successful exit, blockSize+2 bytes of decrypted data are written into
+// prefix. Resync determines if the "resynchronization step" from RFC 4880,
+// 13.9 step 7 is performed. Different parts of OpenPGP vary on this point.
+func NewOCFBDecrypter(block cipher.Block, prefix []byte, resync OCFBResyncOption) cipher.Stream {
+	blockSize := block.BlockSize()
+	if len(prefix) != blockSize+2 {
+		return nil
+	}
+
+	x := &ocfbDecrypter{
+		b:       block,
+		fre:     make([]byte, blockSize),
+		outUsed: 0,
+	}
+	prefixCopy := make([]byte, len(prefix))
+	copy(prefixCopy, prefix)
+
+	block.Encrypt(x.fre, x.fre)
+	for i := 0; i < blockSize; i++ {
+		prefixCopy[i] ^= x.fre[i]
+	}
+
+	block.Encrypt(x.fre, prefix[:blockSize])
+	prefixCopy[blockSize] ^= x.fre[0]
+	prefixCopy[blockSize+1] ^= x.fre[1]
+
+	if prefixCopy[blockSize-2] != prefixCopy[blockSize] ||
+		prefixCopy[blockSize-1] != prefixCopy[blockSize+1] {
+		return nil
+	}
+
+	if resync {
+		block.Encrypt(x.fre, prefix[2:])
+	} else {
+		x.fre[0] = prefix[blockSize]
+		x.fre[1] = prefix[blockSize+1]
+		x.outUsed = 2
+	}
+	copy(prefix, prefixCopy)
+	return x
+}
+
+func (x *ocfbDecrypter) XORKeyStream(dst, src []byte) {
+	for i := 0; i < len(src); i++ {
+		if x.outUsed == len(x.fre) {
+			x.b.Encrypt(x.fre, x.fre)
+			x.outUsed = 0
+		}
+
+		c := src[i]
+		dst[i] = x.fre[x.outUsed] ^ src[i]
+		x.fre[x.outUsed] = c
+		x.outUsed++
+	}
+}

+ 46 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/ocfb_test.go

@@ -0,0 +1,46 @@
+// Copyright 2010 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 packet
+
+import (
+	"bytes"
+	"crypto/aes"
+	"crypto/rand"
+	"testing"
+)
+
+var commonKey128 = []byte{0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}
+
+func testOCFB(t *testing.T, resync OCFBResyncOption) {
+	block, err := aes.NewCipher(commonKey128)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	plaintext := []byte("this is the plaintext, which is long enough to span several blocks.")
+	randData := make([]byte, block.BlockSize())
+	rand.Reader.Read(randData)
+	ocfb, prefix := NewOCFBEncrypter(block, randData, resync)
+	ciphertext := make([]byte, len(plaintext))
+	ocfb.XORKeyStream(ciphertext, plaintext)
+
+	ocfbdec := NewOCFBDecrypter(block, prefix, resync)
+	if ocfbdec == nil {
+		t.Errorf("NewOCFBDecrypter failed (resync: %t)", resync)
+		return
+	}
+	plaintextCopy := make([]byte, len(plaintext))
+	ocfbdec.XORKeyStream(plaintextCopy, ciphertext)
+
+	if !bytes.Equal(plaintextCopy, plaintext) {
+		t.Errorf("got: %x, want: %x (resync: %t)", plaintextCopy, plaintext, resync)
+	}
+}
+
+func TestOCFB(t *testing.T) {
+	testOCFB(t, OCFBNoResync)
+	testOCFB(t, OCFBResync)
+}

+ 73 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/one_pass_signature.go

@@ -0,0 +1,73 @@
+// Copyright 2011 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 packet
+
+import (
+	"crypto"
+	"encoding/binary"
+	"golang.org/x/crypto/openpgp/errors"
+	"golang.org/x/crypto/openpgp/s2k"
+	"io"
+	"strconv"
+)
+
+// OnePassSignature represents a one-pass signature packet. See RFC 4880,
+// section 5.4.
+type OnePassSignature struct {
+	SigType    SignatureType
+	Hash       crypto.Hash
+	PubKeyAlgo PublicKeyAlgorithm
+	KeyId      uint64
+	IsLast     bool
+}
+
+const onePassSignatureVersion = 3
+
+func (ops *OnePassSignature) parse(r io.Reader) (err error) {
+	var buf [13]byte
+
+	_, err = readFull(r, buf[:])
+	if err != nil {
+		return
+	}
+	if buf[0] != onePassSignatureVersion {
+		err = errors.UnsupportedError("one-pass-signature packet version " + strconv.Itoa(int(buf[0])))
+	}
+
+	var ok bool
+	ops.Hash, ok = s2k.HashIdToHash(buf[2])
+	if !ok {
+		return errors.UnsupportedError("hash function: " + strconv.Itoa(int(buf[2])))
+	}
+
+	ops.SigType = SignatureType(buf[1])
+	ops.PubKeyAlgo = PublicKeyAlgorithm(buf[3])
+	ops.KeyId = binary.BigEndian.Uint64(buf[4:12])
+	ops.IsLast = buf[12] != 0
+	return
+}
+
+// Serialize marshals the given OnePassSignature to w.
+func (ops *OnePassSignature) Serialize(w io.Writer) error {
+	var buf [13]byte
+	buf[0] = onePassSignatureVersion
+	buf[1] = uint8(ops.SigType)
+	var ok bool
+	buf[2], ok = s2k.HashToHashId(ops.Hash)
+	if !ok {
+		return errors.UnsupportedError("hash type: " + strconv.Itoa(int(ops.Hash)))
+	}
+	buf[3] = uint8(ops.PubKeyAlgo)
+	binary.BigEndian.PutUint64(buf[4:12], ops.KeyId)
+	if ops.IsLast {
+		buf[12] = 1
+	}
+
+	if err := serializeHeader(w, packetTypeOnePassSignature, len(buf)); err != nil {
+		return err
+	}
+	_, err := w.Write(buf[:])
+	return err
+}

+ 162 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/opaque.go

@@ -0,0 +1,162 @@
+// Copyright 2012 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 packet
+
+import (
+	"bytes"
+	"io"
+	"io/ioutil"
+
+	"golang.org/x/crypto/openpgp/errors"
+)
+
+// OpaquePacket represents an OpenPGP packet as raw, unparsed data. This is
+// useful for splitting and storing the original packet contents separately,
+// handling unsupported packet types or accessing parts of the packet not yet
+// implemented by this package.
+type OpaquePacket struct {
+	// Packet type
+	Tag uint8
+	// Reason why the packet was parsed opaquely
+	Reason error
+	// Binary contents of the packet data
+	Contents []byte
+}
+
+func (op *OpaquePacket) parse(r io.Reader) (err error) {
+	op.Contents, err = ioutil.ReadAll(r)
+	return
+}
+
+// Serialize marshals the packet to a writer in its original form, including
+// the packet header.
+func (op *OpaquePacket) Serialize(w io.Writer) (err error) {
+	err = serializeHeader(w, packetType(op.Tag), len(op.Contents))
+	if err == nil {
+		_, err = w.Write(op.Contents)
+	}
+	return
+}
+
+// Parse attempts to parse the opaque contents into a structure supported by
+// this package. If the packet is not known then the result will be another
+// OpaquePacket.
+func (op *OpaquePacket) Parse() (p Packet, err error) {
+	hdr := bytes.NewBuffer(nil)
+	err = serializeHeader(hdr, packetType(op.Tag), len(op.Contents))
+	if err != nil {
+		op.Reason = err
+		return op, err
+	}
+	p, err = Read(io.MultiReader(hdr, bytes.NewBuffer(op.Contents)))
+	if err != nil {
+		op.Reason = err
+		p = op
+	}
+	return
+}
+
+// OpaqueReader reads OpaquePackets from an io.Reader.
+type OpaqueReader struct {
+	r io.Reader
+}
+
+func NewOpaqueReader(r io.Reader) *OpaqueReader {
+	return &OpaqueReader{r: r}
+}
+
+// Read the next OpaquePacket.
+func (or *OpaqueReader) Next() (op *OpaquePacket, err error) {
+	tag, _, contents, err := readHeader(or.r)
+	if err != nil {
+		return
+	}
+	op = &OpaquePacket{Tag: uint8(tag), Reason: err}
+	err = op.parse(contents)
+	if err != nil {
+		consumeAll(contents)
+	}
+	return
+}
+
+// OpaqueSubpacket represents an unparsed OpenPGP subpacket,
+// as found in signature and user attribute packets.
+type OpaqueSubpacket struct {
+	SubType  uint8
+	Contents []byte
+}
+
+// OpaqueSubpackets extracts opaque, unparsed OpenPGP subpackets from
+// their byte representation.
+func OpaqueSubpackets(contents []byte) (result []*OpaqueSubpacket, err error) {
+	var (
+		subHeaderLen int
+		subPacket    *OpaqueSubpacket
+	)
+	for len(contents) > 0 {
+		subHeaderLen, subPacket, err = nextSubpacket(contents)
+		if err != nil {
+			break
+		}
+		result = append(result, subPacket)
+		contents = contents[subHeaderLen+len(subPacket.Contents):]
+	}
+	return
+}
+
+func nextSubpacket(contents []byte) (subHeaderLen int, subPacket *OpaqueSubpacket, err error) {
+	// RFC 4880, section 5.2.3.1
+	var subLen uint32
+	if len(contents) < 1 {
+		goto Truncated
+	}
+	subPacket = &OpaqueSubpacket{}
+	switch {
+	case contents[0] < 192:
+		subHeaderLen = 2 // 1 length byte, 1 subtype byte
+		if len(contents) < subHeaderLen {
+			goto Truncated
+		}
+		subLen = uint32(contents[0])
+		contents = contents[1:]
+	case contents[0] < 255:
+		subHeaderLen = 3 // 2 length bytes, 1 subtype
+		if len(contents) < subHeaderLen {
+			goto Truncated
+		}
+		subLen = uint32(contents[0]-192)<<8 + uint32(contents[1]) + 192
+		contents = contents[2:]
+	default:
+		subHeaderLen = 6 // 5 length bytes, 1 subtype
+		if len(contents) < subHeaderLen {
+			goto Truncated
+		}
+		subLen = uint32(contents[1])<<24 |
+			uint32(contents[2])<<16 |
+			uint32(contents[3])<<8 |
+			uint32(contents[4])
+		contents = contents[5:]
+	}
+	if subLen > uint32(len(contents)) || subLen == 0 {
+		goto Truncated
+	}
+	subPacket.SubType = contents[0]
+	subPacket.Contents = contents[1:subLen]
+	return
+Truncated:
+	err = errors.StructuralError("subpacket truncated")
+	return
+}
+
+func (osp *OpaqueSubpacket) Serialize(w io.Writer) (err error) {
+	buf := make([]byte, 6)
+	n := serializeSubpacketLength(buf, len(osp.Contents)+1)
+	buf[n] = osp.SubType
+	if _, err = w.Write(buf[:n+1]); err != nil {
+		return
+	}
+	_, err = w.Write(osp.Contents)
+	return
+}

+ 67 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/opaque_test.go

@@ -0,0 +1,67 @@
+// Copyright 2011 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 packet
+
+import (
+	"bytes"
+	"encoding/hex"
+	"io"
+	"testing"
+)
+
+// Test packet.Read error handling in OpaquePacket.Parse,
+// which attempts to re-read an OpaquePacket as a supported
+// Packet type.
+func TestOpaqueParseReason(t *testing.T) {
+	buf, err := hex.DecodeString(UnsupportedKeyHex)
+	if err != nil {
+		t.Fatal(err)
+	}
+	or := NewOpaqueReader(bytes.NewBuffer(buf))
+	count := 0
+	badPackets := 0
+	var uid *UserId
+	for {
+		op, err := or.Next()
+		if err == io.EOF {
+			break
+		} else if err != nil {
+			t.Errorf("#%d: opaque read error: %v", count, err)
+			break
+		}
+		// try to parse opaque packet
+		p, err := op.Parse()
+		switch pkt := p.(type) {
+		case *UserId:
+			uid = pkt
+		case *OpaquePacket:
+			// If an OpaquePacket can't re-parse, packet.Read
+			// certainly had its reasons.
+			if pkt.Reason == nil {
+				t.Errorf("#%d: opaque packet, no reason", count)
+			} else {
+				badPackets++
+			}
+		}
+		count++
+	}
+
+	const expectedBad = 3
+	// Test post-conditions, make sure we actually parsed packets as expected.
+	if badPackets != expectedBad {
+		t.Errorf("unexpected # unparseable packets: %d (want %d)", badPackets, expectedBad)
+	}
+	if uid == nil {
+		t.Errorf("failed to find expected UID in unsupported keyring")
+	} else if uid.Id != "Armin M. Warda <[email protected]>" {
+		t.Errorf("unexpected UID: %v", uid.Id)
+	}
+}
+
+// This key material has public key and signature packet versions modified to
+// an unsupported value (1), so that trying to parse the OpaquePacket to
+// a typed packet will get an error. It also contains a GnuPG trust packet.
+// (Created with: od -An -t x1 pubring.gpg | xargs | sed 's/ //g')
+const UnsupportedKeyHex = `988d012e7a18a20000010400d6ac00d92b89c1f4396c243abb9b76d2e9673ad63483291fed88e22b82e255e441c078c6abbbf7d2d195e50b62eeaa915b85b0ec20c225ce2c64c167cacb6e711daf2e45da4a8356a059b8160e3b3628ac0dd8437b31f06d53d6e8ea4214d4a26406a6b63e1001406ef23e0bb3069fac9a99a91f77dfafd5de0f188a5da5e3c9000511b42741726d696e204d2e205761726461203c7761726461406e657068696c696d2e727568722e64653e8900950105102e8936c705d1eb399e58489901013f0e03ff5a0c4f421e34fcfa388129166420c08cd76987bcdec6f01bd0271459a85cc22048820dd4e44ac2c7d23908d540f54facf1b36b0d9c20488781ce9dca856531e76e2e846826e9951338020a03a09b57aa5faa82e9267458bd76105399885ac35af7dc1cbb6aaed7c39e1039f3b5beda2c0e916bd38560509bab81235d1a0ead83b0020000`

+ 539 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/packet.go

@@ -0,0 +1,539 @@
+// Copyright 2011 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 packet implements parsing and serialization of OpenPGP packets, as
+// specified in RFC 4880.
+package packet // import "golang.org/x/crypto/openpgp/packet"
+
+import (
+	"bufio"
+	"crypto/aes"
+	"crypto/cipher"
+	"crypto/des"
+	"golang.org/x/crypto/cast5"
+	"golang.org/x/crypto/openpgp/errors"
+	"io"
+	"math/big"
+)
+
+// readFull is the same as io.ReadFull except that reading zero bytes returns
+// ErrUnexpectedEOF rather than EOF.
+func readFull(r io.Reader, buf []byte) (n int, err error) {
+	n, err = io.ReadFull(r, buf)
+	if err == io.EOF {
+		err = io.ErrUnexpectedEOF
+	}
+	return
+}
+
+// readLength reads an OpenPGP length from r. See RFC 4880, section 4.2.2.
+func readLength(r io.Reader) (length int64, isPartial bool, err error) {
+	var buf [4]byte
+	_, err = readFull(r, buf[:1])
+	if err != nil {
+		return
+	}
+	switch {
+	case buf[0] < 192:
+		length = int64(buf[0])
+	case buf[0] < 224:
+		length = int64(buf[0]-192) << 8
+		_, err = readFull(r, buf[0:1])
+		if err != nil {
+			return
+		}
+		length += int64(buf[0]) + 192
+	case buf[0] < 255:
+		length = int64(1) << (buf[0] & 0x1f)
+		isPartial = true
+	default:
+		_, err = readFull(r, buf[0:4])
+		if err != nil {
+			return
+		}
+		length = int64(buf[0])<<24 |
+			int64(buf[1])<<16 |
+			int64(buf[2])<<8 |
+			int64(buf[3])
+	}
+	return
+}
+
+// partialLengthReader wraps an io.Reader and handles OpenPGP partial lengths.
+// The continuation lengths are parsed and removed from the stream and EOF is
+// returned at the end of the packet. See RFC 4880, section 4.2.2.4.
+type partialLengthReader struct {
+	r         io.Reader
+	remaining int64
+	isPartial bool
+}
+
+func (r *partialLengthReader) Read(p []byte) (n int, err error) {
+	for r.remaining == 0 {
+		if !r.isPartial {
+			return 0, io.EOF
+		}
+		r.remaining, r.isPartial, err = readLength(r.r)
+		if err != nil {
+			return 0, err
+		}
+	}
+
+	toRead := int64(len(p))
+	if toRead > r.remaining {
+		toRead = r.remaining
+	}
+
+	n, err = r.r.Read(p[:int(toRead)])
+	r.remaining -= int64(n)
+	if n < int(toRead) && err == io.EOF {
+		err = io.ErrUnexpectedEOF
+	}
+	return
+}
+
+// partialLengthWriter writes a stream of data using OpenPGP partial lengths.
+// See RFC 4880, section 4.2.2.4.
+type partialLengthWriter struct {
+	w          io.WriteCloser
+	lengthByte [1]byte
+}
+
+func (w *partialLengthWriter) Write(p []byte) (n int, err error) {
+	for len(p) > 0 {
+		for power := uint(14); power < 32; power-- {
+			l := 1 << power
+			if len(p) >= l {
+				w.lengthByte[0] = 224 + uint8(power)
+				_, err = w.w.Write(w.lengthByte[:])
+				if err != nil {
+					return
+				}
+				var m int
+				m, err = w.w.Write(p[:l])
+				n += m
+				if err != nil {
+					return
+				}
+				p = p[l:]
+				break
+			}
+		}
+	}
+	return
+}
+
+func (w *partialLengthWriter) Close() error {
+	w.lengthByte[0] = 0
+	_, err := w.w.Write(w.lengthByte[:])
+	if err != nil {
+		return err
+	}
+	return w.w.Close()
+}
+
+// A spanReader is an io.LimitReader, but it returns ErrUnexpectedEOF if the
+// underlying Reader returns EOF before the limit has been reached.
+type spanReader struct {
+	r io.Reader
+	n int64
+}
+
+func (l *spanReader) Read(p []byte) (n int, err error) {
+	if l.n <= 0 {
+		return 0, io.EOF
+	}
+	if int64(len(p)) > l.n {
+		p = p[0:l.n]
+	}
+	n, err = l.r.Read(p)
+	l.n -= int64(n)
+	if l.n > 0 && err == io.EOF {
+		err = io.ErrUnexpectedEOF
+	}
+	return
+}
+
+// readHeader parses a packet header and returns an io.Reader which will return
+// the contents of the packet. See RFC 4880, section 4.2.
+func readHeader(r io.Reader) (tag packetType, length int64, contents io.Reader, err error) {
+	var buf [4]byte
+	_, err = io.ReadFull(r, buf[:1])
+	if err != nil {
+		return
+	}
+	if buf[0]&0x80 == 0 {
+		err = errors.StructuralError("tag byte does not have MSB set")
+		return
+	}
+	if buf[0]&0x40 == 0 {
+		// Old format packet
+		tag = packetType((buf[0] & 0x3f) >> 2)
+		lengthType := buf[0] & 3
+		if lengthType == 3 {
+			length = -1
+			contents = r
+			return
+		}
+		lengthBytes := 1 << lengthType
+		_, err = readFull(r, buf[0:lengthBytes])
+		if err != nil {
+			return
+		}
+		for i := 0; i < lengthBytes; i++ {
+			length <<= 8
+			length |= int64(buf[i])
+		}
+		contents = &spanReader{r, length}
+		return
+	}
+
+	// New format packet
+	tag = packetType(buf[0] & 0x3f)
+	length, isPartial, err := readLength(r)
+	if err != nil {
+		return
+	}
+	if isPartial {
+		contents = &partialLengthReader{
+			remaining: length,
+			isPartial: true,
+			r:         r,
+		}
+		length = -1
+	} else {
+		contents = &spanReader{r, length}
+	}
+	return
+}
+
+// serializeHeader writes an OpenPGP packet header to w. See RFC 4880, section
+// 4.2.
+func serializeHeader(w io.Writer, ptype packetType, length int) (err error) {
+	var buf [6]byte
+	var n int
+
+	buf[0] = 0x80 | 0x40 | byte(ptype)
+	if length < 192 {
+		buf[1] = byte(length)
+		n = 2
+	} else if length < 8384 {
+		length -= 192
+		buf[1] = 192 + byte(length>>8)
+		buf[2] = byte(length)
+		n = 3
+	} else {
+		buf[1] = 255
+		buf[2] = byte(length >> 24)
+		buf[3] = byte(length >> 16)
+		buf[4] = byte(length >> 8)
+		buf[5] = byte(length)
+		n = 6
+	}
+
+	_, err = w.Write(buf[:n])
+	return
+}
+
+// serializeStreamHeader writes an OpenPGP packet header to w where the
+// length of the packet is unknown. It returns a io.WriteCloser which can be
+// used to write the contents of the packet. See RFC 4880, section 4.2.
+func serializeStreamHeader(w io.WriteCloser, ptype packetType) (out io.WriteCloser, err error) {
+	var buf [1]byte
+	buf[0] = 0x80 | 0x40 | byte(ptype)
+	_, err = w.Write(buf[:])
+	if err != nil {
+		return
+	}
+	out = &partialLengthWriter{w: w}
+	return
+}
+
+// Packet represents an OpenPGP packet. Users are expected to try casting
+// instances of this interface to specific packet types.
+type Packet interface {
+	parse(io.Reader) error
+}
+
+// consumeAll reads from the given Reader until error, returning the number of
+// bytes read.
+func consumeAll(r io.Reader) (n int64, err error) {
+	var m int
+	var buf [1024]byte
+
+	for {
+		m, err = r.Read(buf[:])
+		n += int64(m)
+		if err == io.EOF {
+			err = nil
+			return
+		}
+		if err != nil {
+			return
+		}
+	}
+
+	panic("unreachable")
+}
+
+// packetType represents the numeric ids of the different OpenPGP packet types. See
+// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-2
+type packetType uint8
+
+const (
+	packetTypeEncryptedKey              packetType = 1
+	packetTypeSignature                 packetType = 2
+	packetTypeSymmetricKeyEncrypted     packetType = 3
+	packetTypeOnePassSignature          packetType = 4
+	packetTypePrivateKey                packetType = 5
+	packetTypePublicKey                 packetType = 6
+	packetTypePrivateSubkey             packetType = 7
+	packetTypeCompressed                packetType = 8
+	packetTypeSymmetricallyEncrypted    packetType = 9
+	packetTypeLiteralData               packetType = 11
+	packetTypeUserId                    packetType = 13
+	packetTypePublicSubkey              packetType = 14
+	packetTypeUserAttribute             packetType = 17
+	packetTypeSymmetricallyEncryptedMDC packetType = 18
+)
+
+// peekVersion detects the version of a public key packet about to
+// be read. A bufio.Reader at the original position of the io.Reader
+// is returned.
+func peekVersion(r io.Reader) (bufr *bufio.Reader, ver byte, err error) {
+	bufr = bufio.NewReader(r)
+	var verBuf []byte
+	if verBuf, err = bufr.Peek(1); err != nil {
+		return
+	}
+	ver = verBuf[0]
+	return
+}
+
+// Read reads a single OpenPGP packet from the given io.Reader. If there is an
+// error parsing a packet, the whole packet is consumed from the input.
+func Read(r io.Reader) (p Packet, err error) {
+	tag, _, contents, err := readHeader(r)
+	if err != nil {
+		return
+	}
+
+	switch tag {
+	case packetTypeEncryptedKey:
+		p = new(EncryptedKey)
+	case packetTypeSignature:
+		var version byte
+		// Detect signature version
+		if contents, version, err = peekVersion(contents); err != nil {
+			return
+		}
+		if version < 4 {
+			p = new(SignatureV3)
+		} else {
+			p = new(Signature)
+		}
+	case packetTypeSymmetricKeyEncrypted:
+		p = new(SymmetricKeyEncrypted)
+	case packetTypeOnePassSignature:
+		p = new(OnePassSignature)
+	case packetTypePrivateKey, packetTypePrivateSubkey:
+		pk := new(PrivateKey)
+		if tag == packetTypePrivateSubkey {
+			pk.IsSubkey = true
+		}
+		p = pk
+	case packetTypePublicKey, packetTypePublicSubkey:
+		var version byte
+		if contents, version, err = peekVersion(contents); err != nil {
+			return
+		}
+		isSubkey := tag == packetTypePublicSubkey
+		if version < 4 {
+			p = &PublicKeyV3{IsSubkey: isSubkey}
+		} else {
+			p = &PublicKey{IsSubkey: isSubkey}
+		}
+	case packetTypeCompressed:
+		p = new(Compressed)
+	case packetTypeSymmetricallyEncrypted:
+		p = new(SymmetricallyEncrypted)
+	case packetTypeLiteralData:
+		p = new(LiteralData)
+	case packetTypeUserId:
+		p = new(UserId)
+	case packetTypeUserAttribute:
+		p = new(UserAttribute)
+	case packetTypeSymmetricallyEncryptedMDC:
+		se := new(SymmetricallyEncrypted)
+		se.MDC = true
+		p = se
+	default:
+		err = errors.UnknownPacketTypeError(tag)
+	}
+	if p != nil {
+		err = p.parse(contents)
+	}
+	if err != nil {
+		consumeAll(contents)
+	}
+	return
+}
+
+// SignatureType represents the different semantic meanings of an OpenPGP
+// signature. See RFC 4880, section 5.2.1.
+type SignatureType uint8
+
+const (
+	SigTypeBinary            SignatureType = 0
+	SigTypeText                            = 1
+	SigTypeGenericCert                     = 0x10
+	SigTypePersonaCert                     = 0x11
+	SigTypeCasualCert                      = 0x12
+	SigTypePositiveCert                    = 0x13
+	SigTypeSubkeyBinding                   = 0x18
+	SigTypePrimaryKeyBinding               = 0x19
+	SigTypeDirectSignature                 = 0x1F
+	SigTypeKeyRevocation                   = 0x20
+	SigTypeSubkeyRevocation                = 0x28
+)
+
+// PublicKeyAlgorithm represents the different public key system specified for
+// OpenPGP. See
+// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-12
+type PublicKeyAlgorithm uint8
+
+const (
+	PubKeyAlgoRSA            PublicKeyAlgorithm = 1
+	PubKeyAlgoRSAEncryptOnly PublicKeyAlgorithm = 2
+	PubKeyAlgoRSASignOnly    PublicKeyAlgorithm = 3
+	PubKeyAlgoElGamal        PublicKeyAlgorithm = 16
+	PubKeyAlgoDSA            PublicKeyAlgorithm = 17
+	// RFC 6637, Section 5.
+	PubKeyAlgoECDH  PublicKeyAlgorithm = 18
+	PubKeyAlgoECDSA PublicKeyAlgorithm = 19
+)
+
+// CanEncrypt returns true if it's possible to encrypt a message to a public
+// key of the given type.
+func (pka PublicKeyAlgorithm) CanEncrypt() bool {
+	switch pka {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal:
+		return true
+	}
+	return false
+}
+
+// CanSign returns true if it's possible for a public key of the given type to
+// sign a message.
+func (pka PublicKeyAlgorithm) CanSign() bool {
+	switch pka {
+	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA:
+		return true
+	}
+	return false
+}
+
+// CipherFunction represents the different block ciphers specified for OpenPGP. See
+// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13
+type CipherFunction uint8
+
+const (
+	Cipher3DES   CipherFunction = 2
+	CipherCAST5  CipherFunction = 3
+	CipherAES128 CipherFunction = 7
+	CipherAES192 CipherFunction = 8
+	CipherAES256 CipherFunction = 9
+)
+
+// KeySize returns the key size, in bytes, of cipher.
+func (cipher CipherFunction) KeySize() int {
+	switch cipher {
+	case Cipher3DES:
+		return 24
+	case CipherCAST5:
+		return cast5.KeySize
+	case CipherAES128:
+		return 16
+	case CipherAES192:
+		return 24
+	case CipherAES256:
+		return 32
+	}
+	return 0
+}
+
+// blockSize returns the block size, in bytes, of cipher.
+func (cipher CipherFunction) blockSize() int {
+	switch cipher {
+	case Cipher3DES:
+		return des.BlockSize
+	case CipherCAST5:
+		return 8
+	case CipherAES128, CipherAES192, CipherAES256:
+		return 16
+	}
+	return 0
+}
+
+// new returns a fresh instance of the given cipher.
+func (cipher CipherFunction) new(key []byte) (block cipher.Block) {
+	switch cipher {
+	case Cipher3DES:
+		block, _ = des.NewTripleDESCipher(key)
+	case CipherCAST5:
+		block, _ = cast5.NewCipher(key)
+	case CipherAES128, CipherAES192, CipherAES256:
+		block, _ = aes.NewCipher(key)
+	}
+	return
+}
+
+// readMPI reads a big integer from r. The bit length returned is the bit
+// length that was specified in r. This is preserved so that the integer can be
+// reserialized exactly.
+func readMPI(r io.Reader) (mpi []byte, bitLength uint16, err error) {
+	var buf [2]byte
+	_, err = readFull(r, buf[0:])
+	if err != nil {
+		return
+	}
+	bitLength = uint16(buf[0])<<8 | uint16(buf[1])
+	numBytes := (int(bitLength) + 7) / 8
+	mpi = make([]byte, numBytes)
+	_, err = readFull(r, mpi)
+	return
+}
+
+// mpiLength returns the length of the given *big.Int when serialized as an
+// MPI.
+func mpiLength(n *big.Int) (mpiLengthInBytes int) {
+	mpiLengthInBytes = 2 /* MPI length */
+	mpiLengthInBytes += (n.BitLen() + 7) / 8
+	return
+}
+
+// writeMPI serializes a big integer to w.
+func writeMPI(w io.Writer, bitLength uint16, mpiBytes []byte) (err error) {
+	_, err = w.Write([]byte{byte(bitLength >> 8), byte(bitLength)})
+	if err == nil {
+		_, err = w.Write(mpiBytes)
+	}
+	return
+}
+
+// writeBig serializes a *big.Int to w.
+func writeBig(w io.Writer, i *big.Int) error {
+	return writeMPI(w, uint16(i.BitLen()), i.Bytes())
+}
+
+// CompressionAlgo Represents the different compression algorithms
+// supported by OpenPGP (except for BZIP2, which is not currently
+// supported). See Section 9.3 of RFC 4880.
+type CompressionAlgo uint8
+
+const (
+	CompressionNone CompressionAlgo = 0
+	CompressionZIP  CompressionAlgo = 1
+	CompressionZLIB CompressionAlgo = 2
+)

+ 255 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/packet_test.go

@@ -0,0 +1,255 @@
+// Copyright 2011 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 packet
+
+import (
+	"bytes"
+	"encoding/hex"
+	"fmt"
+	"golang.org/x/crypto/openpgp/errors"
+	"io"
+	"io/ioutil"
+	"testing"
+)
+
+func TestReadFull(t *testing.T) {
+	var out [4]byte
+
+	b := bytes.NewBufferString("foo")
+	n, err := readFull(b, out[:3])
+	if n != 3 || err != nil {
+		t.Errorf("full read failed n:%d err:%s", n, err)
+	}
+
+	b = bytes.NewBufferString("foo")
+	n, err = readFull(b, out[:4])
+	if n != 3 || err != io.ErrUnexpectedEOF {
+		t.Errorf("partial read failed n:%d err:%s", n, err)
+	}
+
+	b = bytes.NewBuffer(nil)
+	n, err = readFull(b, out[:3])
+	if n != 0 || err != io.ErrUnexpectedEOF {
+		t.Errorf("empty read failed n:%d err:%s", n, err)
+	}
+}
+
+func readerFromHex(s string) io.Reader {
+	data, err := hex.DecodeString(s)
+	if err != nil {
+		panic("readerFromHex: bad input")
+	}
+	return bytes.NewBuffer(data)
+}
+
+var readLengthTests = []struct {
+	hexInput  string
+	length    int64
+	isPartial bool
+	err       error
+}{
+	{"", 0, false, io.ErrUnexpectedEOF},
+	{"1f", 31, false, nil},
+	{"c0", 0, false, io.ErrUnexpectedEOF},
+	{"c101", 256 + 1 + 192, false, nil},
+	{"e0", 1, true, nil},
+	{"e1", 2, true, nil},
+	{"e2", 4, true, nil},
+	{"ff", 0, false, io.ErrUnexpectedEOF},
+	{"ff00", 0, false, io.ErrUnexpectedEOF},
+	{"ff0000", 0, false, io.ErrUnexpectedEOF},
+	{"ff000000", 0, false, io.ErrUnexpectedEOF},
+	{"ff00000000", 0, false, nil},
+	{"ff01020304", 16909060, false, nil},
+}
+
+func TestReadLength(t *testing.T) {
+	for i, test := range readLengthTests {
+		length, isPartial, err := readLength(readerFromHex(test.hexInput))
+		if test.err != nil {
+			if err != test.err {
+				t.Errorf("%d: expected different error got:%s want:%s", i, err, test.err)
+			}
+			continue
+		}
+		if err != nil {
+			t.Errorf("%d: unexpected error: %s", i, err)
+			continue
+		}
+		if length != test.length || isPartial != test.isPartial {
+			t.Errorf("%d: bad result got:(%d,%t) want:(%d,%t)", i, length, isPartial, test.length, test.isPartial)
+		}
+	}
+}
+
+var partialLengthReaderTests = []struct {
+	hexInput  string
+	err       error
+	hexOutput string
+}{
+	{"e0", io.ErrUnexpectedEOF, ""},
+	{"e001", io.ErrUnexpectedEOF, ""},
+	{"e0010102", nil, "0102"},
+	{"ff00000000", nil, ""},
+	{"e10102e1030400", nil, "01020304"},
+	{"e101", io.ErrUnexpectedEOF, ""},
+}
+
+func TestPartialLengthReader(t *testing.T) {
+	for i, test := range partialLengthReaderTests {
+		r := &partialLengthReader{readerFromHex(test.hexInput), 0, true}
+		out, err := ioutil.ReadAll(r)
+		if test.err != nil {
+			if err != test.err {
+				t.Errorf("%d: expected different error got:%s want:%s", i, err, test.err)
+			}
+			continue
+		}
+		if err != nil {
+			t.Errorf("%d: unexpected error: %s", i, err)
+			continue
+		}
+
+		got := fmt.Sprintf("%x", out)
+		if got != test.hexOutput {
+			t.Errorf("%d: got:%s want:%s", i, test.hexOutput, got)
+		}
+	}
+}
+
+var readHeaderTests = []struct {
+	hexInput        string
+	structuralError bool
+	unexpectedEOF   bool
+	tag             int
+	length          int64
+	hexOutput       string
+}{
+	{"", false, false, 0, 0, ""},
+	{"7f", true, false, 0, 0, ""},
+
+	// Old format headers
+	{"80", false, true, 0, 0, ""},
+	{"8001", false, true, 0, 1, ""},
+	{"800102", false, false, 0, 1, "02"},
+	{"81000102", false, false, 0, 1, "02"},
+	{"820000000102", false, false, 0, 1, "02"},
+	{"860000000102", false, false, 1, 1, "02"},
+	{"83010203", false, false, 0, -1, "010203"},
+
+	// New format headers
+	{"c0", false, true, 0, 0, ""},
+	{"c000", false, false, 0, 0, ""},
+	{"c00102", false, false, 0, 1, "02"},
+	{"c0020203", false, false, 0, 2, "0203"},
+	{"c00202", false, true, 0, 2, ""},
+	{"c3020203", false, false, 3, 2, "0203"},
+}
+
+func TestReadHeader(t *testing.T) {
+	for i, test := range readHeaderTests {
+		tag, length, contents, err := readHeader(readerFromHex(test.hexInput))
+		if test.structuralError {
+			if _, ok := err.(errors.StructuralError); ok {
+				continue
+			}
+			t.Errorf("%d: expected StructuralError, got:%s", i, err)
+			continue
+		}
+		if err != nil {
+			if len(test.hexInput) == 0 && err == io.EOF {
+				continue
+			}
+			if !test.unexpectedEOF || err != io.ErrUnexpectedEOF {
+				t.Errorf("%d: unexpected error from readHeader: %s", i, err)
+			}
+			continue
+		}
+		if int(tag) != test.tag || length != test.length {
+			t.Errorf("%d: got:(%d,%d) want:(%d,%d)", i, int(tag), length, test.tag, test.length)
+			continue
+		}
+
+		body, err := ioutil.ReadAll(contents)
+		if err != nil {
+			if !test.unexpectedEOF || err != io.ErrUnexpectedEOF {
+				t.Errorf("%d: unexpected error from contents: %s", i, err)
+			}
+			continue
+		}
+		if test.unexpectedEOF {
+			t.Errorf("%d: expected ErrUnexpectedEOF from contents but got no error", i)
+			continue
+		}
+		got := fmt.Sprintf("%x", body)
+		if got != test.hexOutput {
+			t.Errorf("%d: got:%s want:%s", i, got, test.hexOutput)
+		}
+	}
+}
+
+func TestSerializeHeader(t *testing.T) {
+	tag := packetTypePublicKey
+	lengths := []int{0, 1, 2, 64, 192, 193, 8000, 8384, 8385, 10000}
+
+	for _, length := range lengths {
+		buf := bytes.NewBuffer(nil)
+		serializeHeader(buf, tag, length)
+		tag2, length2, _, err := readHeader(buf)
+		if err != nil {
+			t.Errorf("length %d, err: %s", length, err)
+		}
+		if tag2 != tag {
+			t.Errorf("length %d, tag incorrect (got %d, want %d)", length, tag2, tag)
+		}
+		if int(length2) != length {
+			t.Errorf("length %d, length incorrect (got %d)", length, length2)
+		}
+	}
+}
+
+func TestPartialLengths(t *testing.T) {
+	buf := bytes.NewBuffer(nil)
+	w := new(partialLengthWriter)
+	w.w = noOpCloser{buf}
+
+	const maxChunkSize = 64
+
+	var b [maxChunkSize]byte
+	var n uint8
+	for l := 1; l <= maxChunkSize; l++ {
+		for i := 0; i < l; i++ {
+			b[i] = n
+			n++
+		}
+		m, err := w.Write(b[:l])
+		if m != l {
+			t.Errorf("short write got: %d want: %d", m, l)
+		}
+		if err != nil {
+			t.Errorf("error from write: %s", err)
+		}
+	}
+	w.Close()
+
+	want := (maxChunkSize * (maxChunkSize + 1)) / 2
+	copyBuf := bytes.NewBuffer(nil)
+	r := &partialLengthReader{buf, 0, true}
+	m, err := io.Copy(copyBuf, r)
+	if m != int64(want) {
+		t.Errorf("short copy got: %d want: %d", m, want)
+	}
+	if err != nil {
+		t.Errorf("error from copy: %s", err)
+	}
+
+	copyBytes := copyBuf.Bytes()
+	for i := 0; i < want; i++ {
+		if copyBytes[i] != uint8(i) {
+			t.Errorf("bad pattern in copy at %d", i)
+			break
+		}
+	}
+}

+ 362 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/private_key.go

@@ -0,0 +1,362 @@
+// Copyright 2011 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 packet
+
+import (
+	"bytes"
+	"crypto/cipher"
+	"crypto/dsa"
+	"crypto/ecdsa"
+	"crypto/rsa"
+	"crypto/sha1"
+	"io"
+	"io/ioutil"
+	"math/big"
+	"strconv"
+	"time"
+
+	"golang.org/x/crypto/openpgp/elgamal"
+	"golang.org/x/crypto/openpgp/errors"
+	"golang.org/x/crypto/openpgp/s2k"
+)
+
+// PrivateKey represents a possibly encrypted private key. See RFC 4880,
+// section 5.5.3.
+type PrivateKey struct {
+	PublicKey
+	Encrypted     bool // if true then the private key is unavailable until Decrypt has been called.
+	encryptedData []byte
+	cipher        CipherFunction
+	s2k           func(out, in []byte)
+	PrivateKey    interface{} // An *rsa.PrivateKey or *dsa.PrivateKey.
+	sha1Checksum  bool
+	iv            []byte
+}
+
+func NewRSAPrivateKey(currentTime time.Time, priv *rsa.PrivateKey) *PrivateKey {
+	pk := new(PrivateKey)
+	pk.PublicKey = *NewRSAPublicKey(currentTime, &priv.PublicKey)
+	pk.PrivateKey = priv
+	return pk
+}
+
+func NewDSAPrivateKey(currentTime time.Time, priv *dsa.PrivateKey) *PrivateKey {
+	pk := new(PrivateKey)
+	pk.PublicKey = *NewDSAPublicKey(currentTime, &priv.PublicKey)
+	pk.PrivateKey = priv
+	return pk
+}
+
+func NewElGamalPrivateKey(currentTime time.Time, priv *elgamal.PrivateKey) *PrivateKey {
+	pk := new(PrivateKey)
+	pk.PublicKey = *NewElGamalPublicKey(currentTime, &priv.PublicKey)
+	pk.PrivateKey = priv
+	return pk
+}
+
+func NewECDSAPrivateKey(currentTime time.Time, priv *ecdsa.PrivateKey) *PrivateKey {
+	pk := new(PrivateKey)
+	pk.PublicKey = *NewECDSAPublicKey(currentTime, &priv.PublicKey)
+	pk.PrivateKey = priv
+	return pk
+}
+
+func (pk *PrivateKey) parse(r io.Reader) (err error) {
+	err = (&pk.PublicKey).parse(r)
+	if err != nil {
+		return
+	}
+	var buf [1]byte
+	_, err = readFull(r, buf[:])
+	if err != nil {
+		return
+	}
+
+	s2kType := buf[0]
+
+	switch s2kType {
+	case 0:
+		pk.s2k = nil
+		pk.Encrypted = false
+	case 254, 255:
+		_, err = readFull(r, buf[:])
+		if err != nil {
+			return
+		}
+		pk.cipher = CipherFunction(buf[0])
+		pk.Encrypted = true
+		pk.s2k, err = s2k.Parse(r)
+		if err != nil {
+			return
+		}
+		if s2kType == 254 {
+			pk.sha1Checksum = true
+		}
+	default:
+		return errors.UnsupportedError("deprecated s2k function in private key")
+	}
+
+	if pk.Encrypted {
+		blockSize := pk.cipher.blockSize()
+		if blockSize == 0 {
+			return errors.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(pk.cipher)))
+		}
+		pk.iv = make([]byte, blockSize)
+		_, err = readFull(r, pk.iv)
+		if err != nil {
+			return
+		}
+	}
+
+	pk.encryptedData, err = ioutil.ReadAll(r)
+	if err != nil {
+		return
+	}
+
+	if !pk.Encrypted {
+		return pk.parsePrivateKey(pk.encryptedData)
+	}
+
+	return
+}
+
+func mod64kHash(d []byte) uint16 {
+	var h uint16
+	for _, b := range d {
+		h += uint16(b)
+	}
+	return h
+}
+
+func (pk *PrivateKey) Serialize(w io.Writer) (err error) {
+	// TODO(agl): support encrypted private keys
+	buf := bytes.NewBuffer(nil)
+	err = pk.PublicKey.serializeWithoutHeaders(buf)
+	if err != nil {
+		return
+	}
+	buf.WriteByte(0 /* no encryption */)
+
+	privateKeyBuf := bytes.NewBuffer(nil)
+
+	switch priv := pk.PrivateKey.(type) {
+	case *rsa.PrivateKey:
+		err = serializeRSAPrivateKey(privateKeyBuf, priv)
+	case *dsa.PrivateKey:
+		err = serializeDSAPrivateKey(privateKeyBuf, priv)
+	case *elgamal.PrivateKey:
+		err = serializeElGamalPrivateKey(privateKeyBuf, priv)
+	case *ecdsa.PrivateKey:
+		err = serializeECDSAPrivateKey(privateKeyBuf, priv)
+	default:
+		err = errors.InvalidArgumentError("unknown private key type")
+	}
+	if err != nil {
+		return
+	}
+
+	ptype := packetTypePrivateKey
+	contents := buf.Bytes()
+	privateKeyBytes := privateKeyBuf.Bytes()
+	if pk.IsSubkey {
+		ptype = packetTypePrivateSubkey
+	}
+	err = serializeHeader(w, ptype, len(contents)+len(privateKeyBytes)+2)
+	if err != nil {
+		return
+	}
+	_, err = w.Write(contents)
+	if err != nil {
+		return
+	}
+	_, err = w.Write(privateKeyBytes)
+	if err != nil {
+		return
+	}
+
+	checksum := mod64kHash(privateKeyBytes)
+	var checksumBytes [2]byte
+	checksumBytes[0] = byte(checksum >> 8)
+	checksumBytes[1] = byte(checksum)
+	_, err = w.Write(checksumBytes[:])
+
+	return
+}
+
+func serializeRSAPrivateKey(w io.Writer, priv *rsa.PrivateKey) error {
+	err := writeBig(w, priv.D)
+	if err != nil {
+		return err
+	}
+	err = writeBig(w, priv.Primes[1])
+	if err != nil {
+		return err
+	}
+	err = writeBig(w, priv.Primes[0])
+	if err != nil {
+		return err
+	}
+	return writeBig(w, priv.Precomputed.Qinv)
+}
+
+func serializeDSAPrivateKey(w io.Writer, priv *dsa.PrivateKey) error {
+	return writeBig(w, priv.X)
+}
+
+func serializeElGamalPrivateKey(w io.Writer, priv *elgamal.PrivateKey) error {
+	return writeBig(w, priv.X)
+}
+
+func serializeECDSAPrivateKey(w io.Writer, priv *ecdsa.PrivateKey) error {
+	return writeBig(w, priv.D)
+}
+
+// Decrypt decrypts an encrypted private key using a passphrase.
+func (pk *PrivateKey) Decrypt(passphrase []byte) error {
+	if !pk.Encrypted {
+		return nil
+	}
+
+	key := make([]byte, pk.cipher.KeySize())
+	pk.s2k(key, passphrase)
+	block := pk.cipher.new(key)
+	cfb := cipher.NewCFBDecrypter(block, pk.iv)
+
+	data := make([]byte, len(pk.encryptedData))
+	cfb.XORKeyStream(data, pk.encryptedData)
+
+	if pk.sha1Checksum {
+		if len(data) < sha1.Size {
+			return errors.StructuralError("truncated private key data")
+		}
+		h := sha1.New()
+		h.Write(data[:len(data)-sha1.Size])
+		sum := h.Sum(nil)
+		if !bytes.Equal(sum, data[len(data)-sha1.Size:]) {
+			return errors.StructuralError("private key checksum failure")
+		}
+		data = data[:len(data)-sha1.Size]
+	} else {
+		if len(data) < 2 {
+			return errors.StructuralError("truncated private key data")
+		}
+		var sum uint16
+		for i := 0; i < len(data)-2; i++ {
+			sum += uint16(data[i])
+		}
+		if data[len(data)-2] != uint8(sum>>8) ||
+			data[len(data)-1] != uint8(sum) {
+			return errors.StructuralError("private key checksum failure")
+		}
+		data = data[:len(data)-2]
+	}
+
+	return pk.parsePrivateKey(data)
+}
+
+func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) {
+	switch pk.PublicKey.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoRSAEncryptOnly:
+		return pk.parseRSAPrivateKey(data)
+	case PubKeyAlgoDSA:
+		return pk.parseDSAPrivateKey(data)
+	case PubKeyAlgoElGamal:
+		return pk.parseElGamalPrivateKey(data)
+	case PubKeyAlgoECDSA:
+		return pk.parseECDSAPrivateKey(data)
+	}
+	panic("impossible")
+}
+
+func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err error) {
+	rsaPub := pk.PublicKey.PublicKey.(*rsa.PublicKey)
+	rsaPriv := new(rsa.PrivateKey)
+	rsaPriv.PublicKey = *rsaPub
+
+	buf := bytes.NewBuffer(data)
+	d, _, err := readMPI(buf)
+	if err != nil {
+		return
+	}
+	p, _, err := readMPI(buf)
+	if err != nil {
+		return
+	}
+	q, _, err := readMPI(buf)
+	if err != nil {
+		return
+	}
+
+	rsaPriv.D = new(big.Int).SetBytes(d)
+	rsaPriv.Primes = make([]*big.Int, 2)
+	rsaPriv.Primes[0] = new(big.Int).SetBytes(p)
+	rsaPriv.Primes[1] = new(big.Int).SetBytes(q)
+	if err := rsaPriv.Validate(); err != nil {
+		return err
+	}
+	rsaPriv.Precompute()
+	pk.PrivateKey = rsaPriv
+	pk.Encrypted = false
+	pk.encryptedData = nil
+
+	return nil
+}
+
+func (pk *PrivateKey) parseDSAPrivateKey(data []byte) (err error) {
+	dsaPub := pk.PublicKey.PublicKey.(*dsa.PublicKey)
+	dsaPriv := new(dsa.PrivateKey)
+	dsaPriv.PublicKey = *dsaPub
+
+	buf := bytes.NewBuffer(data)
+	x, _, err := readMPI(buf)
+	if err != nil {
+		return
+	}
+
+	dsaPriv.X = new(big.Int).SetBytes(x)
+	pk.PrivateKey = dsaPriv
+	pk.Encrypted = false
+	pk.encryptedData = nil
+
+	return nil
+}
+
+func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err error) {
+	pub := pk.PublicKey.PublicKey.(*elgamal.PublicKey)
+	priv := new(elgamal.PrivateKey)
+	priv.PublicKey = *pub
+
+	buf := bytes.NewBuffer(data)
+	x, _, err := readMPI(buf)
+	if err != nil {
+		return
+	}
+
+	priv.X = new(big.Int).SetBytes(x)
+	pk.PrivateKey = priv
+	pk.Encrypted = false
+	pk.encryptedData = nil
+
+	return nil
+}
+
+func (pk *PrivateKey) parseECDSAPrivateKey(data []byte) (err error) {
+	ecdsaPub := pk.PublicKey.PublicKey.(*ecdsa.PublicKey)
+
+	buf := bytes.NewBuffer(data)
+	d, _, err := readMPI(buf)
+	if err != nil {
+		return
+	}
+
+	pk.PrivateKey = &ecdsa.PrivateKey{
+		PublicKey: *ecdsaPub,
+		D:         new(big.Int).SetBytes(d),
+	}
+	pk.Encrypted = false
+	pk.encryptedData = nil
+
+	return nil
+}

+ 126 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/private_key_test.go

@@ -0,0 +1,126 @@
+// Copyright 2011 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 packet
+
+import (
+	"bytes"
+	"crypto"
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rand"
+	"hash"
+	"testing"
+	"time"
+)
+
+var privateKeyTests = []struct {
+	privateKeyHex string
+	creationTime  time.Time
+}{
+	{
+		privKeyRSAHex,
+		time.Unix(0x4cc349a8, 0),
+	},
+	{
+		privKeyElGamalHex,
+		time.Unix(0x4df9ee1a, 0),
+	},
+}
+
+func TestPrivateKeyRead(t *testing.T) {
+	for i, test := range privateKeyTests {
+		packet, err := Read(readerFromHex(test.privateKeyHex))
+		if err != nil {
+			t.Errorf("#%d: failed to parse: %s", i, err)
+			continue
+		}
+
+		privKey := packet.(*PrivateKey)
+
+		if !privKey.Encrypted {
+			t.Errorf("#%d: private key isn't encrypted", i)
+			continue
+		}
+
+		err = privKey.Decrypt([]byte("wrong password"))
+		if err == nil {
+			t.Errorf("#%d: decrypted with incorrect key", i)
+			continue
+		}
+
+		err = privKey.Decrypt([]byte("testing"))
+		if err != nil {
+			t.Errorf("#%d: failed to decrypt: %s", i, err)
+			continue
+		}
+
+		if !privKey.CreationTime.Equal(test.creationTime) || privKey.Encrypted {
+			t.Errorf("#%d: bad result, got: %#v", i, privKey)
+		}
+	}
+}
+
+func populateHash(hashFunc crypto.Hash, msg []byte) (hash.Hash, error) {
+	h := hashFunc.New()
+	if _, err := h.Write(msg); err != nil {
+		return nil, err
+	}
+	return h, nil
+}
+
+func TestECDSAPrivateKey(t *testing.T) {
+	ecdsaPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	var buf bytes.Buffer
+	if err := NewECDSAPrivateKey(time.Now(), ecdsaPriv).Serialize(&buf); err != nil {
+		t.Fatal(err)
+	}
+
+	p, err := Read(&buf)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	priv, ok := p.(*PrivateKey)
+	if !ok {
+		t.Fatal("didn't parse private key")
+	}
+
+	sig := &Signature{
+		PubKeyAlgo: PubKeyAlgoECDSA,
+		Hash:       crypto.SHA256,
+	}
+	msg := []byte("Hello World!")
+
+	h, err := populateHash(sig.Hash, msg)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if err := sig.Sign(h, priv, nil); err != nil {
+		t.Fatal(err)
+	}
+
+	if h, err = populateHash(sig.Hash, msg); err != nil {
+		t.Fatal(err)
+	}
+	if err := priv.VerifySignature(h, sig); err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestIssue11505(t *testing.T) {
+	// parsing a rsa private key with p or q == 1 used to panic due to a divide by zero
+	_, _ = Read(readerFromHex("9c3004303030300100000011303030000000000000010130303030303030303030303030303030303030303030303030303030303030303030303030303030303030"))
+}
+
+// Generated with `gpg --export-secret-keys "Test Key 2"`
+const privKeyRSAHex = "9501fe044cc349a8010400b70ca0010e98c090008d45d1ee8f9113bd5861fd57b88bacb7c68658747663f1e1a3b5a98f32fda6472373c024b97359cd2efc88ff60f77751adfbf6af5e615e6a1408cfad8bf0cea30b0d5f53aa27ad59089ba9b15b7ebc2777a25d7b436144027e3bcd203909f147d0e332b240cf63d3395f5dfe0df0a6c04e8655af7eacdf0011010001fe0303024a252e7d475fd445607de39a265472aa74a9320ba2dac395faa687e9e0336aeb7e9a7397e511b5afd9dc84557c80ac0f3d4d7bfec5ae16f20d41c8c84a04552a33870b930420e230e179564f6d19bb153145e76c33ae993886c388832b0fa042ddda7f133924f3854481533e0ede31d51278c0519b29abc3bf53da673e13e3e1214b52413d179d7f66deee35cac8eacb060f78379d70ef4af8607e68131ff529439668fc39c9ce6dfef8a5ac234d234802cbfb749a26107db26406213ae5c06d4673253a3cbee1fcbae58d6ab77e38d6e2c0e7c6317c48e054edadb5a40d0d48acb44643d998139a8a66bb820be1f3f80185bc777d14b5954b60effe2448a036d565c6bc0b915fcea518acdd20ab07bc1529f561c58cd044f723109b93f6fd99f876ff891d64306b5d08f48bab59f38695e9109c4dec34013ba3153488ce070268381ba923ee1eb77125b36afcb4347ec3478c8f2735b06ef17351d872e577fa95d0c397c88c71b59629a36aec"
+
+// Generated by `gpg --export-secret-keys` followed by a manual extraction of
+// the ElGamal subkey from the packets.
+const privKeyElGamalHex = "9d0157044df9ee1a100400eb8e136a58ec39b582629cdadf830bc64e0a94ed8103ca8bb247b27b11b46d1d25297ef4bcc3071785ba0c0bedfe89eabc5287fcc0edf81ab5896c1c8e4b20d27d79813c7aede75320b33eaeeaa586edc00fd1036c10133e6ba0ff277245d0d59d04b2b3421b7244aca5f4a8d870c6f1c1fbff9e1c26699a860b9504f35ca1d700030503fd1ededd3b840795be6d9ccbe3c51ee42e2f39233c432b831ddd9c4e72b7025a819317e47bf94f9ee316d7273b05d5fcf2999c3a681f519b1234bbfa6d359b4752bd9c3f77d6b6456cde152464763414ca130f4e91d91041432f90620fec0e6d6b5116076c2985d5aeaae13be492b9b329efcaf7ee25120159a0a30cd976b42d7afe030302dae7eb80db744d4960c4df930d57e87fe81412eaace9f900e6c839817a614ddb75ba6603b9417c33ea7b6c93967dfa2bcff3fa3c74a5ce2c962db65b03aece14c96cbd0038fc"

+ 750 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/public_key.go

@@ -0,0 +1,750 @@
+// Copyright 2011 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 packet
+
+import (
+	"bytes"
+	"crypto"
+	"crypto/dsa"
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rsa"
+	"crypto/sha1"
+	_ "crypto/sha256"
+	_ "crypto/sha512"
+	"encoding/binary"
+	"fmt"
+	"hash"
+	"io"
+	"math/big"
+	"strconv"
+	"time"
+
+	"golang.org/x/crypto/openpgp/elgamal"
+	"golang.org/x/crypto/openpgp/errors"
+)
+
+var (
+	// NIST curve P-256
+	oidCurveP256 []byte = []byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}
+	// NIST curve P-384
+	oidCurveP384 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x22}
+	// NIST curve P-521
+	oidCurveP521 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x23}
+)
+
+const maxOIDLength = 8
+
+// ecdsaKey stores the algorithm-specific fields for ECDSA keys.
+// as defined in RFC 6637, Section 9.
+type ecdsaKey struct {
+	// oid contains the OID byte sequence identifying the elliptic curve used
+	oid []byte
+	// p contains the elliptic curve point that represents the public key
+	p parsedMPI
+}
+
+// parseOID reads the OID for the curve as defined in RFC 6637, Section 9.
+func parseOID(r io.Reader) (oid []byte, err error) {
+	buf := make([]byte, maxOIDLength)
+	if _, err = readFull(r, buf[:1]); err != nil {
+		return
+	}
+	oidLen := buf[0]
+	if int(oidLen) > len(buf) {
+		err = errors.UnsupportedError("invalid oid length: " + strconv.Itoa(int(oidLen)))
+		return
+	}
+	oid = buf[:oidLen]
+	_, err = readFull(r, oid)
+	return
+}
+
+func (f *ecdsaKey) parse(r io.Reader) (err error) {
+	if f.oid, err = parseOID(r); err != nil {
+		return err
+	}
+	f.p.bytes, f.p.bitLength, err = readMPI(r)
+	return
+}
+
+func (f *ecdsaKey) serialize(w io.Writer) (err error) {
+	buf := make([]byte, maxOIDLength+1)
+	buf[0] = byte(len(f.oid))
+	copy(buf[1:], f.oid)
+	if _, err = w.Write(buf[:len(f.oid)+1]); err != nil {
+		return
+	}
+	return writeMPIs(w, f.p)
+}
+
+func (f *ecdsaKey) newECDSA() (*ecdsa.PublicKey, error) {
+	var c elliptic.Curve
+	if bytes.Equal(f.oid, oidCurveP256) {
+		c = elliptic.P256()
+	} else if bytes.Equal(f.oid, oidCurveP384) {
+		c = elliptic.P384()
+	} else if bytes.Equal(f.oid, oidCurveP521) {
+		c = elliptic.P521()
+	} else {
+		return nil, errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", f.oid))
+	}
+	x, y := elliptic.Unmarshal(c, f.p.bytes)
+	if x == nil {
+		return nil, errors.UnsupportedError("failed to parse EC point")
+	}
+	return &ecdsa.PublicKey{Curve: c, X: x, Y: y}, nil
+}
+
+func (f *ecdsaKey) byteLen() int {
+	return 1 + len(f.oid) + 2 + len(f.p.bytes)
+}
+
+type kdfHashFunction byte
+type kdfAlgorithm byte
+
+// ecdhKdf stores key derivation function parameters
+// used for ECDH encryption. See RFC 6637, Section 9.
+type ecdhKdf struct {
+	KdfHash kdfHashFunction
+	KdfAlgo kdfAlgorithm
+}
+
+func (f *ecdhKdf) parse(r io.Reader) (err error) {
+	buf := make([]byte, 1)
+	if _, err = readFull(r, buf); err != nil {
+		return
+	}
+	kdfLen := int(buf[0])
+	if kdfLen < 3 {
+		return errors.UnsupportedError("Unsupported ECDH KDF length: " + strconv.Itoa(kdfLen))
+	}
+	buf = make([]byte, kdfLen)
+	if _, err = readFull(r, buf); err != nil {
+		return
+	}
+	reserved := int(buf[0])
+	f.KdfHash = kdfHashFunction(buf[1])
+	f.KdfAlgo = kdfAlgorithm(buf[2])
+	if reserved != 0x01 {
+		return errors.UnsupportedError("Unsupported KDF reserved field: " + strconv.Itoa(reserved))
+	}
+	return
+}
+
+func (f *ecdhKdf) serialize(w io.Writer) (err error) {
+	buf := make([]byte, 4)
+	// See RFC 6637, Section 9, Algorithm-Specific Fields for ECDH keys.
+	buf[0] = byte(0x03) // Length of the following fields
+	buf[1] = byte(0x01) // Reserved for future extensions, must be 1 for now
+	buf[2] = byte(f.KdfHash)
+	buf[3] = byte(f.KdfAlgo)
+	_, err = w.Write(buf[:])
+	return
+}
+
+func (f *ecdhKdf) byteLen() int {
+	return 4
+}
+
+// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2.
+type PublicKey struct {
+	CreationTime time.Time
+	PubKeyAlgo   PublicKeyAlgorithm
+	PublicKey    interface{} // *rsa.PublicKey, *dsa.PublicKey or *ecdsa.PublicKey
+	Fingerprint  [20]byte
+	KeyId        uint64
+	IsSubkey     bool
+
+	n, e, p, q, g, y parsedMPI
+
+	// RFC 6637 fields
+	ec   *ecdsaKey
+	ecdh *ecdhKdf
+}
+
+// signingKey provides a convenient abstraction over signature verification
+// for v3 and v4 public keys.
+type signingKey interface {
+	SerializeSignaturePrefix(io.Writer)
+	serializeWithoutHeaders(io.Writer) error
+}
+
+func fromBig(n *big.Int) parsedMPI {
+	return parsedMPI{
+		bytes:     n.Bytes(),
+		bitLength: uint16(n.BitLen()),
+	}
+}
+
+// NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey.
+func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey {
+	pk := &PublicKey{
+		CreationTime: creationTime,
+		PubKeyAlgo:   PubKeyAlgoRSA,
+		PublicKey:    pub,
+		n:            fromBig(pub.N),
+		e:            fromBig(big.NewInt(int64(pub.E))),
+	}
+
+	pk.setFingerPrintAndKeyId()
+	return pk
+}
+
+// NewDSAPublicKey returns a PublicKey that wraps the given dsa.PublicKey.
+func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey {
+	pk := &PublicKey{
+		CreationTime: creationTime,
+		PubKeyAlgo:   PubKeyAlgoDSA,
+		PublicKey:    pub,
+		p:            fromBig(pub.P),
+		q:            fromBig(pub.Q),
+		g:            fromBig(pub.G),
+		y:            fromBig(pub.Y),
+	}
+
+	pk.setFingerPrintAndKeyId()
+	return pk
+}
+
+// NewElGamalPublicKey returns a PublicKey that wraps the given elgamal.PublicKey.
+func NewElGamalPublicKey(creationTime time.Time, pub *elgamal.PublicKey) *PublicKey {
+	pk := &PublicKey{
+		CreationTime: creationTime,
+		PubKeyAlgo:   PubKeyAlgoElGamal,
+		PublicKey:    pub,
+		p:            fromBig(pub.P),
+		g:            fromBig(pub.G),
+		y:            fromBig(pub.Y),
+	}
+
+	pk.setFingerPrintAndKeyId()
+	return pk
+}
+
+func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey {
+	pk := &PublicKey{
+		CreationTime: creationTime,
+		PubKeyAlgo:   PubKeyAlgoECDSA,
+		PublicKey:    pub,
+		ec:           new(ecdsaKey),
+	}
+
+	switch pub.Curve {
+	case elliptic.P256():
+		pk.ec.oid = oidCurveP256
+	case elliptic.P384():
+		pk.ec.oid = oidCurveP384
+	case elliptic.P521():
+		pk.ec.oid = oidCurveP521
+	default:
+		panic("unknown elliptic curve")
+	}
+
+	pk.ec.p.bytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y)
+	pk.ec.p.bitLength = uint16(8 * len(pk.ec.p.bytes))
+
+	pk.setFingerPrintAndKeyId()
+	return pk
+}
+
+func (pk *PublicKey) parse(r io.Reader) (err error) {
+	// RFC 4880, section 5.5.2
+	var buf [6]byte
+	_, err = readFull(r, buf[:])
+	if err != nil {
+		return
+	}
+	if buf[0] != 4 {
+		return errors.UnsupportedError("public key version")
+	}
+	pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0)
+	pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5])
+	switch pk.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+		err = pk.parseRSA(r)
+	case PubKeyAlgoDSA:
+		err = pk.parseDSA(r)
+	case PubKeyAlgoElGamal:
+		err = pk.parseElGamal(r)
+	case PubKeyAlgoECDSA:
+		pk.ec = new(ecdsaKey)
+		if err = pk.ec.parse(r); err != nil {
+			return err
+		}
+		pk.PublicKey, err = pk.ec.newECDSA()
+	case PubKeyAlgoECDH:
+		pk.ec = new(ecdsaKey)
+		if err = pk.ec.parse(r); err != nil {
+			return
+		}
+		pk.ecdh = new(ecdhKdf)
+		if err = pk.ecdh.parse(r); err != nil {
+			return
+		}
+		// The ECDH key is stored in an ecdsa.PublicKey for convenience.
+		pk.PublicKey, err = pk.ec.newECDSA()
+	default:
+		err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
+	}
+	if err != nil {
+		return
+	}
+
+	pk.setFingerPrintAndKeyId()
+	return
+}
+
+func (pk *PublicKey) setFingerPrintAndKeyId() {
+	// RFC 4880, section 12.2
+	fingerPrint := sha1.New()
+	pk.SerializeSignaturePrefix(fingerPrint)
+	pk.serializeWithoutHeaders(fingerPrint)
+	copy(pk.Fingerprint[:], fingerPrint.Sum(nil))
+	pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20])
+}
+
+// parseRSA parses RSA public key material from the given Reader. See RFC 4880,
+// section 5.5.2.
+func (pk *PublicKey) parseRSA(r io.Reader) (err error) {
+	pk.n.bytes, pk.n.bitLength, err = readMPI(r)
+	if err != nil {
+		return
+	}
+	pk.e.bytes, pk.e.bitLength, err = readMPI(r)
+	if err != nil {
+		return
+	}
+
+	if len(pk.e.bytes) > 3 {
+		err = errors.UnsupportedError("large public exponent")
+		return
+	}
+	rsa := &rsa.PublicKey{
+		N: new(big.Int).SetBytes(pk.n.bytes),
+		E: 0,
+	}
+	for i := 0; i < len(pk.e.bytes); i++ {
+		rsa.E <<= 8
+		rsa.E |= int(pk.e.bytes[i])
+	}
+	pk.PublicKey = rsa
+	return
+}
+
+// parseDSA parses DSA public key material from the given Reader. See RFC 4880,
+// section 5.5.2.
+func (pk *PublicKey) parseDSA(r io.Reader) (err error) {
+	pk.p.bytes, pk.p.bitLength, err = readMPI(r)
+	if err != nil {
+		return
+	}
+	pk.q.bytes, pk.q.bitLength, err = readMPI(r)
+	if err != nil {
+		return
+	}
+	pk.g.bytes, pk.g.bitLength, err = readMPI(r)
+	if err != nil {
+		return
+	}
+	pk.y.bytes, pk.y.bitLength, err = readMPI(r)
+	if err != nil {
+		return
+	}
+
+	dsa := new(dsa.PublicKey)
+	dsa.P = new(big.Int).SetBytes(pk.p.bytes)
+	dsa.Q = new(big.Int).SetBytes(pk.q.bytes)
+	dsa.G = new(big.Int).SetBytes(pk.g.bytes)
+	dsa.Y = new(big.Int).SetBytes(pk.y.bytes)
+	pk.PublicKey = dsa
+	return
+}
+
+// parseElGamal parses ElGamal public key material from the given Reader. See
+// RFC 4880, section 5.5.2.
+func (pk *PublicKey) parseElGamal(r io.Reader) (err error) {
+	pk.p.bytes, pk.p.bitLength, err = readMPI(r)
+	if err != nil {
+		return
+	}
+	pk.g.bytes, pk.g.bitLength, err = readMPI(r)
+	if err != nil {
+		return
+	}
+	pk.y.bytes, pk.y.bitLength, err = readMPI(r)
+	if err != nil {
+		return
+	}
+
+	elgamal := new(elgamal.PublicKey)
+	elgamal.P = new(big.Int).SetBytes(pk.p.bytes)
+	elgamal.G = new(big.Int).SetBytes(pk.g.bytes)
+	elgamal.Y = new(big.Int).SetBytes(pk.y.bytes)
+	pk.PublicKey = elgamal
+	return
+}
+
+// SerializeSignaturePrefix writes the prefix for this public key to the given Writer.
+// The prefix is used when calculating a signature over this public key. See
+// RFC 4880, section 5.2.4.
+func (pk *PublicKey) SerializeSignaturePrefix(h io.Writer) {
+	var pLength uint16
+	switch pk.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+		pLength += 2 + uint16(len(pk.n.bytes))
+		pLength += 2 + uint16(len(pk.e.bytes))
+	case PubKeyAlgoDSA:
+		pLength += 2 + uint16(len(pk.p.bytes))
+		pLength += 2 + uint16(len(pk.q.bytes))
+		pLength += 2 + uint16(len(pk.g.bytes))
+		pLength += 2 + uint16(len(pk.y.bytes))
+	case PubKeyAlgoElGamal:
+		pLength += 2 + uint16(len(pk.p.bytes))
+		pLength += 2 + uint16(len(pk.g.bytes))
+		pLength += 2 + uint16(len(pk.y.bytes))
+	case PubKeyAlgoECDSA:
+		pLength += uint16(pk.ec.byteLen())
+	case PubKeyAlgoECDH:
+		pLength += uint16(pk.ec.byteLen())
+		pLength += uint16(pk.ecdh.byteLen())
+	default:
+		panic("unknown public key algorithm")
+	}
+	pLength += 6
+	h.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)})
+	return
+}
+
+func (pk *PublicKey) Serialize(w io.Writer) (err error) {
+	length := 6 // 6 byte header
+
+	switch pk.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+		length += 2 + len(pk.n.bytes)
+		length += 2 + len(pk.e.bytes)
+	case PubKeyAlgoDSA:
+		length += 2 + len(pk.p.bytes)
+		length += 2 + len(pk.q.bytes)
+		length += 2 + len(pk.g.bytes)
+		length += 2 + len(pk.y.bytes)
+	case PubKeyAlgoElGamal:
+		length += 2 + len(pk.p.bytes)
+		length += 2 + len(pk.g.bytes)
+		length += 2 + len(pk.y.bytes)
+	case PubKeyAlgoECDSA:
+		length += pk.ec.byteLen()
+	case PubKeyAlgoECDH:
+		length += pk.ec.byteLen()
+		length += pk.ecdh.byteLen()
+	default:
+		panic("unknown public key algorithm")
+	}
+
+	packetType := packetTypePublicKey
+	if pk.IsSubkey {
+		packetType = packetTypePublicSubkey
+	}
+	err = serializeHeader(w, packetType, length)
+	if err != nil {
+		return
+	}
+	return pk.serializeWithoutHeaders(w)
+}
+
+// serializeWithoutHeaders marshals the PublicKey to w in the form of an
+// OpenPGP public key packet, not including the packet header.
+func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) {
+	var buf [6]byte
+	buf[0] = 4
+	t := uint32(pk.CreationTime.Unix())
+	buf[1] = byte(t >> 24)
+	buf[2] = byte(t >> 16)
+	buf[3] = byte(t >> 8)
+	buf[4] = byte(t)
+	buf[5] = byte(pk.PubKeyAlgo)
+
+	_, err = w.Write(buf[:])
+	if err != nil {
+		return
+	}
+
+	switch pk.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+		return writeMPIs(w, pk.n, pk.e)
+	case PubKeyAlgoDSA:
+		return writeMPIs(w, pk.p, pk.q, pk.g, pk.y)
+	case PubKeyAlgoElGamal:
+		return writeMPIs(w, pk.p, pk.g, pk.y)
+	case PubKeyAlgoECDSA:
+		return pk.ec.serialize(w)
+	case PubKeyAlgoECDH:
+		if err = pk.ec.serialize(w); err != nil {
+			return
+		}
+		return pk.ecdh.serialize(w)
+	}
+	return errors.InvalidArgumentError("bad public-key algorithm")
+}
+
+// CanSign returns true iff this public key can generate signatures
+func (pk *PublicKey) CanSign() bool {
+	return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal
+}
+
+// VerifySignature returns nil iff sig is a valid signature, made by this
+// public key, of the data hashed into signed. signed is mutated by this call.
+func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) {
+	if !pk.CanSign() {
+		return errors.InvalidArgumentError("public key cannot generate signatures")
+	}
+
+	signed.Write(sig.HashSuffix)
+	hashBytes := signed.Sum(nil)
+
+	if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
+		return errors.SignatureError("hash tag doesn't match")
+	}
+
+	if pk.PubKeyAlgo != sig.PubKeyAlgo {
+		return errors.InvalidArgumentError("public key and signature use different algorithms")
+	}
+
+	switch pk.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
+		rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey)
+		err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes)
+		if err != nil {
+			return errors.SignatureError("RSA verification failure")
+		}
+		return nil
+	case PubKeyAlgoDSA:
+		dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey)
+		// Need to truncate hashBytes to match FIPS 186-3 section 4.6.
+		subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8
+		if len(hashBytes) > subgroupSize {
+			hashBytes = hashBytes[:subgroupSize]
+		}
+		if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) {
+			return errors.SignatureError("DSA verification failure")
+		}
+		return nil
+	case PubKeyAlgoECDSA:
+		ecdsaPublicKey := pk.PublicKey.(*ecdsa.PublicKey)
+		if !ecdsa.Verify(ecdsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.ECDSASigR.bytes), new(big.Int).SetBytes(sig.ECDSASigS.bytes)) {
+			return errors.SignatureError("ECDSA verification failure")
+		}
+		return nil
+	default:
+		return errors.SignatureError("Unsupported public key algorithm used in signature")
+	}
+	panic("unreachable")
+}
+
+// VerifySignatureV3 returns nil iff sig is a valid signature, made by this
+// public key, of the data hashed into signed. signed is mutated by this call.
+func (pk *PublicKey) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) {
+	if !pk.CanSign() {
+		return errors.InvalidArgumentError("public key cannot generate signatures")
+	}
+
+	suffix := make([]byte, 5)
+	suffix[0] = byte(sig.SigType)
+	binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix()))
+	signed.Write(suffix)
+	hashBytes := signed.Sum(nil)
+
+	if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
+		return errors.SignatureError("hash tag doesn't match")
+	}
+
+	if pk.PubKeyAlgo != sig.PubKeyAlgo {
+		return errors.InvalidArgumentError("public key and signature use different algorithms")
+	}
+
+	switch pk.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
+		rsaPublicKey := pk.PublicKey.(*rsa.PublicKey)
+		if err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil {
+			return errors.SignatureError("RSA verification failure")
+		}
+		return
+	case PubKeyAlgoDSA:
+		dsaPublicKey := pk.PublicKey.(*dsa.PublicKey)
+		// Need to truncate hashBytes to match FIPS 186-3 section 4.6.
+		subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8
+		if len(hashBytes) > subgroupSize {
+			hashBytes = hashBytes[:subgroupSize]
+		}
+		if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) {
+			return errors.SignatureError("DSA verification failure")
+		}
+		return nil
+	default:
+		panic("shouldn't happen")
+	}
+	panic("unreachable")
+}
+
+// keySignatureHash returns a Hash of the message that needs to be signed for
+// pk to assert a subkey relationship to signed.
+func keySignatureHash(pk, signed signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
+	if !hashFunc.Available() {
+		return nil, errors.UnsupportedError("hash function")
+	}
+	h = hashFunc.New()
+
+	// RFC 4880, section 5.2.4
+	pk.SerializeSignaturePrefix(h)
+	pk.serializeWithoutHeaders(h)
+	signed.SerializeSignaturePrefix(h)
+	signed.serializeWithoutHeaders(h)
+	return
+}
+
+// VerifyKeySignature returns nil iff sig is a valid signature, made by this
+// public key, of signed.
+func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) error {
+	h, err := keySignatureHash(pk, signed, sig.Hash)
+	if err != nil {
+		return err
+	}
+	if err = pk.VerifySignature(h, sig); err != nil {
+		return err
+	}
+
+	if sig.FlagSign {
+		// Signing subkeys must be cross-signed. See
+		// https://www.gnupg.org/faq/subkey-cross-certify.html.
+		if sig.EmbeddedSignature == nil {
+			return errors.StructuralError("signing subkey is missing cross-signature")
+		}
+		// Verify the cross-signature. This is calculated over the same
+		// data as the main signature, so we cannot just recursively
+		// call signed.VerifyKeySignature(...)
+		if h, err = keySignatureHash(pk, signed, sig.EmbeddedSignature.Hash); err != nil {
+			return errors.StructuralError("error while hashing for cross-signature: " + err.Error())
+		}
+		if err := signed.VerifySignature(h, sig.EmbeddedSignature); err != nil {
+			return errors.StructuralError("error while verifying cross-signature: " + err.Error())
+		}
+	}
+
+	return nil
+}
+
+func keyRevocationHash(pk signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
+	if !hashFunc.Available() {
+		return nil, errors.UnsupportedError("hash function")
+	}
+	h = hashFunc.New()
+
+	// RFC 4880, section 5.2.4
+	pk.SerializeSignaturePrefix(h)
+	pk.serializeWithoutHeaders(h)
+
+	return
+}
+
+// VerifyRevocationSignature returns nil iff sig is a valid signature, made by this
+// public key.
+func (pk *PublicKey) VerifyRevocationSignature(sig *Signature) (err error) {
+	h, err := keyRevocationHash(pk, sig.Hash)
+	if err != nil {
+		return err
+	}
+	return pk.VerifySignature(h, sig)
+}
+
+// userIdSignatureHash returns a Hash of the message that needs to be signed
+// to assert that pk is a valid key for id.
+func userIdSignatureHash(id string, pk *PublicKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
+	if !hashFunc.Available() {
+		return nil, errors.UnsupportedError("hash function")
+	}
+	h = hashFunc.New()
+
+	// RFC 4880, section 5.2.4
+	pk.SerializeSignaturePrefix(h)
+	pk.serializeWithoutHeaders(h)
+
+	var buf [5]byte
+	buf[0] = 0xb4
+	buf[1] = byte(len(id) >> 24)
+	buf[2] = byte(len(id) >> 16)
+	buf[3] = byte(len(id) >> 8)
+	buf[4] = byte(len(id))
+	h.Write(buf[:])
+	h.Write([]byte(id))
+
+	return
+}
+
+// VerifyUserIdSignature returns nil iff sig is a valid signature, made by this
+// public key, that id is the identity of pub.
+func (pk *PublicKey) VerifyUserIdSignature(id string, pub *PublicKey, sig *Signature) (err error) {
+	h, err := userIdSignatureHash(id, pub, sig.Hash)
+	if err != nil {
+		return err
+	}
+	return pk.VerifySignature(h, sig)
+}
+
+// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this
+// public key, that id is the identity of pub.
+func (pk *PublicKey) VerifyUserIdSignatureV3(id string, pub *PublicKey, sig *SignatureV3) (err error) {
+	h, err := userIdSignatureV3Hash(id, pub, sig.Hash)
+	if err != nil {
+		return err
+	}
+	return pk.VerifySignatureV3(h, sig)
+}
+
+// KeyIdString returns the public key's fingerprint in capital hex
+// (e.g. "6C7EE1B8621CC013").
+func (pk *PublicKey) KeyIdString() string {
+	return fmt.Sprintf("%X", pk.Fingerprint[12:20])
+}
+
+// KeyIdShortString returns the short form of public key's fingerprint
+// in capital hex, as shown by gpg --list-keys (e.g. "621CC013").
+func (pk *PublicKey) KeyIdShortString() string {
+	return fmt.Sprintf("%X", pk.Fingerprint[16:20])
+}
+
+// A parsedMPI is used to store the contents of a big integer, along with the
+// bit length that was specified in the original input. This allows the MPI to
+// be reserialized exactly.
+type parsedMPI struct {
+	bytes     []byte
+	bitLength uint16
+}
+
+// writeMPIs is a utility function for serializing several big integers to the
+// given Writer.
+func writeMPIs(w io.Writer, mpis ...parsedMPI) (err error) {
+	for _, mpi := range mpis {
+		err = writeMPI(w, mpi.bitLength, mpi.bytes)
+		if err != nil {
+			return
+		}
+	}
+	return
+}
+
+// BitLength returns the bit length for the given public key.
+func (pk *PublicKey) BitLength() (bitLength uint16, err error) {
+	switch pk.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+		bitLength = pk.n.bitLength
+	case PubKeyAlgoDSA:
+		bitLength = pk.p.bitLength
+	case PubKeyAlgoElGamal:
+		bitLength = pk.p.bitLength
+	default:
+		err = errors.InvalidArgumentError("bad public-key algorithm")
+	}
+	return
+}

+ 202 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/public_key_test.go

@@ -0,0 +1,202 @@
+// Copyright 2011 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 packet
+
+import (
+	"bytes"
+	"encoding/hex"
+	"testing"
+	"time"
+)
+
+var pubKeyTests = []struct {
+	hexData        string
+	hexFingerprint string
+	creationTime   time.Time
+	pubKeyAlgo     PublicKeyAlgorithm
+	keyId          uint64
+	keyIdString    string
+	keyIdShort     string
+}{
+	{rsaPkDataHex, rsaFingerprintHex, time.Unix(0x4d3c5c10, 0), PubKeyAlgoRSA, 0xa34d7e18c20c31bb, "A34D7E18C20C31BB", "C20C31BB"},
+	{dsaPkDataHex, dsaFingerprintHex, time.Unix(0x4d432f89, 0), PubKeyAlgoDSA, 0x8e8fbe54062f19ed, "8E8FBE54062F19ED", "062F19ED"},
+	{ecdsaPkDataHex, ecdsaFingerprintHex, time.Unix(0x5071c294, 0), PubKeyAlgoECDSA, 0x43fe956c542ca00b, "43FE956C542CA00B", "542CA00B"},
+}
+
+func TestPublicKeyRead(t *testing.T) {
+	for i, test := range pubKeyTests {
+		packet, err := Read(readerFromHex(test.hexData))
+		if err != nil {
+			t.Errorf("#%d: Read error: %s", i, err)
+			continue
+		}
+		pk, ok := packet.(*PublicKey)
+		if !ok {
+			t.Errorf("#%d: failed to parse, got: %#v", i, packet)
+			continue
+		}
+		if pk.PubKeyAlgo != test.pubKeyAlgo {
+			t.Errorf("#%d: bad public key algorithm got:%x want:%x", i, pk.PubKeyAlgo, test.pubKeyAlgo)
+		}
+		if !pk.CreationTime.Equal(test.creationTime) {
+			t.Errorf("#%d: bad creation time got:%v want:%v", i, pk.CreationTime, test.creationTime)
+		}
+		expectedFingerprint, _ := hex.DecodeString(test.hexFingerprint)
+		if !bytes.Equal(expectedFingerprint, pk.Fingerprint[:]) {
+			t.Errorf("#%d: bad fingerprint got:%x want:%x", i, pk.Fingerprint[:], expectedFingerprint)
+		}
+		if pk.KeyId != test.keyId {
+			t.Errorf("#%d: bad keyid got:%x want:%x", i, pk.KeyId, test.keyId)
+		}
+		if g, e := pk.KeyIdString(), test.keyIdString; g != e {
+			t.Errorf("#%d: bad KeyIdString got:%q want:%q", i, g, e)
+		}
+		if g, e := pk.KeyIdShortString(), test.keyIdShort; g != e {
+			t.Errorf("#%d: bad KeyIdShortString got:%q want:%q", i, g, e)
+		}
+	}
+}
+
+func TestPublicKeySerialize(t *testing.T) {
+	for i, test := range pubKeyTests {
+		packet, err := Read(readerFromHex(test.hexData))
+		if err != nil {
+			t.Errorf("#%d: Read error: %s", i, err)
+			continue
+		}
+		pk, ok := packet.(*PublicKey)
+		if !ok {
+			t.Errorf("#%d: failed to parse, got: %#v", i, packet)
+			continue
+		}
+		serializeBuf := bytes.NewBuffer(nil)
+		err = pk.Serialize(serializeBuf)
+		if err != nil {
+			t.Errorf("#%d: failed to serialize: %s", i, err)
+			continue
+		}
+
+		packet, err = Read(serializeBuf)
+		if err != nil {
+			t.Errorf("#%d: Read error (from serialized data): %s", i, err)
+			continue
+		}
+		pk, ok = packet.(*PublicKey)
+		if !ok {
+			t.Errorf("#%d: failed to parse serialized data, got: %#v", i, packet)
+			continue
+		}
+	}
+}
+
+func TestEcc384Serialize(t *testing.T) {
+	r := readerFromHex(ecc384PubHex)
+	var w bytes.Buffer
+	for i := 0; i < 2; i++ {
+		// Public key
+		p, err := Read(r)
+		if err != nil {
+			t.Error(err)
+		}
+		pubkey := p.(*PublicKey)
+		if !bytes.Equal(pubkey.ec.oid, []byte{0x2b, 0x81, 0x04, 0x00, 0x22}) {
+			t.Errorf("Unexpected pubkey OID: %x", pubkey.ec.oid)
+		}
+		if !bytes.Equal(pubkey.ec.p.bytes[:5], []byte{0x04, 0xf6, 0xb8, 0xc5, 0xac}) {
+			t.Errorf("Unexpected pubkey P[:5]: %x", pubkey.ec.p.bytes)
+		}
+		if pubkey.KeyId != 0x098033880F54719F {
+			t.Errorf("Unexpected pubkey ID: %x", pubkey.KeyId)
+		}
+		err = pubkey.Serialize(&w)
+		if err != nil {
+			t.Error(err)
+		}
+		// User ID
+		p, err = Read(r)
+		if err != nil {
+			t.Error(err)
+		}
+		uid := p.(*UserId)
+		if uid.Id != "ec_dsa_dh_384 <[email protected]>" {
+			t.Error("Unexpected UID:", uid.Id)
+		}
+		err = uid.Serialize(&w)
+		if err != nil {
+			t.Error(err)
+		}
+		// User ID Sig
+		p, err = Read(r)
+		if err != nil {
+			t.Error(err)
+		}
+		uidSig := p.(*Signature)
+		err = pubkey.VerifyUserIdSignature(uid.Id, pubkey, uidSig)
+		if err != nil {
+			t.Error(err, ": UID")
+		}
+		err = uidSig.Serialize(&w)
+		if err != nil {
+			t.Error(err)
+		}
+		// Subkey
+		p, err = Read(r)
+		if err != nil {
+			t.Error(err)
+		}
+		subkey := p.(*PublicKey)
+		if !bytes.Equal(subkey.ec.oid, []byte{0x2b, 0x81, 0x04, 0x00, 0x22}) {
+			t.Errorf("Unexpected subkey OID: %x", subkey.ec.oid)
+		}
+		if !bytes.Equal(subkey.ec.p.bytes[:5], []byte{0x04, 0x2f, 0xaa, 0x84, 0x02}) {
+			t.Errorf("Unexpected subkey P[:5]: %x", subkey.ec.p.bytes)
+		}
+		if subkey.ecdh.KdfHash != 0x09 {
+			t.Error("Expected KDF hash function SHA384 (0x09), got", subkey.ecdh.KdfHash)
+		}
+		if subkey.ecdh.KdfAlgo != 0x09 {
+			t.Error("Expected KDF symmetric alg AES256 (0x09), got", subkey.ecdh.KdfAlgo)
+		}
+		if subkey.KeyId != 0xAA8B938F9A201946 {
+			t.Errorf("Unexpected subkey ID: %x", subkey.KeyId)
+		}
+		err = subkey.Serialize(&w)
+		if err != nil {
+			t.Error(err)
+		}
+		// Subkey Sig
+		p, err = Read(r)
+		if err != nil {
+			t.Error(err)
+		}
+		subkeySig := p.(*Signature)
+		err = pubkey.VerifyKeySignature(subkey, subkeySig)
+		if err != nil {
+			t.Error(err)
+		}
+		err = subkeySig.Serialize(&w)
+		if err != nil {
+			t.Error(err)
+		}
+		// Now read back what we've written again
+		r = bytes.NewBuffer(w.Bytes())
+		w.Reset()
+	}
+}
+
+const rsaFingerprintHex = "5fb74b1d03b1e3cb31bc2f8aa34d7e18c20c31bb"
+
+const rsaPkDataHex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001"
+
+const dsaFingerprintHex = "eece4c094db002103714c63c8e8fbe54062f19ed"
+
+const dsaPkDataHex = "9901a2044d432f89110400cd581334f0d7a1e1bdc8b9d6d8c0baf68793632735d2bb0903224cbaa1dfbf35a60ee7a13b92643421e1eb41aa8d79bea19a115a677f6b8ba3c7818ce53a6c2a24a1608bd8b8d6e55c5090cbde09dd26e356267465ae25e69ec8bdd57c7bbb2623e4d73336f73a0a9098f7f16da2e25252130fd694c0e8070c55a812a423ae7f00a0ebf50e70c2f19c3520a551bd4b08d30f23530d3d03ff7d0bf4a53a64a09dc5e6e6e35854b7d70c882b0c60293401958b1bd9e40abec3ea05ba87cf64899299d4bd6aa7f459c201d3fbbd6c82004bdc5e8a9eb8082d12054cc90fa9d4ec251a843236a588bf49552441817436c4f43326966fe85447d4e6d0acf8fa1ef0f014730770603ad7634c3088dc52501c237328417c31c89ed70400b2f1a98b0bf42f11fefc430704bebbaa41d9f355600c3facee1e490f64208e0e094ea55e3a598a219a58500bf78ac677b670a14f4e47e9cf8eab4f368cc1ddcaa18cc59309d4cc62dd4f680e73e6cc3e1ce87a84d0925efbcb26c575c093fc42eecf45135fabf6403a25c2016e1774c0484e440a18319072c617cc97ac0a3bb0"
+
+const ecdsaFingerprintHex = "9892270b38b8980b05c8d56d43fe956c542ca00b"
+
+const ecdsaPkDataHex = "9893045071c29413052b8104002304230401f4867769cedfa52c325018896245443968e52e51d0c2df8d939949cb5b330f2921711fbee1c9b9dddb95d15cb0255e99badeddda7cc23d9ddcaacbc290969b9f24019375d61c2e4e3b36953a28d8b2bc95f78c3f1d592fb24499be348656a7b17e3963187b4361afe497bc5f9f81213f04069f8e1fb9e6a6290ae295ca1a92b894396cb4"
+
+// Source: https://sites.google.com/site/brainhub/pgpecckeys#TOC-ECC-NIST-P-384-key
+const ecc384PubHex = `99006f044d53059213052b81040022030304f6b8c5aced5b84ef9f4a209db2e4a9dfb70d28cb8c10ecd57674a9fa5a67389942b62d5e51367df4c7bfd3f8e500feecf07ed265a621a8ebbbe53e947ec78c677eba143bd1533c2b350e1c29f82313e1e1108eba063be1e64b10e6950e799c2db42465635f6473615f64685f333834203c6f70656e70677040627261696e6875622e6f72673e8900cb04101309005305024d530592301480000000002000077072656665727265642d656d61696c2d656e636f64696e67407067702e636f6d7067706d696d65040b090807021901051b03000000021602051e010000000415090a08000a0910098033880f54719fca2b0180aa37350968bd5f115afd8ce7bc7b103822152dbff06d0afcda835329510905b98cb469ba208faab87c7412b799e7b633017f58364ea480e8a1a3f253a0c5f22c446e8be9a9fce6210136ee30811abbd49139de28b5bdf8dc36d06ae748579e9ff503b90073044d53059212052b810400220303042faa84024a20b6735c4897efa5bfb41bf85b7eefeab5ca0cb9ffc8ea04a46acb25534a577694f9e25340a4ab5223a9dd1eda530c8aa2e6718db10d7e672558c7736fe09369ea5739a2a3554bf16d41faa50562f11c6d39bbd5dffb6b9a9ec9180301090989008404181309000c05024d530592051b0c000000000a0910098033880f54719f80970180eee7a6d8fcee41ee4f9289df17f9bcf9d955dca25c583b94336f3a2b2d4986dc5cf417b8d2dc86f741a9e1a6d236c0e3017d1c76575458a0cfb93ae8a2b274fcc65ceecd7a91eec83656ba13219969f06945b48c56bd04152c3a0553c5f2f4bd1267`

+ 280 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/public_key_v3.go

@@ -0,0 +1,280 @@
+// Copyright 2013 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 packet
+
+import (
+	"crypto"
+	"crypto/md5"
+	"crypto/rsa"
+	"encoding/binary"
+	"fmt"
+	"hash"
+	"io"
+	"math/big"
+	"strconv"
+	"time"
+
+	"golang.org/x/crypto/openpgp/errors"
+)
+
+// PublicKeyV3 represents older, version 3 public keys. These keys are less secure and
+// should not be used for signing or encrypting. They are supported here only for
+// parsing version 3 key material and validating signatures.
+// See RFC 4880, section 5.5.2.
+type PublicKeyV3 struct {
+	CreationTime time.Time
+	DaysToExpire uint16
+	PubKeyAlgo   PublicKeyAlgorithm
+	PublicKey    *rsa.PublicKey
+	Fingerprint  [16]byte
+	KeyId        uint64
+	IsSubkey     bool
+
+	n, e parsedMPI
+}
+
+// newRSAPublicKeyV3 returns a PublicKey that wraps the given rsa.PublicKey.
+// Included here for testing purposes only. RFC 4880, section 5.5.2:
+// "an implementation MUST NOT generate a V3 key, but MAY accept it."
+func newRSAPublicKeyV3(creationTime time.Time, pub *rsa.PublicKey) *PublicKeyV3 {
+	pk := &PublicKeyV3{
+		CreationTime: creationTime,
+		PublicKey:    pub,
+		n:            fromBig(pub.N),
+		e:            fromBig(big.NewInt(int64(pub.E))),
+	}
+
+	pk.setFingerPrintAndKeyId()
+	return pk
+}
+
+func (pk *PublicKeyV3) parse(r io.Reader) (err error) {
+	// RFC 4880, section 5.5.2
+	var buf [8]byte
+	if _, err = readFull(r, buf[:]); err != nil {
+		return
+	}
+	if buf[0] < 2 || buf[0] > 3 {
+		return errors.UnsupportedError("public key version")
+	}
+	pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0)
+	pk.DaysToExpire = binary.BigEndian.Uint16(buf[5:7])
+	pk.PubKeyAlgo = PublicKeyAlgorithm(buf[7])
+	switch pk.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+		err = pk.parseRSA(r)
+	default:
+		err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
+	}
+	if err != nil {
+		return
+	}
+
+	pk.setFingerPrintAndKeyId()
+	return
+}
+
+func (pk *PublicKeyV3) setFingerPrintAndKeyId() {
+	// RFC 4880, section 12.2
+	fingerPrint := md5.New()
+	fingerPrint.Write(pk.n.bytes)
+	fingerPrint.Write(pk.e.bytes)
+	fingerPrint.Sum(pk.Fingerprint[:0])
+	pk.KeyId = binary.BigEndian.Uint64(pk.n.bytes[len(pk.n.bytes)-8:])
+}
+
+// parseRSA parses RSA public key material from the given Reader. See RFC 4880,
+// section 5.5.2.
+func (pk *PublicKeyV3) parseRSA(r io.Reader) (err error) {
+	if pk.n.bytes, pk.n.bitLength, err = readMPI(r); err != nil {
+		return
+	}
+	if pk.e.bytes, pk.e.bitLength, err = readMPI(r); err != nil {
+		return
+	}
+
+	// RFC 4880 Section 12.2 requires the low 8 bytes of the
+	// modulus to form the key id.
+	if len(pk.n.bytes) < 8 {
+		return errors.StructuralError("v3 public key modulus is too short")
+	}
+	if len(pk.e.bytes) > 3 {
+		err = errors.UnsupportedError("large public exponent")
+		return
+	}
+	rsa := &rsa.PublicKey{N: new(big.Int).SetBytes(pk.n.bytes)}
+	for i := 0; i < len(pk.e.bytes); i++ {
+		rsa.E <<= 8
+		rsa.E |= int(pk.e.bytes[i])
+	}
+	pk.PublicKey = rsa
+	return
+}
+
+// SerializeSignaturePrefix writes the prefix for this public key to the given Writer.
+// The prefix is used when calculating a signature over this public key. See
+// RFC 4880, section 5.2.4.
+func (pk *PublicKeyV3) SerializeSignaturePrefix(w io.Writer) {
+	var pLength uint16
+	switch pk.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+		pLength += 2 + uint16(len(pk.n.bytes))
+		pLength += 2 + uint16(len(pk.e.bytes))
+	default:
+		panic("unknown public key algorithm")
+	}
+	pLength += 6
+	w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)})
+	return
+}
+
+func (pk *PublicKeyV3) Serialize(w io.Writer) (err error) {
+	length := 8 // 8 byte header
+
+	switch pk.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+		length += 2 + len(pk.n.bytes)
+		length += 2 + len(pk.e.bytes)
+	default:
+		panic("unknown public key algorithm")
+	}
+
+	packetType := packetTypePublicKey
+	if pk.IsSubkey {
+		packetType = packetTypePublicSubkey
+	}
+	if err = serializeHeader(w, packetType, length); err != nil {
+		return
+	}
+	return pk.serializeWithoutHeaders(w)
+}
+
+// serializeWithoutHeaders marshals the PublicKey to w in the form of an
+// OpenPGP public key packet, not including the packet header.
+func (pk *PublicKeyV3) serializeWithoutHeaders(w io.Writer) (err error) {
+	var buf [8]byte
+	// Version 3
+	buf[0] = 3
+	// Creation time
+	t := uint32(pk.CreationTime.Unix())
+	buf[1] = byte(t >> 24)
+	buf[2] = byte(t >> 16)
+	buf[3] = byte(t >> 8)
+	buf[4] = byte(t)
+	// Days to expire
+	buf[5] = byte(pk.DaysToExpire >> 8)
+	buf[6] = byte(pk.DaysToExpire)
+	// Public key algorithm
+	buf[7] = byte(pk.PubKeyAlgo)
+
+	if _, err = w.Write(buf[:]); err != nil {
+		return
+	}
+
+	switch pk.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+		return writeMPIs(w, pk.n, pk.e)
+	}
+	return errors.InvalidArgumentError("bad public-key algorithm")
+}
+
+// CanSign returns true iff this public key can generate signatures
+func (pk *PublicKeyV3) CanSign() bool {
+	return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly
+}
+
+// VerifySignatureV3 returns nil iff sig is a valid signature, made by this
+// public key, of the data hashed into signed. signed is mutated by this call.
+func (pk *PublicKeyV3) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) {
+	if !pk.CanSign() {
+		return errors.InvalidArgumentError("public key cannot generate signatures")
+	}
+
+	suffix := make([]byte, 5)
+	suffix[0] = byte(sig.SigType)
+	binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix()))
+	signed.Write(suffix)
+	hashBytes := signed.Sum(nil)
+
+	if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
+		return errors.SignatureError("hash tag doesn't match")
+	}
+
+	if pk.PubKeyAlgo != sig.PubKeyAlgo {
+		return errors.InvalidArgumentError("public key and signature use different algorithms")
+	}
+
+	switch pk.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
+		if err = rsa.VerifyPKCS1v15(pk.PublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil {
+			return errors.SignatureError("RSA verification failure")
+		}
+		return
+	default:
+		// V3 public keys only support RSA.
+		panic("shouldn't happen")
+	}
+	panic("unreachable")
+}
+
+// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this
+// public key, that id is the identity of pub.
+func (pk *PublicKeyV3) VerifyUserIdSignatureV3(id string, pub *PublicKeyV3, sig *SignatureV3) (err error) {
+	h, err := userIdSignatureV3Hash(id, pk, sig.Hash)
+	if err != nil {
+		return err
+	}
+	return pk.VerifySignatureV3(h, sig)
+}
+
+// VerifyKeySignatureV3 returns nil iff sig is a valid signature, made by this
+// public key, of signed.
+func (pk *PublicKeyV3) VerifyKeySignatureV3(signed *PublicKeyV3, sig *SignatureV3) (err error) {
+	h, err := keySignatureHash(pk, signed, sig.Hash)
+	if err != nil {
+		return err
+	}
+	return pk.VerifySignatureV3(h, sig)
+}
+
+// userIdSignatureV3Hash returns a Hash of the message that needs to be signed
+// to assert that pk is a valid key for id.
+func userIdSignatureV3Hash(id string, pk signingKey, hfn crypto.Hash) (h hash.Hash, err error) {
+	if !hfn.Available() {
+		return nil, errors.UnsupportedError("hash function")
+	}
+	h = hfn.New()
+
+	// RFC 4880, section 5.2.4
+	pk.SerializeSignaturePrefix(h)
+	pk.serializeWithoutHeaders(h)
+
+	h.Write([]byte(id))
+
+	return
+}
+
+// KeyIdString returns the public key's fingerprint in capital hex
+// (e.g. "6C7EE1B8621CC013").
+func (pk *PublicKeyV3) KeyIdString() string {
+	return fmt.Sprintf("%X", pk.KeyId)
+}
+
+// KeyIdShortString returns the short form of public key's fingerprint
+// in capital hex, as shown by gpg --list-keys (e.g. "621CC013").
+func (pk *PublicKeyV3) KeyIdShortString() string {
+	return fmt.Sprintf("%X", pk.KeyId&0xFFFFFFFF)
+}
+
+// BitLength returns the bit length for the given public key.
+func (pk *PublicKeyV3) BitLength() (bitLength uint16, err error) {
+	switch pk.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+		bitLength = pk.n.bitLength
+	default:
+		err = errors.InvalidArgumentError("bad public-key algorithm")
+	}
+	return
+}

+ 82 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go

@@ -0,0 +1,82 @@
+// Copyright 2013 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 packet
+
+import (
+	"bytes"
+	"encoding/hex"
+	"testing"
+	"time"
+)
+
+var pubKeyV3Test = struct {
+	hexFingerprint string
+	creationTime   time.Time
+	pubKeyAlgo     PublicKeyAlgorithm
+	keyId          uint64
+	keyIdString    string
+	keyIdShort     string
+}{
+	"103BECF5BD1E837C89D19E98487767F7",
+	time.Unix(779753634, 0),
+	PubKeyAlgoRSA,
+	0xDE0F188A5DA5E3C9,
+	"DE0F188A5DA5E3C9",
+	"5DA5E3C9"}
+
+func TestPublicKeyV3Read(t *testing.T) {
+	i, test := 0, pubKeyV3Test
+	packet, err := Read(v3KeyReader(t))
+	if err != nil {
+		t.Fatalf("#%d: Read error: %s", i, err)
+	}
+	pk, ok := packet.(*PublicKeyV3)
+	if !ok {
+		t.Fatalf("#%d: failed to parse, got: %#v", i, packet)
+	}
+	if pk.PubKeyAlgo != test.pubKeyAlgo {
+		t.Errorf("#%d: bad public key algorithm got:%x want:%x", i, pk.PubKeyAlgo, test.pubKeyAlgo)
+	}
+	if !pk.CreationTime.Equal(test.creationTime) {
+		t.Errorf("#%d: bad creation time got:%v want:%v", i, pk.CreationTime, test.creationTime)
+	}
+	expectedFingerprint, _ := hex.DecodeString(test.hexFingerprint)
+	if !bytes.Equal(expectedFingerprint, pk.Fingerprint[:]) {
+		t.Errorf("#%d: bad fingerprint got:%x want:%x", i, pk.Fingerprint[:], expectedFingerprint)
+	}
+	if pk.KeyId != test.keyId {
+		t.Errorf("#%d: bad keyid got:%x want:%x", i, pk.KeyId, test.keyId)
+	}
+	if g, e := pk.KeyIdString(), test.keyIdString; g != e {
+		t.Errorf("#%d: bad KeyIdString got:%q want:%q", i, g, e)
+	}
+	if g, e := pk.KeyIdShortString(), test.keyIdShort; g != e {
+		t.Errorf("#%d: bad KeyIdShortString got:%q want:%q", i, g, e)
+	}
+}
+
+func TestPublicKeyV3Serialize(t *testing.T) {
+	//for i, test := range pubKeyV3Tests {
+	i := 0
+	packet, err := Read(v3KeyReader(t))
+	if err != nil {
+		t.Fatalf("#%d: Read error: %s", i, err)
+	}
+	pk, ok := packet.(*PublicKeyV3)
+	if !ok {
+		t.Fatalf("#%d: failed to parse, got: %#v", i, packet)
+	}
+	var serializeBuf bytes.Buffer
+	if err = pk.Serialize(&serializeBuf); err != nil {
+		t.Fatalf("#%d: failed to serialize: %s", i, err)
+	}
+
+	if packet, err = Read(bytes.NewBuffer(serializeBuf.Bytes())); err != nil {
+		t.Fatalf("#%d: Read error (from serialized data): %s", i, err)
+	}
+	if pk, ok = packet.(*PublicKeyV3); !ok {
+		t.Fatalf("#%d: failed to parse serialized data, got: %#v", i, packet)
+	}
+}

+ 76 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/reader.go

@@ -0,0 +1,76 @@
+// Copyright 2011 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 packet
+
+import (
+	"golang.org/x/crypto/openpgp/errors"
+	"io"
+)
+
+// Reader reads packets from an io.Reader and allows packets to be 'unread' so
+// that they result from the next call to Next.
+type Reader struct {
+	q       []Packet
+	readers []io.Reader
+}
+
+// New io.Readers are pushed when a compressed or encrypted packet is processed
+// and recursively treated as a new source of packets. However, a carefully
+// crafted packet can trigger an infinite recursive sequence of packets. See
+// http://mumble.net/~campbell/misc/pgp-quine
+// https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-4402
+// This constant limits the number of recursive packets that may be pushed.
+const maxReaders = 32
+
+// Next returns the most recently unread Packet, or reads another packet from
+// the top-most io.Reader. Unknown packet types are skipped.
+func (r *Reader) Next() (p Packet, err error) {
+	if len(r.q) > 0 {
+		p = r.q[len(r.q)-1]
+		r.q = r.q[:len(r.q)-1]
+		return
+	}
+
+	for len(r.readers) > 0 {
+		p, err = Read(r.readers[len(r.readers)-1])
+		if err == nil {
+			return
+		}
+		if err == io.EOF {
+			r.readers = r.readers[:len(r.readers)-1]
+			continue
+		}
+		if _, ok := err.(errors.UnknownPacketTypeError); !ok {
+			return nil, err
+		}
+	}
+
+	return nil, io.EOF
+}
+
+// Push causes the Reader to start reading from a new io.Reader. When an EOF
+// error is seen from the new io.Reader, it is popped and the Reader continues
+// to read from the next most recent io.Reader. Push returns a StructuralError
+// if pushing the reader would exceed the maximum recursion level, otherwise it
+// returns nil.
+func (r *Reader) Push(reader io.Reader) (err error) {
+	if len(r.readers) >= maxReaders {
+		return errors.StructuralError("too many layers of packets")
+	}
+	r.readers = append(r.readers, reader)
+	return nil
+}
+
+// Unread causes the given Packet to be returned from the next call to Next.
+func (r *Reader) Unread(p Packet) {
+	r.q = append(r.q, p)
+}
+
+func NewReader(r io.Reader) *Reader {
+	return &Reader{
+		q:       nil,
+		readers: []io.Reader{r},
+	}
+}

+ 706 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/signature.go

@@ -0,0 +1,706 @@
+// Copyright 2011 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 packet
+
+import (
+	"bytes"
+	"crypto"
+	"crypto/dsa"
+	"crypto/ecdsa"
+	"crypto/rsa"
+	"encoding/binary"
+	"hash"
+	"io"
+	"strconv"
+	"time"
+
+	"golang.org/x/crypto/openpgp/errors"
+	"golang.org/x/crypto/openpgp/s2k"
+)
+
+const (
+	// See RFC 4880, section 5.2.3.21 for details.
+	KeyFlagCertify = 1 << iota
+	KeyFlagSign
+	KeyFlagEncryptCommunications
+	KeyFlagEncryptStorage
+)
+
+// Signature represents a signature. See RFC 4880, section 5.2.
+type Signature struct {
+	SigType    SignatureType
+	PubKeyAlgo PublicKeyAlgorithm
+	Hash       crypto.Hash
+
+	// HashSuffix is extra data that is hashed in after the signed data.
+	HashSuffix []byte
+	// HashTag contains the first two bytes of the hash for fast rejection
+	// of bad signed data.
+	HashTag      [2]byte
+	CreationTime time.Time
+
+	RSASignature         parsedMPI
+	DSASigR, DSASigS     parsedMPI
+	ECDSASigR, ECDSASigS parsedMPI
+
+	// rawSubpackets contains the unparsed subpackets, in order.
+	rawSubpackets []outputSubpacket
+
+	// The following are optional so are nil when not included in the
+	// signature.
+
+	SigLifetimeSecs, KeyLifetimeSecs                        *uint32
+	PreferredSymmetric, PreferredHash, PreferredCompression []uint8
+	IssuerKeyId                                             *uint64
+	IsPrimaryId                                             *bool
+
+	// FlagsValid is set if any flags were given. See RFC 4880, section
+	// 5.2.3.21 for details.
+	FlagsValid                                                           bool
+	FlagCertify, FlagSign, FlagEncryptCommunications, FlagEncryptStorage bool
+
+	// RevocationReason is set if this signature has been revoked.
+	// See RFC 4880, section 5.2.3.23 for details.
+	RevocationReason     *uint8
+	RevocationReasonText string
+
+	// MDC is set if this signature has a feature packet that indicates
+	// support for MDC subpackets.
+	MDC bool
+
+	// EmbeddedSignature, if non-nil, is a signature of the parent key, by
+	// this key. This prevents an attacker from claiming another's signing
+	// subkey as their own.
+	EmbeddedSignature *Signature
+
+	outSubpackets []outputSubpacket
+}
+
+func (sig *Signature) parse(r io.Reader) (err error) {
+	// RFC 4880, section 5.2.3
+	var buf [5]byte
+	_, err = readFull(r, buf[:1])
+	if err != nil {
+		return
+	}
+	if buf[0] != 4 {
+		err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0])))
+		return
+	}
+
+	_, err = readFull(r, buf[:5])
+	if err != nil {
+		return
+	}
+	sig.SigType = SignatureType(buf[0])
+	sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1])
+	switch sig.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA:
+	default:
+		err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo)))
+		return
+	}
+
+	var ok bool
+	sig.Hash, ok = s2k.HashIdToHash(buf[2])
+	if !ok {
+		return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2])))
+	}
+
+	hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4])
+	l := 6 + hashedSubpacketsLength
+	sig.HashSuffix = make([]byte, l+6)
+	sig.HashSuffix[0] = 4
+	copy(sig.HashSuffix[1:], buf[:5])
+	hashedSubpackets := sig.HashSuffix[6:l]
+	_, err = readFull(r, hashedSubpackets)
+	if err != nil {
+		return
+	}
+	// See RFC 4880, section 5.2.4
+	trailer := sig.HashSuffix[l:]
+	trailer[0] = 4
+	trailer[1] = 0xff
+	trailer[2] = uint8(l >> 24)
+	trailer[3] = uint8(l >> 16)
+	trailer[4] = uint8(l >> 8)
+	trailer[5] = uint8(l)
+
+	err = parseSignatureSubpackets(sig, hashedSubpackets, true)
+	if err != nil {
+		return
+	}
+
+	_, err = readFull(r, buf[:2])
+	if err != nil {
+		return
+	}
+	unhashedSubpacketsLength := int(buf[0])<<8 | int(buf[1])
+	unhashedSubpackets := make([]byte, unhashedSubpacketsLength)
+	_, err = readFull(r, unhashedSubpackets)
+	if err != nil {
+		return
+	}
+	err = parseSignatureSubpackets(sig, unhashedSubpackets, false)
+	if err != nil {
+		return
+	}
+
+	_, err = readFull(r, sig.HashTag[:2])
+	if err != nil {
+		return
+	}
+
+	switch sig.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
+		sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r)
+	case PubKeyAlgoDSA:
+		sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r)
+		if err == nil {
+			sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r)
+		}
+	case PubKeyAlgoECDSA:
+		sig.ECDSASigR.bytes, sig.ECDSASigR.bitLength, err = readMPI(r)
+		if err == nil {
+			sig.ECDSASigS.bytes, sig.ECDSASigS.bitLength, err = readMPI(r)
+		}
+	default:
+		panic("unreachable")
+	}
+	return
+}
+
+// parseSignatureSubpackets parses subpackets of the main signature packet. See
+// RFC 4880, section 5.2.3.1.
+func parseSignatureSubpackets(sig *Signature, subpackets []byte, isHashed bool) (err error) {
+	for len(subpackets) > 0 {
+		subpackets, err = parseSignatureSubpacket(sig, subpackets, isHashed)
+		if err != nil {
+			return
+		}
+	}
+
+	if sig.CreationTime.IsZero() {
+		err = errors.StructuralError("no creation time in signature")
+	}
+
+	return
+}
+
+type signatureSubpacketType uint8
+
+const (
+	creationTimeSubpacket        signatureSubpacketType = 2
+	signatureExpirationSubpacket signatureSubpacketType = 3
+	keyExpirationSubpacket       signatureSubpacketType = 9
+	prefSymmetricAlgosSubpacket  signatureSubpacketType = 11
+	issuerSubpacket              signatureSubpacketType = 16
+	prefHashAlgosSubpacket       signatureSubpacketType = 21
+	prefCompressionSubpacket     signatureSubpacketType = 22
+	primaryUserIdSubpacket       signatureSubpacketType = 25
+	keyFlagsSubpacket            signatureSubpacketType = 27
+	reasonForRevocationSubpacket signatureSubpacketType = 29
+	featuresSubpacket            signatureSubpacketType = 30
+	embeddedSignatureSubpacket   signatureSubpacketType = 32
+)
+
+// parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1.
+func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (rest []byte, err error) {
+	// RFC 4880, section 5.2.3.1
+	var (
+		length     uint32
+		packetType signatureSubpacketType
+		isCritical bool
+	)
+	switch {
+	case subpacket[0] < 192:
+		length = uint32(subpacket[0])
+		subpacket = subpacket[1:]
+	case subpacket[0] < 255:
+		if len(subpacket) < 2 {
+			goto Truncated
+		}
+		length = uint32(subpacket[0]-192)<<8 + uint32(subpacket[1]) + 192
+		subpacket = subpacket[2:]
+	default:
+		if len(subpacket) < 5 {
+			goto Truncated
+		}
+		length = uint32(subpacket[1])<<24 |
+			uint32(subpacket[2])<<16 |
+			uint32(subpacket[3])<<8 |
+			uint32(subpacket[4])
+		subpacket = subpacket[5:]
+	}
+	if length > uint32(len(subpacket)) {
+		goto Truncated
+	}
+	rest = subpacket[length:]
+	subpacket = subpacket[:length]
+	if len(subpacket) == 0 {
+		err = errors.StructuralError("zero length signature subpacket")
+		return
+	}
+	packetType = signatureSubpacketType(subpacket[0] & 0x7f)
+	isCritical = subpacket[0]&0x80 == 0x80
+	subpacket = subpacket[1:]
+	sig.rawSubpackets = append(sig.rawSubpackets, outputSubpacket{isHashed, packetType, isCritical, subpacket})
+	switch packetType {
+	case creationTimeSubpacket:
+		if !isHashed {
+			err = errors.StructuralError("signature creation time in non-hashed area")
+			return
+		}
+		if len(subpacket) != 4 {
+			err = errors.StructuralError("signature creation time not four bytes")
+			return
+		}
+		t := binary.BigEndian.Uint32(subpacket)
+		sig.CreationTime = time.Unix(int64(t), 0)
+	case signatureExpirationSubpacket:
+		// Signature expiration time, section 5.2.3.10
+		if !isHashed {
+			return
+		}
+		if len(subpacket) != 4 {
+			err = errors.StructuralError("expiration subpacket with bad length")
+			return
+		}
+		sig.SigLifetimeSecs = new(uint32)
+		*sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket)
+	case keyExpirationSubpacket:
+		// Key expiration time, section 5.2.3.6
+		if !isHashed {
+			return
+		}
+		if len(subpacket) != 4 {
+			err = errors.StructuralError("key expiration subpacket with bad length")
+			return
+		}
+		sig.KeyLifetimeSecs = new(uint32)
+		*sig.KeyLifetimeSecs = binary.BigEndian.Uint32(subpacket)
+	case prefSymmetricAlgosSubpacket:
+		// Preferred symmetric algorithms, section 5.2.3.7
+		if !isHashed {
+			return
+		}
+		sig.PreferredSymmetric = make([]byte, len(subpacket))
+		copy(sig.PreferredSymmetric, subpacket)
+	case issuerSubpacket:
+		// Issuer, section 5.2.3.5
+		if len(subpacket) != 8 {
+			err = errors.StructuralError("issuer subpacket with bad length")
+			return
+		}
+		sig.IssuerKeyId = new(uint64)
+		*sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket)
+	case prefHashAlgosSubpacket:
+		// Preferred hash algorithms, section 5.2.3.8
+		if !isHashed {
+			return
+		}
+		sig.PreferredHash = make([]byte, len(subpacket))
+		copy(sig.PreferredHash, subpacket)
+	case prefCompressionSubpacket:
+		// Preferred compression algorithms, section 5.2.3.9
+		if !isHashed {
+			return
+		}
+		sig.PreferredCompression = make([]byte, len(subpacket))
+		copy(sig.PreferredCompression, subpacket)
+	case primaryUserIdSubpacket:
+		// Primary User ID, section 5.2.3.19
+		if !isHashed {
+			return
+		}
+		if len(subpacket) != 1 {
+			err = errors.StructuralError("primary user id subpacket with bad length")
+			return
+		}
+		sig.IsPrimaryId = new(bool)
+		if subpacket[0] > 0 {
+			*sig.IsPrimaryId = true
+		}
+	case keyFlagsSubpacket:
+		// Key flags, section 5.2.3.21
+		if !isHashed {
+			return
+		}
+		if len(subpacket) == 0 {
+			err = errors.StructuralError("empty key flags subpacket")
+			return
+		}
+		sig.FlagsValid = true
+		if subpacket[0]&KeyFlagCertify != 0 {
+			sig.FlagCertify = true
+		}
+		if subpacket[0]&KeyFlagSign != 0 {
+			sig.FlagSign = true
+		}
+		if subpacket[0]&KeyFlagEncryptCommunications != 0 {
+			sig.FlagEncryptCommunications = true
+		}
+		if subpacket[0]&KeyFlagEncryptStorage != 0 {
+			sig.FlagEncryptStorage = true
+		}
+	case reasonForRevocationSubpacket:
+		// Reason For Revocation, section 5.2.3.23
+		if !isHashed {
+			return
+		}
+		if len(subpacket) == 0 {
+			err = errors.StructuralError("empty revocation reason subpacket")
+			return
+		}
+		sig.RevocationReason = new(uint8)
+		*sig.RevocationReason = subpacket[0]
+		sig.RevocationReasonText = string(subpacket[1:])
+	case featuresSubpacket:
+		// Features subpacket, section 5.2.3.24 specifies a very general
+		// mechanism for OpenPGP implementations to signal support for new
+		// features. In practice, the subpacket is used exclusively to
+		// indicate support for MDC-protected encryption.
+		sig.MDC = len(subpacket) >= 1 && subpacket[0]&1 == 1
+	case embeddedSignatureSubpacket:
+		// Only usage is in signatures that cross-certify
+		// signing subkeys. section 5.2.3.26 describes the
+		// format, with its usage described in section 11.1
+		if sig.EmbeddedSignature != nil {
+			err = errors.StructuralError("Cannot have multiple embedded signatures")
+			return
+		}
+		sig.EmbeddedSignature = new(Signature)
+		// Embedded signatures are required to be v4 signatures see
+		// section 12.1. However, we only parse v4 signatures in this
+		// file anyway.
+		if err := sig.EmbeddedSignature.parse(bytes.NewBuffer(subpacket)); err != nil {
+			return nil, err
+		}
+		if sigType := sig.EmbeddedSignature.SigType; sigType != SigTypePrimaryKeyBinding {
+			return nil, errors.StructuralError("cross-signature has unexpected type " + strconv.Itoa(int(sigType)))
+		}
+	default:
+		if isCritical {
+			err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType)))
+			return
+		}
+	}
+	return
+
+Truncated:
+	err = errors.StructuralError("signature subpacket truncated")
+	return
+}
+
+// subpacketLengthLength returns the length, in bytes, of an encoded length value.
+func subpacketLengthLength(length int) int {
+	if length < 192 {
+		return 1
+	}
+	if length < 16320 {
+		return 2
+	}
+	return 5
+}
+
+// serializeSubpacketLength marshals the given length into to.
+func serializeSubpacketLength(to []byte, length int) int {
+	// RFC 4880, Section 4.2.2.
+	if length < 192 {
+		to[0] = byte(length)
+		return 1
+	}
+	if length < 16320 {
+		length -= 192
+		to[0] = byte((length >> 8) + 192)
+		to[1] = byte(length)
+		return 2
+	}
+	to[0] = 255
+	to[1] = byte(length >> 24)
+	to[2] = byte(length >> 16)
+	to[3] = byte(length >> 8)
+	to[4] = byte(length)
+	return 5
+}
+
+// subpacketsLength returns the serialized length, in bytes, of the given
+// subpackets.
+func subpacketsLength(subpackets []outputSubpacket, hashed bool) (length int) {
+	for _, subpacket := range subpackets {
+		if subpacket.hashed == hashed {
+			length += subpacketLengthLength(len(subpacket.contents) + 1)
+			length += 1 // type byte
+			length += len(subpacket.contents)
+		}
+	}
+	return
+}
+
+// serializeSubpackets marshals the given subpackets into to.
+func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) {
+	for _, subpacket := range subpackets {
+		if subpacket.hashed == hashed {
+			n := serializeSubpacketLength(to, len(subpacket.contents)+1)
+			to[n] = byte(subpacket.subpacketType)
+			to = to[1+n:]
+			n = copy(to, subpacket.contents)
+			to = to[n:]
+		}
+	}
+	return
+}
+
+// KeyExpired returns whether sig is a self-signature of a key that has
+// expired.
+func (sig *Signature) KeyExpired(currentTime time.Time) bool {
+	if sig.KeyLifetimeSecs == nil {
+		return false
+	}
+	expiry := sig.CreationTime.Add(time.Duration(*sig.KeyLifetimeSecs) * time.Second)
+	return currentTime.After(expiry)
+}
+
+// buildHashSuffix constructs the HashSuffix member of sig in preparation for signing.
+func (sig *Signature) buildHashSuffix() (err error) {
+	hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true)
+
+	var ok bool
+	l := 6 + hashedSubpacketsLen
+	sig.HashSuffix = make([]byte, l+6)
+	sig.HashSuffix[0] = 4
+	sig.HashSuffix[1] = uint8(sig.SigType)
+	sig.HashSuffix[2] = uint8(sig.PubKeyAlgo)
+	sig.HashSuffix[3], ok = s2k.HashToHashId(sig.Hash)
+	if !ok {
+		sig.HashSuffix = nil
+		return errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash)))
+	}
+	sig.HashSuffix[4] = byte(hashedSubpacketsLen >> 8)
+	sig.HashSuffix[5] = byte(hashedSubpacketsLen)
+	serializeSubpackets(sig.HashSuffix[6:l], sig.outSubpackets, true)
+	trailer := sig.HashSuffix[l:]
+	trailer[0] = 4
+	trailer[1] = 0xff
+	trailer[2] = byte(l >> 24)
+	trailer[3] = byte(l >> 16)
+	trailer[4] = byte(l >> 8)
+	trailer[5] = byte(l)
+	return
+}
+
+func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) {
+	err = sig.buildHashSuffix()
+	if err != nil {
+		return
+	}
+
+	h.Write(sig.HashSuffix)
+	digest = h.Sum(nil)
+	copy(sig.HashTag[:], digest)
+	return
+}
+
+// Sign signs a message with a private key. The hash, h, must contain
+// the hash of the message to be signed and will be mutated by this function.
+// On success, the signature is stored in sig. Call Serialize to write it out.
+// If config is nil, sensible defaults will be used.
+func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err error) {
+	sig.outSubpackets = sig.buildSubpackets()
+	digest, err := sig.signPrepareHash(h)
+	if err != nil {
+		return
+	}
+
+	switch priv.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
+		sig.RSASignature.bytes, err = rsa.SignPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), sig.Hash, digest)
+		sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes))
+	case PubKeyAlgoDSA:
+		dsaPriv := priv.PrivateKey.(*dsa.PrivateKey)
+
+		// Need to truncate hashBytes to match FIPS 186-3 section 4.6.
+		subgroupSize := (dsaPriv.Q.BitLen() + 7) / 8
+		if len(digest) > subgroupSize {
+			digest = digest[:subgroupSize]
+		}
+		r, s, err := dsa.Sign(config.Random(), dsaPriv, digest)
+		if err == nil {
+			sig.DSASigR.bytes = r.Bytes()
+			sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes))
+			sig.DSASigS.bytes = s.Bytes()
+			sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes))
+		}
+	case PubKeyAlgoECDSA:
+		r, s, err := ecdsa.Sign(config.Random(), priv.PrivateKey.(*ecdsa.PrivateKey), digest)
+		if err == nil {
+			sig.ECDSASigR = fromBig(r)
+			sig.ECDSASigS = fromBig(s)
+		}
+	default:
+		err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
+	}
+
+	return
+}
+
+// SignUserId computes a signature from priv, asserting that pub is a valid
+// key for the identity id.  On success, the signature is stored in sig. Call
+// Serialize to write it out.
+// If config is nil, sensible defaults will be used.
+func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, config *Config) error {
+	h, err := userIdSignatureHash(id, pub, sig.Hash)
+	if err != nil {
+		return nil
+	}
+	return sig.Sign(h, priv, config)
+}
+
+// SignKey computes a signature from priv, asserting that pub is a subkey. On
+// success, the signature is stored in sig. Call Serialize to write it out.
+// If config is nil, sensible defaults will be used.
+func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey, config *Config) error {
+	h, err := keySignatureHash(&priv.PublicKey, pub, sig.Hash)
+	if err != nil {
+		return err
+	}
+	return sig.Sign(h, priv, config)
+}
+
+// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been
+// called first.
+func (sig *Signature) Serialize(w io.Writer) (err error) {
+	if len(sig.outSubpackets) == 0 {
+		sig.outSubpackets = sig.rawSubpackets
+	}
+	if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil && sig.ECDSASigR.bytes == nil {
+		return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize")
+	}
+
+	sigLength := 0
+	switch sig.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
+		sigLength = 2 + len(sig.RSASignature.bytes)
+	case PubKeyAlgoDSA:
+		sigLength = 2 + len(sig.DSASigR.bytes)
+		sigLength += 2 + len(sig.DSASigS.bytes)
+	case PubKeyAlgoECDSA:
+		sigLength = 2 + len(sig.ECDSASigR.bytes)
+		sigLength += 2 + len(sig.ECDSASigS.bytes)
+	default:
+		panic("impossible")
+	}
+
+	unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false)
+	length := len(sig.HashSuffix) - 6 /* trailer not included */ +
+		2 /* length of unhashed subpackets */ + unhashedSubpacketsLen +
+		2 /* hash tag */ + sigLength
+	err = serializeHeader(w, packetTypeSignature, length)
+	if err != nil {
+		return
+	}
+
+	_, err = w.Write(sig.HashSuffix[:len(sig.HashSuffix)-6])
+	if err != nil {
+		return
+	}
+
+	unhashedSubpackets := make([]byte, 2+unhashedSubpacketsLen)
+	unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 8)
+	unhashedSubpackets[1] = byte(unhashedSubpacketsLen)
+	serializeSubpackets(unhashedSubpackets[2:], sig.outSubpackets, false)
+
+	_, err = w.Write(unhashedSubpackets)
+	if err != nil {
+		return
+	}
+	_, err = w.Write(sig.HashTag[:])
+	if err != nil {
+		return
+	}
+
+	switch sig.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
+		err = writeMPIs(w, sig.RSASignature)
+	case PubKeyAlgoDSA:
+		err = writeMPIs(w, sig.DSASigR, sig.DSASigS)
+	case PubKeyAlgoECDSA:
+		err = writeMPIs(w, sig.ECDSASigR, sig.ECDSASigS)
+	default:
+		panic("impossible")
+	}
+	return
+}
+
+// outputSubpacket represents a subpacket to be marshaled.
+type outputSubpacket struct {
+	hashed        bool // true if this subpacket is in the hashed area.
+	subpacketType signatureSubpacketType
+	isCritical    bool
+	contents      []byte
+}
+
+func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) {
+	creationTime := make([]byte, 4)
+	binary.BigEndian.PutUint32(creationTime, uint32(sig.CreationTime.Unix()))
+	subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, false, creationTime})
+
+	if sig.IssuerKeyId != nil {
+		keyId := make([]byte, 8)
+		binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId)
+		subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId})
+	}
+
+	if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 {
+		sigLifetime := make([]byte, 4)
+		binary.BigEndian.PutUint32(sigLifetime, *sig.SigLifetimeSecs)
+		subpackets = append(subpackets, outputSubpacket{true, signatureExpirationSubpacket, true, sigLifetime})
+	}
+
+	// Key flags may only appear in self-signatures or certification signatures.
+
+	if sig.FlagsValid {
+		var flags byte
+		if sig.FlagCertify {
+			flags |= KeyFlagCertify
+		}
+		if sig.FlagSign {
+			flags |= KeyFlagSign
+		}
+		if sig.FlagEncryptCommunications {
+			flags |= KeyFlagEncryptCommunications
+		}
+		if sig.FlagEncryptStorage {
+			flags |= KeyFlagEncryptStorage
+		}
+		subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, false, []byte{flags}})
+	}
+
+	// The following subpackets may only appear in self-signatures
+
+	if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 {
+		keyLifetime := make([]byte, 4)
+		binary.BigEndian.PutUint32(keyLifetime, *sig.KeyLifetimeSecs)
+		subpackets = append(subpackets, outputSubpacket{true, keyExpirationSubpacket, true, keyLifetime})
+	}
+
+	if sig.IsPrimaryId != nil && *sig.IsPrimaryId {
+		subpackets = append(subpackets, outputSubpacket{true, primaryUserIdSubpacket, false, []byte{1}})
+	}
+
+	if len(sig.PreferredSymmetric) > 0 {
+		subpackets = append(subpackets, outputSubpacket{true, prefSymmetricAlgosSubpacket, false, sig.PreferredSymmetric})
+	}
+
+	if len(sig.PreferredHash) > 0 {
+		subpackets = append(subpackets, outputSubpacket{true, prefHashAlgosSubpacket, false, sig.PreferredHash})
+	}
+
+	if len(sig.PreferredCompression) > 0 {
+		subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression})
+	}
+
+	return
+}

+ 42 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/signature_test.go

@@ -0,0 +1,42 @@
+// Copyright 2011 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 packet
+
+import (
+	"bytes"
+	"crypto"
+	"encoding/hex"
+	"testing"
+)
+
+func TestSignatureRead(t *testing.T) {
+	packet, err := Read(readerFromHex(signatureDataHex))
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	sig, ok := packet.(*Signature)
+	if !ok || sig.SigType != SigTypeBinary || sig.PubKeyAlgo != PubKeyAlgoRSA || sig.Hash != crypto.SHA1 {
+		t.Errorf("failed to parse, got: %#v", packet)
+	}
+}
+
+func TestSignatureReserialize(t *testing.T) {
+	packet, _ := Read(readerFromHex(signatureDataHex))
+	sig := packet.(*Signature)
+	out := new(bytes.Buffer)
+	err := sig.Serialize(out)
+	if err != nil {
+		t.Errorf("error reserializing: %s", err)
+		return
+	}
+
+	expected, _ := hex.DecodeString(signatureDataHex)
+	if !bytes.Equal(expected, out.Bytes()) {
+		t.Errorf("output doesn't match input (got vs expected):\n%s\n%s", hex.Dump(out.Bytes()), hex.Dump(expected))
+	}
+}
+
+const signatureDataHex = "c2c05c04000102000605024cb45112000a0910ab105c91af38fb158f8d07ff5596ea368c5efe015bed6e78348c0f033c931d5f2ce5db54ce7f2a7e4b4ad64db758d65a7a71773edeab7ba2a9e0908e6a94a1175edd86c1d843279f045b021a6971a72702fcbd650efc393c5474d5b59a15f96d2eaad4c4c426797e0dcca2803ef41c6ff234d403eec38f31d610c344c06f2401c262f0993b2e66cad8a81ebc4322c723e0d4ba09fe917e8777658307ad8329adacba821420741009dfe87f007759f0982275d028a392c6ed983a0d846f890b36148c7358bdb8a516007fac760261ecd06076813831a36d0459075d1befa245ae7f7fb103d92ca759e9498fe60ef8078a39a3beda510deea251ea9f0a7f0df6ef42060f20780360686f3e400e"

+ 146 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/signature_v3.go

@@ -0,0 +1,146 @@
+// Copyright 2013 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 packet
+
+import (
+	"crypto"
+	"encoding/binary"
+	"fmt"
+	"io"
+	"strconv"
+	"time"
+
+	"golang.org/x/crypto/openpgp/errors"
+	"golang.org/x/crypto/openpgp/s2k"
+)
+
+// SignatureV3 represents older version 3 signatures. These signatures are less secure
+// than version 4 and should not be used to create new signatures. They are included
+// here for backwards compatibility to read and validate with older key material.
+// See RFC 4880, section 5.2.2.
+type SignatureV3 struct {
+	SigType      SignatureType
+	CreationTime time.Time
+	IssuerKeyId  uint64
+	PubKeyAlgo   PublicKeyAlgorithm
+	Hash         crypto.Hash
+	HashTag      [2]byte
+
+	RSASignature     parsedMPI
+	DSASigR, DSASigS parsedMPI
+}
+
+func (sig *SignatureV3) parse(r io.Reader) (err error) {
+	// RFC 4880, section 5.2.2
+	var buf [8]byte
+	if _, err = readFull(r, buf[:1]); err != nil {
+		return
+	}
+	if buf[0] < 2 || buf[0] > 3 {
+		err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0])))
+		return
+	}
+	if _, err = readFull(r, buf[:1]); err != nil {
+		return
+	}
+	if buf[0] != 5 {
+		err = errors.UnsupportedError(
+			"invalid hashed material length " + strconv.Itoa(int(buf[0])))
+		return
+	}
+
+	// Read hashed material: signature type + creation time
+	if _, err = readFull(r, buf[:5]); err != nil {
+		return
+	}
+	sig.SigType = SignatureType(buf[0])
+	t := binary.BigEndian.Uint32(buf[1:5])
+	sig.CreationTime = time.Unix(int64(t), 0)
+
+	// Eight-octet Key ID of signer.
+	if _, err = readFull(r, buf[:8]); err != nil {
+		return
+	}
+	sig.IssuerKeyId = binary.BigEndian.Uint64(buf[:])
+
+	// Public-key and hash algorithm
+	if _, err = readFull(r, buf[:2]); err != nil {
+		return
+	}
+	sig.PubKeyAlgo = PublicKeyAlgorithm(buf[0])
+	switch sig.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA:
+	default:
+		err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo)))
+		return
+	}
+	var ok bool
+	if sig.Hash, ok = s2k.HashIdToHash(buf[1]); !ok {
+		return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2])))
+	}
+
+	// Two-octet field holding left 16 bits of signed hash value.
+	if _, err = readFull(r, sig.HashTag[:2]); err != nil {
+		return
+	}
+
+	switch sig.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
+		sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r)
+	case PubKeyAlgoDSA:
+		if sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r); err != nil {
+			return
+		}
+		sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r)
+	default:
+		panic("unreachable")
+	}
+	return
+}
+
+// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been
+// called first.
+func (sig *SignatureV3) Serialize(w io.Writer) (err error) {
+	buf := make([]byte, 8)
+
+	// Write the sig type and creation time
+	buf[0] = byte(sig.SigType)
+	binary.BigEndian.PutUint32(buf[1:5], uint32(sig.CreationTime.Unix()))
+	if _, err = w.Write(buf[:5]); err != nil {
+		return
+	}
+
+	// Write the issuer long key ID
+	binary.BigEndian.PutUint64(buf[:8], sig.IssuerKeyId)
+	if _, err = w.Write(buf[:8]); err != nil {
+		return
+	}
+
+	// Write public key algorithm, hash ID, and hash value
+	buf[0] = byte(sig.PubKeyAlgo)
+	hashId, ok := s2k.HashToHashId(sig.Hash)
+	if !ok {
+		return errors.UnsupportedError(fmt.Sprintf("hash function %v", sig.Hash))
+	}
+	buf[1] = hashId
+	copy(buf[2:4], sig.HashTag[:])
+	if _, err = w.Write(buf[:4]); err != nil {
+		return
+	}
+
+	if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil {
+		return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize")
+	}
+
+	switch sig.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
+		err = writeMPIs(w, sig.RSASignature)
+	case PubKeyAlgoDSA:
+		err = writeMPIs(w, sig.DSASigR, sig.DSASigS)
+	default:
+		panic("impossible")
+	}
+	return
+}

+ 92 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/signature_v3_test.go

@@ -0,0 +1,92 @@
+// Copyright 2013 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 packet
+
+import (
+	"bytes"
+	"crypto"
+	"encoding/hex"
+	"io"
+	"io/ioutil"
+	"testing"
+
+	"golang.org/x/crypto/openpgp/armor"
+)
+
+func TestSignatureV3Read(t *testing.T) {
+	r := v3KeyReader(t)
+	Read(r)                // Skip public key
+	Read(r)                // Skip uid
+	packet, err := Read(r) // Signature
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	sig, ok := packet.(*SignatureV3)
+	if !ok || sig.SigType != SigTypeGenericCert || sig.PubKeyAlgo != PubKeyAlgoRSA || sig.Hash != crypto.MD5 {
+		t.Errorf("failed to parse, got: %#v", packet)
+	}
+}
+
+func TestSignatureV3Reserialize(t *testing.T) {
+	r := v3KeyReader(t)
+	Read(r) // Skip public key
+	Read(r) // Skip uid
+	packet, err := Read(r)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	sig := packet.(*SignatureV3)
+	out := new(bytes.Buffer)
+	if err = sig.Serialize(out); err != nil {
+		t.Errorf("error reserializing: %s", err)
+		return
+	}
+	expected, err := ioutil.ReadAll(v3KeyReader(t))
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	expected = expected[4+141+4+39:] // See pgpdump offsets below, this is where the sig starts
+	if !bytes.Equal(expected, out.Bytes()) {
+		t.Errorf("output doesn't match input (got vs expected):\n%s\n%s", hex.Dump(out.Bytes()), hex.Dump(expected))
+	}
+}
+
+func v3KeyReader(t *testing.T) io.Reader {
+	armorBlock, err := armor.Decode(bytes.NewBufferString(keySigV3Armor))
+	if err != nil {
+		t.Fatalf("armor Decode failed: %v", err)
+	}
+	return armorBlock.Body
+}
+
+// keySigV3Armor is some V3 public key I found in an SKS dump.
+// Old: Public Key Packet(tag 6)(141 bytes)
+//      Ver 4 - new
+//      Public key creation time - Fri Sep 16 17:13:54 CDT 1994
+//      Pub alg - unknown(pub 0)
+//      Unknown public key(pub 0)
+// Old: User ID Packet(tag 13)(39 bytes)
+//      User ID - Armin M. Warda <[email protected]>
+// Old: Signature Packet(tag 2)(149 bytes)
+//      Ver 4 - new
+//      Sig type - unknown(05)
+//      Pub alg - ElGamal Encrypt-Only(pub 16)
+//      Hash alg - unknown(hash 46)
+//      Hashed Sub: unknown(sub 81, critical)(1988 bytes)
+const keySigV3Armor = `-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: SKS 1.0.10
+
+mI0CLnoYogAAAQQA1qwA2SuJwfQ5bCQ6u5t20ulnOtY0gykf7YjiK4LiVeRBwHjGq7v30tGV
+5Qti7qqRW4Ww7CDCJc4sZMFnystucR2vLkXaSoNWoFm4Fg47NiisDdhDezHwbVPW6OpCFNSi
+ZAamtj4QAUBu8j4LswafrJqZqR9336/V3g8Yil2l48kABRG0J0FybWluIE0uIFdhcmRhIDx3
+YXJkYUBuZXBoaWxpbS5ydWhyLmRlPoiVAgUQLok2xwXR6zmeWEiZAQE/DgP/WgxPQh40/Po4
+gSkWZCDAjNdph7zexvAb0CcUWahcwiBIgg3U5ErCx9I5CNVA9U+s8bNrDZwgSIeBzp3KhWUx
+524uhGgm6ZUTOAIKA6CbV6pfqoLpJnRYvXYQU5mIWsNa99wcu2qu18OeEDnztb7aLA6Ra9OF
+YFCbq4EjXRoOrYM=
+=LPjs
+-----END PGP PUBLIC KEY BLOCK-----`

+ 155 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go

@@ -0,0 +1,155 @@
+// Copyright 2011 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 packet
+
+import (
+	"bytes"
+	"crypto/cipher"
+	"io"
+	"strconv"
+
+	"golang.org/x/crypto/openpgp/errors"
+	"golang.org/x/crypto/openpgp/s2k"
+)
+
+// This is the largest session key that we'll support. Since no 512-bit cipher
+// has even been seriously used, this is comfortably large.
+const maxSessionKeySizeInBytes = 64
+
+// SymmetricKeyEncrypted represents a passphrase protected session key. See RFC
+// 4880, section 5.3.
+type SymmetricKeyEncrypted struct {
+	CipherFunc   CipherFunction
+	s2k          func(out, in []byte)
+	encryptedKey []byte
+}
+
+const symmetricKeyEncryptedVersion = 4
+
+func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error {
+	// RFC 4880, section 5.3.
+	var buf [2]byte
+	if _, err := readFull(r, buf[:]); err != nil {
+		return err
+	}
+	if buf[0] != symmetricKeyEncryptedVersion {
+		return errors.UnsupportedError("SymmetricKeyEncrypted version")
+	}
+	ske.CipherFunc = CipherFunction(buf[1])
+
+	if ske.CipherFunc.KeySize() == 0 {
+		return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[1])))
+	}
+
+	var err error
+	ske.s2k, err = s2k.Parse(r)
+	if err != nil {
+		return err
+	}
+
+	encryptedKey := make([]byte, maxSessionKeySizeInBytes)
+	// The session key may follow. We just have to try and read to find
+	// out. If it exists then we limit it to maxSessionKeySizeInBytes.
+	n, err := readFull(r, encryptedKey)
+	if err != nil && err != io.ErrUnexpectedEOF {
+		return err
+	}
+
+	if n != 0 {
+		if n == maxSessionKeySizeInBytes {
+			return errors.UnsupportedError("oversized encrypted session key")
+		}
+		ske.encryptedKey = encryptedKey[:n]
+	}
+
+	return nil
+}
+
+// Decrypt attempts to decrypt an encrypted session key and returns the key and
+// the cipher to use when decrypting a subsequent Symmetrically Encrypted Data
+// packet.
+func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) ([]byte, CipherFunction, error) {
+	key := make([]byte, ske.CipherFunc.KeySize())
+	ske.s2k(key, passphrase)
+
+	if len(ske.encryptedKey) == 0 {
+		return key, ske.CipherFunc, nil
+	}
+
+	// the IV is all zeros
+	iv := make([]byte, ske.CipherFunc.blockSize())
+	c := cipher.NewCFBDecrypter(ske.CipherFunc.new(key), iv)
+	plaintextKey := make([]byte, len(ske.encryptedKey))
+	c.XORKeyStream(plaintextKey, ske.encryptedKey)
+	cipherFunc := CipherFunction(plaintextKey[0])
+	if cipherFunc.blockSize() == 0 {
+		return nil, ske.CipherFunc, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc)))
+	}
+	plaintextKey = plaintextKey[1:]
+	if l := len(plaintextKey); l == 0 || l%cipherFunc.blockSize() != 0 {
+		return nil, cipherFunc, errors.StructuralError("length of decrypted key not a multiple of block size")
+	}
+
+	return plaintextKey, cipherFunc, nil
+}
+
+// SerializeSymmetricKeyEncrypted serializes a symmetric key packet to w. The
+// packet contains a random session key, encrypted by a key derived from the
+// given passphrase. The session key is returned and must be passed to
+// SerializeSymmetricallyEncrypted.
+// If config is nil, sensible defaults will be used.
+func SerializeSymmetricKeyEncrypted(w io.Writer, passphrase []byte, config *Config) (key []byte, err error) {
+	cipherFunc := config.Cipher()
+	keySize := cipherFunc.KeySize()
+	if keySize == 0 {
+		return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc)))
+	}
+
+	s2kBuf := new(bytes.Buffer)
+	keyEncryptingKey := make([]byte, keySize)
+	// s2k.Serialize salts and stretches the passphrase, and writes the
+	// resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf.
+	err = s2k.Serialize(s2kBuf, keyEncryptingKey, config.Random(), passphrase, &s2k.Config{Hash: config.Hash(), S2KCount: config.PasswordHashIterations()})
+	if err != nil {
+		return
+	}
+	s2kBytes := s2kBuf.Bytes()
+
+	packetLength := 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize
+	err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength)
+	if err != nil {
+		return
+	}
+
+	var buf [2]byte
+	buf[0] = symmetricKeyEncryptedVersion
+	buf[1] = byte(cipherFunc)
+	_, err = w.Write(buf[:])
+	if err != nil {
+		return
+	}
+	_, err = w.Write(s2kBytes)
+	if err != nil {
+		return
+	}
+
+	sessionKey := make([]byte, keySize)
+	_, err = io.ReadFull(config.Random(), sessionKey)
+	if err != nil {
+		return
+	}
+	iv := make([]byte, cipherFunc.blockSize())
+	c := cipher.NewCFBEncrypter(cipherFunc.new(keyEncryptingKey), iv)
+	encryptedCipherAndKey := make([]byte, keySize+1)
+	c.XORKeyStream(encryptedCipherAndKey, buf[1:])
+	c.XORKeyStream(encryptedCipherAndKey[1:], sessionKey)
+	_, err = w.Write(encryptedCipherAndKey)
+	if err != nil {
+		return
+	}
+
+	key = sessionKey
+	return
+}

+ 103 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go

@@ -0,0 +1,103 @@
+// Copyright 2011 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 packet
+
+import (
+	"bytes"
+	"encoding/hex"
+	"io"
+	"io/ioutil"
+	"testing"
+)
+
+func TestSymmetricKeyEncrypted(t *testing.T) {
+	buf := readerFromHex(symmetricallyEncryptedHex)
+	packet, err := Read(buf)
+	if err != nil {
+		t.Errorf("failed to read SymmetricKeyEncrypted: %s", err)
+		return
+	}
+	ske, ok := packet.(*SymmetricKeyEncrypted)
+	if !ok {
+		t.Error("didn't find SymmetricKeyEncrypted packet")
+		return
+	}
+	key, cipherFunc, err := ske.Decrypt([]byte("password"))
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	packet, err = Read(buf)
+	if err != nil {
+		t.Errorf("failed to read SymmetricallyEncrypted: %s", err)
+		return
+	}
+	se, ok := packet.(*SymmetricallyEncrypted)
+	if !ok {
+		t.Error("didn't find SymmetricallyEncrypted packet")
+		return
+	}
+	r, err := se.Decrypt(cipherFunc, key)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	contents, err := ioutil.ReadAll(r)
+	if err != nil && err != io.EOF {
+		t.Error(err)
+		return
+	}
+
+	expectedContents, _ := hex.DecodeString(symmetricallyEncryptedContentsHex)
+	if !bytes.Equal(expectedContents, contents) {
+		t.Errorf("bad contents got:%x want:%x", contents, expectedContents)
+	}
+}
+
+const symmetricallyEncryptedHex = "8c0d04030302371a0b38d884f02060c91cf97c9973b8e58e028e9501708ccfe618fb92afef7fa2d80ddadd93cf"
+const symmetricallyEncryptedContentsHex = "cb1062004d14c4df636f6e74656e74732e0a"
+
+func TestSerializeSymmetricKeyEncrypted(t *testing.T) {
+	buf := bytes.NewBuffer(nil)
+	passphrase := []byte("testing")
+	const cipherFunc = CipherAES128
+	config := &Config{
+		DefaultCipher: cipherFunc,
+	}
+
+	key, err := SerializeSymmetricKeyEncrypted(buf, passphrase, config)
+	if err != nil {
+		t.Errorf("failed to serialize: %s", err)
+		return
+	}
+
+	p, err := Read(buf)
+	if err != nil {
+		t.Errorf("failed to reparse: %s", err)
+		return
+	}
+	ske, ok := p.(*SymmetricKeyEncrypted)
+	if !ok {
+		t.Errorf("parsed a different packet type: %#v", p)
+		return
+	}
+
+	if ske.CipherFunc != config.DefaultCipher {
+		t.Errorf("SKE cipher function is %d (expected %d)", ske.CipherFunc, config.DefaultCipher)
+	}
+	parsedKey, parsedCipherFunc, err := ske.Decrypt(passphrase)
+	if err != nil {
+		t.Errorf("failed to decrypt reparsed SKE: %s", err)
+		return
+	}
+	if !bytes.Equal(key, parsedKey) {
+		t.Errorf("keys don't match after Decrypt: %x (original) vs %x (parsed)", key, parsedKey)
+	}
+	if parsedCipherFunc != cipherFunc {
+		t.Errorf("cipher function doesn't match after Decrypt: %d (original) vs %d (parsed)", cipherFunc, parsedCipherFunc)
+	}
+}

+ 290 - 0
bashbrew/go/vendor/src/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go

@@ -0,0 +1,290 @@
+// Copyright 2011 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 packet
+
+import (
+	"crypto/cipher"
+	"crypto/sha1"
+	"crypto/subtle"
+	"golang.org/x/crypto/openpgp/errors"
+	"hash"
+	"io"
+	"strconv"
+)
+
+// SymmetricallyEncrypted represents a symmetrically encrypted byte string. The
+// encrypted contents will consist of more OpenPGP packets. See RFC 4880,
+// sections 5.7 and 5.13.
+type SymmetricallyEncrypted struct {
+	MDC      bool // true iff this is a type 18 packet and thus has an embedded MAC.
+	contents io.Reader
+	prefix   []byte
+}
+
+const symmetricallyEncryptedVersion = 1
+
+func (se *SymmetricallyEncrypted) parse(r io.Reader) error {
+	if se.MDC {
+		// See RFC 4880, section 5.13.
+		var buf [1]byte
+		_, err := readFull(r, buf[:])
+		if err != nil {
+			return err
+		}
+		if buf[0] != symmetricallyEncryptedVersion {
+			return errors.UnsupportedError("unknown SymmetricallyEncrypted version")
+		}
+	}
+	se.contents = r
+	return nil
+}
+
+// Decrypt returns a ReadCloser, from which the decrypted contents of the
+// packet can be read. An incorrect key can, with high probability, be detected
+// immediately and this will result in a KeyIncorrect error being returned.
+func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.ReadCloser, error) {
+	keySize := c.KeySize()
+	if keySize == 0 {
+		return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(c)))
+	}
+	if len(key) != keySize {
+		return nil, errors.InvalidArgumentError("SymmetricallyEncrypted: incorrect key length")
+	}
+
+	if se.prefix == nil {
+		se.prefix = make([]byte, c.blockSize()+2)
+		_, err := readFull(se.contents, se.prefix)
+		if err != nil {
+			return nil, err
+		}
+	} else if len(se.prefix) != c.blockSize()+2 {
+		return nil, errors.InvalidArgumentError("can't try ciphers with different block lengths")
+	}
+
+	ocfbResync := OCFBResync
+	if se.MDC {
+		// MDC packets use a different form of OCFB mode.
+		ocfbResync = OCFBNoResync
+	}
+
+	s := NewOCFBDecrypter(c.new(key), se.prefix, ocfbResync)
+	if s == nil {
+		return nil, errors.ErrKeyIncorrect
+	}
+
+	plaintext := cipher.StreamReader{S: s, R: se.contents}
+
+	if se.MDC {
+		// MDC packets have an embedded hash that we need to check.
+		h := sha1.New()
+		h.Write(se.prefix)
+		return &seMDCReader{in: plaintext, h: h}, nil
+	}
+
+	// Otherwise, we just need to wrap plaintext so that it's a valid ReadCloser.
+	return seReader{plaintext}, nil
+}
+
+// seReader wraps an io.Reader with a no-op Close method.
+type seReader struct {
+	in io.Reader
+}
+
+func (ser seReader) Read(buf []byte) (int, error) {
+	return ser.in.Read(buf)
+}
+
+func (ser seReader) Close() error {
+	return nil
+}
+
+const mdcTrailerSize = 1 /* tag byte */ + 1 /* length byte */ + sha1.Size
+
+// An seMDCReader wraps an io.Reader, maintains a running hash and keeps hold
+// of the most recent 22 bytes (mdcTrailerSize). Upon EOF, those bytes form an
+// MDC packet containing a hash of the previous contents which is checked
+// against the running hash. See RFC 4880, section 5.13.
+type seMDCReader struct {
+	in          io.Reader
+	h           hash.Hash
+	trailer     [mdcTrailerSize]byte
+	scratch     [mdcTrailerSize]byte
+	trailerUsed int
+	error       bool
+	eof         bool
+}
+
+func (ser *seMDCReader) Read(buf []byte) (n int, err error) {
+	if ser.error {
+		err = io.ErrUnexpectedEOF
+		return
+	}
+	if ser.eof {
+		err = io.EOF
+		return
+	}
+
+	// If we haven't yet filled the trailer buffer then we must do that
+	// first.
+	for ser.trailerUsed < mdcTrailerSize {
+		n, err = ser.in.Read(ser.trailer[ser.trailerUsed:])
+		ser.trailerUsed += n
+		if err == io.EOF {
+			if ser.trailerUsed != mdcTrailerSize {
+				n = 0
+				err = io.ErrUnexpectedEOF
+				ser.error = true
+				return
+			}
+			ser.eof = true
+			n = 0
+			return
+		}
+
+		if err != nil {
+			n = 0
+			return
+		}
+	}
+
+	// If it's a short read then we read into a temporary buffer and shift
+	// the data into the caller's buffer.
+	if len(buf) <= mdcTrailerSize {
+		n, err = readFull(ser.in, ser.scratch[:len(buf)])
+		copy(buf, ser.trailer[:n])
+		ser.h.Write(buf[:n])
+		copy(ser.trailer[:], ser.trailer[n:])
+		copy(ser.trailer[mdcTrailerSize-n:], ser.scratch[:])
+		if n < len(buf) {
+			ser.eof = true
+			err = io.EOF
+		}
+		return
+	}
+
+	n, err = ser.in.Read(buf[mdcTrailerSize:])
+	copy(buf, ser.trailer[:])
+	ser.h.Write(buf[:n])
+	copy(ser.trailer[:], buf[n:])
+
+	if err == io.EOF {
+		ser.eof = true
+	}
+	return
+}
+
+// This is a new-format packet tag byte for a type 19 (MDC) packet.
+const mdcPacketTagByte = byte(0x80) | 0x40 | 19
+
+func (ser *seMDCReader) Close() error {
+	if ser.error {
+		return errors.SignatureError("error during reading")
+	}
+
+	for !ser.eof {
+		// We haven't seen EOF so we need to read to the end
+		var buf [1024]byte
+		_, err := ser.Read(buf[:])
+		if err == io.EOF {
+			break
+		}
+		if err != nil {
+			return errors.SignatureError("error during reading")
+		}
+	}
+
+	if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size {
+		return errors.SignatureError("MDC packet not found")
+	}
+	ser.h.Write(ser.trailer[:2])
+
+	final := ser.h.Sum(nil)
+	if subtle.ConstantTimeCompare(final, ser.trailer[2:]) != 1 {
+		return errors.SignatureError("hash mismatch")
+	}
+	return nil
+}
+
+// An seMDCWriter writes through to an io.WriteCloser while maintains a running
+// hash of the data written. On close, it emits an MDC packet containing the
+// running hash.
+type seMDCWriter struct {
+	w io.WriteCloser
+	h hash.Hash
+}
+
+func (w *seMDCWriter) Write(buf []byte) (n int, err error) {
+	w.h.Write(buf)
+	return w.w.Write(buf)
+}
+
+func (w *seMDCWriter) Close() (err error) {
+	var buf [mdcTrailerSize]byte
+
+	buf[0] = mdcPacketTagByte
+	buf[1] = sha1.Size
+	w.h.Write(buf[:2])
+	digest := w.h.Sum(nil)
+	copy(buf[2:], digest)
+
+	_, err = w.w.Write(buf[:])
+	if err != nil {
+		return
+	}
+	return w.w.Close()
+}
+
+// noOpCloser is like an ioutil.NopCloser, but for an io.Writer.
+type noOpCloser struct {
+	w io.Writer
+}
+
+func (c noOpCloser) Write(data []byte) (n int, err error) {
+	return c.w.Write(data)
+}
+
+func (c noOpCloser) Close() error {
+	return nil
+}
+
+// SerializeSymmetricallyEncrypted serializes a symmetrically encrypted packet
+// to w and returns a WriteCloser to which the to-be-encrypted packets can be
+// written.
+// If config is nil, sensible defaults will be used.
+func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, key []byte, config *Config) (contents io.WriteCloser, err error) {
+	if c.KeySize() != len(key) {
+		return nil, errors.InvalidArgumentError("SymmetricallyEncrypted.Serialize: bad key length")
+	}
+	writeCloser := noOpCloser{w}
+	ciphertext, err := serializeStreamHeader(writeCloser, packetTypeSymmetricallyEncryptedMDC)
+	if err != nil {
+		return
+	}
+
+	_, err = ciphertext.Write([]byte{symmetricallyEncryptedVersion})
+	if err != nil {
+		return
+	}
+
+	block := c.new(key)
+	blockSize := block.BlockSize()
+	iv := make([]byte, blockSize)
+	_, err = config.Random().Read(iv)
+	if err != nil {
+		return
+	}
+	s, prefix := NewOCFBEncrypter(block, iv, OCFBNoResync)
+	_, err = ciphertext.Write(prefix)
+	if err != nil {
+		return
+	}
+	plaintext := cipher.StreamWriter{S: s, W: ciphertext}
+
+	h := sha1.New()
+	h.Write(iv)
+	h.Write(iv[blockSize-2:])
+	contents = &seMDCWriter{w: plaintext, h: h}
+	return
+}

部分文件因为文件数量过多而无法显示