├── .gitignore ├── Goopfile ├── Goopfile.lock ├── LICENSE.md ├── Makefile ├── PATCHES.md ├── README.md ├── bindata.go ├── build_ruby.go ├── build_ruby_test.go ├── client.go └── data ├── Dockerfile-centos.template ├── Dockerfile-xenial.template ├── Dockerfile.template └── patches ├── 1.0.0 ├── 01_for_tests └── 02_for_tests ├── 1.9.3-p551 └── 01_strict_hostname_checking.patch ├── 2.0.0-p0 └── 01_readline.patch ├── 2.0.0-p195 └── 01_readline.patch ├── 2.0.0-p247 └── 01_readline.patch ├── 2.0.0-p353 └── 01_readline.patch ├── 2.0.0-p451 └── 01_readline.patch ├── 2.1.0 └── 01_readline.patch └── 2.1.1 └── 01_readline.patch /.gitignore: -------------------------------------------------------------------------------- 1 | ruby*deb 2 | ruby*rpm 3 | bin/build_ruby 4 | *.a 5 | *.o 6 | *.so 7 | .DS_Store 8 | bindata.go 9 | RELEASE.md 10 | -------------------------------------------------------------------------------- /Goopfile: -------------------------------------------------------------------------------- 1 | github.com/google/uuid/uuid 2 | github.com/urfave/cli 3 | github.com/fsouza/go-dockerclient 4 | github.com/wsxiaoys/terminal/color 5 | -------------------------------------------------------------------------------- /Goopfile.lock: -------------------------------------------------------------------------------- 1 | github.com/Sirupsen/logrus #f3cfb454f4c209e6668c95216c4744b8fddb2356 2 | github.com/docker/docker #e904f58e199836fa43ee1c6736e689ef58e4fe10 3 | github.com/docker/engine-api #2e14eff07a3a024485694527a29275b7d3a57462 4 | github.com/docker/go-units #f2d77a61e3c169b43402a0a1e84f06daf29b8190 5 | github.com/fsouza/go-dockerclient #1a3d0cfd7814bbfe44ada7617654948c99891749 6 | github.com/google/uuid/uuid #f3f4b54b2fabcf1f11dcc939025bb0c109b00ed8 7 | github.com/gorilla/mux #9fa818a44c2bf1396a17f9d5a3c0f6dd39d2ff8e 8 | github.com/hashicorp/go-cleanhttp #ad28ea4487f05916463e2423a55166280e8254b5 9 | github.com/opencontainers/runc #629e35666d31f743090452416c8df207d9fdbd34 10 | github.com/urfave/cli #1efa31f08b9333f1bd4882d61f9d668a70cd902e 11 | github.com/wsxiaoys/terminal/color #0940f3fc43a0ed42d04916b1c04578462c650b09 12 | golang.org/x/net #8e573f4005aa312856df2ea97c32b9beac70dd89 13 | gopkg.in/yaml.v2 #a83829b6f1293c91addabc89d0571c246397bbf4 14 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (C) 2014 by Will Jessop 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: assets 2 | $(GOPATH)/bin/goop go build -o bin/build_ruby 3 | 4 | setup: 5 | go get -u github.com/jteeuwen/go-bindata/go-bindata... 6 | go get -u github.com/karmakaze/goop 7 | 8 | test: assets 9 | $(GOPATH)/bin/goop go test 10 | 11 | assets: 12 | ${GOPATH}/bin/go-bindata data/... 13 | 14 | clean: 15 | rm -f bin/* 16 | rm -f *deb 17 | 18 | deps: 19 | $(GOPATH)/bin/goop install 20 | 21 | update_deps: 22 | $(GOPATH)/bin/goop update 23 | 24 | package: 25 | $(GOPATH)/bin/goop go build -o /tmp/tmp_build 26 | GOOS=linux make 27 | $(eval VERSION = $(shell /tmp/tmp_build -v)) fpm -s dir -t deb -n build_ruby -a amd64 -v ${VERSION} bin 28 | -------------------------------------------------------------------------------- /PATCHES.md: -------------------------------------------------------------------------------- 1 | # Patches 2 | 3 | 1.9.3: 4 | 5 | Requires strict hostname checking patch to be secure. Currently only applied to -p551, if you need other 1.9.3 versions please submit a PR or open an issue and I'll add it. 6 | 7 | 2.0.0-pX: 8 | 9 | Some -p levels require a readline patch 10 | 11 | 2.1.0 and 2.1.1 require: 12 | 13 | https://gist.github.com/mislav/a18b9d7f0dc5b9efc162 14 | 15 | 2.1.2 builds cleanly 16 | 17 | 2.2.x build cleanly 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Build ruby packages 2 | 3 | *build_ruby* is a tool for building Ruby packages using Docker. Currently it can build .deb packages for Ubuntu and .rpms for Centos. The packages that it creates will install Ruby to ````/opt/ruby````, eg ````/opt/ruby2.1.0```` or ````/opt/ruby1.9.3-p429````. This is to allow for multiple concurrent installs (that we symlink into the rbenv dir) and is how we install Ruby at [Basecamp](https://basecamp.com/). I have a branch to default to a more traditional path that I might release if anyone is interested. 4 | 5 | ## Installation 6 | 7 | ### 1 Install Docker and tools: 8 | 9 | #### 1.1 Linux 10 | 11 | [Follow the instructions here](http://docs.docker.io/installation/) 12 | 13 | #### 1.2 OS X 14 | 15 | ##### 1.2.1 An existing Docker host somewhere 16 | 17 | Advanced usage! If you've got a Docker instance running somewhere already, for instance another server, you need to set these environment variables: 18 | 19 | export DOCKER_CERT_PATH=$HOME/path/to/docker/certs 20 | export DOCKER_HOST=tcp://192.168.1.79:2376 21 | export DOCKER_TLS_VERIFY=1 22 | 23 | Change as needed. The files required in the certs dir are: 24 | 25 | * ca.pem: The ca certificate 26 | * cert.pem: The client certificate 27 | * key.pem: The client key 28 | 29 | For simpler usage see section 1.2.2, "Run Docker locally using a VM" 30 | 31 | ##### 1.2.2 Run Docker locally using a VM 32 | 33 | On [this page](http://docs.docker.io/installation/mac/) follow these tasks: 34 | 35 | * Installing VirtualBox 36 | * Installing docker-machine using HomeBrew 37 | 38 | Next, [create and start a docker-machine image](https://docs.docker.com/machine/get-started/) 39 | 40 | You can now run docker commands locally on your mac. 41 | 42 | #### 1.3 Install pre-requisite tools 43 | 44 | $ make setup 45 | 46 | ## Running it 47 | 48 | ### 2. Clone and build this repo 49 | 50 | $ git clone git@github.com:wjessop/build_ruby.git 51 | $ cd build_ruby 52 | $ make 53 | 54 | ## Usage 55 | 56 | $ bin/build_ruby -r 2.1.0 -i 37s~precise -d ubuntu:12.04 57 | $ bin/build_ruby -r 2.1.0 -d ubuntu:13.04 58 | $ bin/build_ruby -r 2.1.0 59 | 60 | ### Other options 61 | 62 | #### -c, --cpus 63 | 64 | Specify the number of CPUs to use in the make process. If omitted defaults to the number of CPUs in your local machine (useful if you're building using a local Docker daemon), but if you're building on a VM, or a remote Docker installation specify this number to match the CPUs available: 65 | 66 | $ bin/build_ruby -r 2.1.0 -c 16 67 | $ bin/build_ruby -r 2.1.0 --cpus 16 68 | 69 | ### Building 70 | 71 | Just run: 72 | 73 | make 74 | 75 | If you need to update the deps run: 76 | 77 | make update_deps 78 | 79 | See the Makefile for more functions. 80 | 81 | ### Testing 82 | 83 | make test 84 | 85 | ## Troubleshooting 86 | 87 | ### You get an error ````dial unix /var/run/docker.sock: no such file or directory```` 88 | 89 | 2014/05/08 21:50:45 dial unix /var/run/docker.sock: no such file or directory 90 | 91 | Make sure you ran ````export DOCKER_HOST=tcp://localhost:4243```` in the terminal you are trying to use docker/build_ruby from 92 | 93 | ## Todo 94 | 95 | * Test that a package test is actually created, perhaps requiring Docker to be running 96 | * Support Other Linux distros/package types 97 | 98 | ## How to contribute 99 | 100 | Here's the most direct way to get your work merged into the project: 101 | 102 | 1. Fork the project 103 | 2. Clone down your fork 104 | 3. Create a feature branch 105 | 4. Add your feature + tests 106 | 5. Document new features in the README 107 | 6. Make sure everything still passes by running the tests 108 | 7. If necessary, rebase your commits into logical chunks, without errors 109 | 8. Push the branch up 110 | 9. Send a pull request for your branch 111 | 112 | Take a look at the TODO list or known issues for some inspiration if you need it, or email me. If you're going to make a major change ask first to maje sure it's in line with the project goals. 113 | 114 | ## Authors 115 | 116 | * [Will Jessop](mailto:will@willj.net) 117 | 118 | ## Background reading 119 | 120 | * [The Docker API docs](http://docs.docker.io/reference/api/docker_remote_api_v1.10/) 121 | * [The Ruby download page](http://docs.docker.io/reference/api/docker_remote_api_v1.10/) 122 | * [The go-dockerclient lib](https://github.com/fsouza/go-dockerclient) 123 | * [go-bindata Github page](github.com/jteeuwen/go-bindata) 124 | 125 | ## LICENSE 126 | 127 | See LICENSE.md 128 | -------------------------------------------------------------------------------- /bindata.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-bindata. 2 | // sources: 3 | // data/Dockerfile-centos.template 4 | // data/Dockerfile-xenial.template 5 | // data/Dockerfile.template 6 | // data/patches/1.0.0/01_for_tests 7 | // data/patches/1.0.0/02_for_tests 8 | // data/patches/1.9.3-p551/01_strict_hostname_checking.patch 9 | // data/patches/2.0.0-p0/01_readline.patch 10 | // data/patches/2.0.0-p195/01_readline.patch 11 | // data/patches/2.0.0-p247/01_readline.patch 12 | // data/patches/2.0.0-p353/01_readline.patch 13 | // data/patches/2.0.0-p451/01_readline.patch 14 | // data/patches/2.1.0/01_readline.patch 15 | // data/patches/2.1.1/01_readline.patch 16 | // DO NOT EDIT! 17 | 18 | package main 19 | 20 | import ( 21 | "bytes" 22 | "compress/gzip" 23 | "fmt" 24 | "io" 25 | "io/ioutil" 26 | "os" 27 | "path/filepath" 28 | "strings" 29 | "time" 30 | ) 31 | 32 | func bindataRead(data []byte, name string) ([]byte, error) { 33 | gz, err := gzip.NewReader(bytes.NewBuffer(data)) 34 | if err != nil { 35 | return nil, fmt.Errorf("Read %q: %v", name, err) 36 | } 37 | 38 | var buf bytes.Buffer 39 | _, err = io.Copy(&buf, gz) 40 | clErr := gz.Close() 41 | 42 | if err != nil { 43 | return nil, fmt.Errorf("Read %q: %v", name, err) 44 | } 45 | if clErr != nil { 46 | return nil, err 47 | } 48 | 49 | return buf.Bytes(), nil 50 | } 51 | 52 | type asset struct { 53 | bytes []byte 54 | info os.FileInfo 55 | } 56 | 57 | type bindataFileInfo struct { 58 | name string 59 | size int64 60 | mode os.FileMode 61 | modTime time.Time 62 | } 63 | 64 | func (fi bindataFileInfo) Name() string { 65 | return fi.name 66 | } 67 | func (fi bindataFileInfo) Size() int64 { 68 | return fi.size 69 | } 70 | func (fi bindataFileInfo) Mode() os.FileMode { 71 | return fi.mode 72 | } 73 | func (fi bindataFileInfo) ModTime() time.Time { 74 | return fi.modTime 75 | } 76 | func (fi bindataFileInfo) IsDir() bool { 77 | return false 78 | } 79 | func (fi bindataFileInfo) Sys() interface{} { 80 | return nil 81 | } 82 | 83 | var _dataDockerfileCentosTemplate = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x84\x55\xeb\x6e\x1b\x37\x13\xfd\xaf\xa7\x18\x38\x1f\x10\xe0\x4b\xb8\x1b\xc5\x8e\x63\xb9\xf5\x0f\x55\x8a\x0b\x3b\x8e\xaf\x75\x0c\xb4\x29\x12\x6a\xc9\x95\x68\x73\xc9\x05\xc9\x95\x7c\xa9\xfa\xec\x3d\xe4\xae\x65\x39\x29\x50\x03\x16\x39\x87\xc3\xd9\xb9\x9c\x19\xee\x9f\x9f\x7c\xa2\x87\x87\x6c\xac\x7c\x70\x76\xb9\xec\x9d\x5f\x1e\xd3\x5d\x53\x51\x53\x0b\x1e\x24\xb1\xbb\x15\xa2\x8c\x0f\x5c\x6b\x40\x34\x2d\x8a\xf8\xcf\x8a\x57\xaf\xa8\xe2\x37\x92\x78\x13\x6c\xda\xdc\x48\x67\xa4\x66\x42\xce\xa5\x26\x57\x57\x6c\xd2\x28\x2d\xe8\x4b\x8f\xf0\x37\xd5\x6a\x52\x74\x67\xd8\x96\xa5\xea\x84\xa9\x98\x54\xdd\xd6\x14\x8d\xf3\xd2\x77\x52\x7b\xcf\x49\x2e\xb4\x32\xb2\x03\x6d\x2d\x8d\xf7\xfa\xc9\xd0\x1d\xaf\x1e\xa5\x7b\x88\xcf\xee\xc2\x9c\xa6\xc0\x5d\xef\x05\x1d\x74\x01\x70\xaa\xac\x93\xf8\x11\x70\x96\xe6\xd2\x79\x65\x0d\xd9\x92\xce\x9b\xc9\x5d\x46\x43\x12\xb2\x8e\x62\x59\x57\x34\xb5\xa1\x4b\x85\x20\x6e\x04\x29\x6f\x5e\x06\xd8\x2a\x6c\x55\xf3\xa0\x26\x5a\xd2\x42\x85\x19\x39\x5c\xa5\x7e\xb6\x93\xbd\xa7\xc5\x4c\x15\x33\x28\x62\xc3\x43\x5c\xbb\xc4\xc1\xc2\x5c\xf1\x98\xca\xde\x70\x3c\xa6\x59\x08\xb5\xdf\xcd\x73\x2f\x8d\x28\x78\xc8\x60\x31\x17\x3a\xff\x85\x8b\xc3\x23\xf1\xa6\x1e\xde\x9e\xf5\x0f\x3f\x8f\x0e\xb7\xae\x8f\x46\xa1\x7c\xf7\xc9\xed\xef\x7c\xd8\x1c\x0e\x26\xe6\xed\xfc\xe3\x45\xc5\xcd\xef\xe5\x49\xe8\x8f\xcf\xce\x06\xfd\xfb\xeb\xd1\x74\x91\xf7\xb7\xdf\xf5\xf3\xe8\x05\x7b\x9b\x6d\x66\x6f\xbe\x6e\xbe\xf7\x7f\x17\xd2\x04\xeb\xbf\xf2\x4a\x6c\x6f\x65\x28\x06\xe5\xa1\xaa\xf3\x54\xd0\x28\x31\xd5\x02\xff\x71\x2b\xe9\xff\xb1\x91\xdb\x3a\x24\xd5\xa4\x99\x4f\x94\xc9\xa7\xb2\xda\x78\x4d\x1b\x5d\x7c\x71\x8b\x94\xc5\x85\x31\x1c\x0b\xe5\xf6\xf2\xc6\xbb\xa8\xda\x82\xc6\x32\x27\x6c\xf1\x24\xa8\x8d\x3f\x93\xf5\x54\xa4\xc8\x42\xbb\x30\xda\x72\x71\xe9\xf4\x72\xf9\x17\xaa\x46\xf6\xf6\x7e\x94\xbc\xec\x3d\x3c\x38\x6e\xa6\x92\xb2\x53\x1e\x8a\x99\xf4\xcb\x65\xcc\x22\x2e\x2d\x97\x94\xe3\x14\x69\x04\x7d\xaf\x4e\xce\x3f\x8e\x0f\xce\xd7\x02\x83\x46\xac\xeb\xe7\xb6\xcc\x1d\xc3\x4b\xeb\x48\xa1\x30\xf4\x2d\x05\xa2\x3d\xe5\xff\xcf\xea\x68\xf8\xdb\x4f\x24\x2c\xa5\x2d\xb1\xfa\x0d\xfd\x4c\xff\x53\x11\x32\x32\x5d\x1c\xed\x1f\x0d\x7f\xbd\xd8\x7b\xc9\x2a\xee\x8a\xd9\xde\xed\xce\x36\xdb\xde\x22\x76\xb2\x49\xac\x44\x44\x25\xf7\x01\x47\x20\x04\x9b\x02\x9a\x82\xd8\xc4\xae\x52\xd7\x5c\xc9\xdb\xe0\x38\x56\xa8\x35\xa6\xf1\x52\xb0\x9a\x3b\x5e\xc9\x20\x5d\x8b\x42\x44\xea\x11\x9a\xf4\x2d\xa0\xad\x99\xa6\x9f\x56\xac\x94\xf7\x0a\x48\xa9\xa4\x16\x4c\x19\x15\x14\xd7\xea\x1e\x81\xe1\xbc\x33\x39\xe7\x4e\xf1\xc8\x4a\x76\x55\x5b\x65\x60\x9b\x01\x89\xfe\x5c\x2d\xb0\x4a\x86\x36\x87\x8d\x78\x43\xc8\x42\xc3\x81\x80\xac\x30\x5e\x46\x4d\x94\x31\xc8\x0a\x3e\xe0\x54\x55\xb5\x56\x85\x0a\xac\x6c\x4c\x91\x74\xd6\xf4\xd3\xed\xda\xc9\x22\xf6\xc5\xfa\x81\x7f\x8c\xa4\xb8\xc1\xc1\x44\x85\xd6\xd7\xb6\x5b\x08\x1f\x10\x7b\xca\xdb\xc1\xce\x60\xb0\xdb\x1f\x0c\x06\x84\xac\x9d\x1e\x8c\x5e\x52\x96\x17\xd6\x94\x6a\xda\xa0\x2f\x63\xdf\x32\x06\xeb\xa5\xba\x6d\x09\xa4\x6d\xc1\x75\x87\x4b\x13\xc3\x63\x7e\x86\x64\x89\x0e\x13\xca\x27\xb0\x23\x22\x03\xc7\x9e\x6b\x47\x4e\x31\x27\x35\x7c\x9c\x4b\x74\xef\x85\x94\x95\xa7\x60\xc9\x1a\x7d\x47\xbc\x2c\x65\x11\xc8\xdb\x4a\xa2\x85\x07\xe4\xa5\x53\x28\x01\x58\x83\xe5\x35\x4d\x9a\x40\xa8\x4a\x6c\x79\x70\x05\x1f\x4d\x83\xce\x07\x59\xef\xf6\x5e\xc0\x58\xfc\x8b\xd4\x48\x30\xbb\xde\x59\x0d\xca\xf1\x87\x8b\xdf\xc0\xc5\xbd\xc4\x45\x74\x46\xd2\x0e\x71\x28\x80\xc9\xc9\x64\xba\x82\x8d\x69\x77\xdd\xc5\xd7\xb4\xe0\x9e\x26\xce\xde\x48\x93\xd1\x05\xea\x10\x02\x6a\x46\x2a\x8e\x22\x28\x05\x1b\xed\x2c\x2c\x1c\x8d\x0c\x0a\xc9\x35\x8c\x04\x81\x91\x63\xdd\x8d\xa7\x12\x6e\xee\xf6\xd6\x7c\x42\x0f\x1c\x37\xd5\xe8\xf4\xb2\xa3\xff\xfa\xd7\x7e\x74\xf3\xa9\x89\xda\x5e\xc1\xa8\x68\x67\x29\xf3\x84\xa6\x7e\x14\x42\x1a\x22\x9d\x60\xda\x09\xd8\x49\x3c\xf6\xe5\x10\x0d\x82\xde\xec\xa0\x39\x7d\xdf\x88\xdd\x09\xe0\x03\x90\x2f\xd1\x07\xee\x25\x65\xf1\xec\xa9\xf8\xf2\x08\x3e\x7b\x33\x56\xe8\xda\xe3\xb1\xc2\xfe\xed\x15\x01\xfc\xdd\x43\xb2\xc2\x9f\xbf\x28\xeb\xdf\x5b\x7b\x5a\x56\xf0\x0f\x6f\x0c\x6b\x47\x54\xbe\x96\xa9\x9a\x72\x04\xb6\xaf\xb4\x3c\x46\x8b\xaf\x82\x05\x9b\x7b\xff\x04\x00\x00\xff\xff\xb8\xfb\xaf\xce\x73\x07\x00\x00") 84 | 85 | func dataDockerfileCentosTemplateBytes() ([]byte, error) { 86 | return bindataRead( 87 | _dataDockerfileCentosTemplate, 88 | "data/Dockerfile-centos.template", 89 | ) 90 | } 91 | 92 | func dataDockerfileCentosTemplate() (*asset, error) { 93 | bytes, err := dataDockerfileCentosTemplateBytes() 94 | if err != nil { 95 | return nil, err 96 | } 97 | 98 | info := bindataFileInfo{name: "data/Dockerfile-centos.template", size: 1907, mode: os.FileMode(420), modTime: time.Unix(1467243494, 0)} 99 | a := &asset{bytes: bytes, info: info} 100 | return a, nil 101 | } 102 | 103 | var _dataDockerfileXenialTemplate = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x6c\x54\x4d\x6f\xe3\x36\x10\xbd\xfb\x57\x0c\xb2\x05\x16\x28\x96\x56\x83\xb6\x41\x9c\xd6\x87\x20\x6e\x8a\xa0\x6d\x12\x38\x4d\x73\xe8\x16\x58\x5a\x1c\x29\x6c\x28\x52\x20\xa9\x38\x1f\xf5\x7f\xef\x23\x25\x79\x95\x6e\x7d\xb0\x86\x6f\x3e\x38\x9c\x79\x33\xe7\xeb\xab\xdf\xe8\xf5\x75\xbe\xd2\x21\x7a\xb7\xdb\xcd\xd6\xb7\x97\x24\xdb\x28\x6a\x8e\xd4\xb5\x4a\x46\x7e\x03\x69\x1b\xa2\x34\x86\xc4\x33\x6d\x3a\x6d\x94\xe0\x10\xd8\x46\x2d\x0d\x7d\x9c\x11\x7e\x46\x6f\xca\x23\xa1\xf8\x31\x49\x55\xa5\x47\xb1\x56\x9b\x66\x94\x6d\xd9\xf9\xc0\xe1\xfb\x7c\xde\xbb\x79\x96\xca\x68\xcb\xa3\x55\x08\x66\x14\x9f\x65\xd3\xcb\x2f\x38\x1c\xd6\x13\x3f\x44\x32\xe4\xbb\xcd\x73\xfe\x4b\x8a\x9c\xee\x9f\x07\x35\x37\x07\x1f\xe8\x60\xc8\x37\x89\x55\x9b\x11\x21\x36\xda\x2a\xed\x97\x45\x17\x7c\x01\xb9\x07\xad\x13\x5e\xb9\xf2\xf3\x41\x1f\xfc\x35\xcb\xb1\xf2\x15\xa9\x44\x6e\x6b\x8d\x93\xea\xd6\x9b\xdd\xee\x9f\x28\x3d\xb9\xa7\x97\x33\x2a\x62\xd3\xce\x5e\x5f\xbd\xb4\x35\xd3\xfc\x5a\xc6\xf2\x9e\xc3\x6e\x77\xba\x5a\x25\xa7\xdd\x8e\x0a\x68\xd9\x2a\xd4\xf6\xee\x6a\xfd\xcb\xea\x62\x9d\x5d\x8a\x9c\x2f\x2c\xd6\xf8\xfe\xc1\x3e\x68\x67\x87\xf2\x57\xce\x93\x46\xa5\xe9\x53\x4a\xaf\x30\x81\x8a\xaf\xe7\x6d\x0a\xfc\xe9\x07\x52\x8e\xb2\x48\xa2\xfd\x86\x7e\xa4\xaf\x74\x82\x6c\xdf\xa4\xb3\xf3\x5f\x4f\x7f\xbe\x59\xbe\x17\x8d\xf4\xe5\xfd\xf2\xe9\xf8\x48\x1c\x7d\x47\xe2\xea\x5b\x12\x15\x9e\x54\xc9\x10\xa1\x8a\xf0\xad\x01\xd5\x68\x09\x89\xbb\xdc\xcd\x3b\x7e\x8a\x5e\xe2\x0b\xb3\xce\x76\x81\x95\x68\xa5\x97\x0d\x47\xf6\x3d\x8a\x23\xfa\x8c\xa7\x71\xe8\x01\xe3\x6c\x9d\xff\xfa\x63\xa3\x43\xd0\x40\x2a\xcd\x60\x85\xb6\x3a\x71\x42\xbf\xe0\x61\xd0\x0f\x21\x1f\xa5\xd7\x72\x63\x18\x48\xeb\xb4\x45\x6c\x01\x24\xe5\x73\xb7\xc5\x97\x05\x38\x88\x18\xc9\x43\x71\x69\x90\x40\x44\x55\x84\xac\x92\x25\xfa\x18\xb9\x41\x0e\xd0\xea\xa6\x35\xba\xd4\x51\x54\x9d\x2d\xb3\xcd\xc4\x3e\x7b\xb7\x9e\x4b\xd8\xab\xa9\x22\x8c\x2f\x29\x1f\xa0\xd8\xe8\xd8\xe7\x5a\xba\x06\x15\x25\x5c\xa0\x96\x3a\xb8\xc5\xf1\x62\x71\x72\xb8\x58\x2c\x08\x55\xbb\xbe\x38\x7b\x4f\xf3\xa2\x74\xb6\xd2\x75\xe7\x39\xb3\x4e\x08\x44\xaf\xf4\x53\xcf\x20\xe3\xca\x81\xfc\x42\xb0\x4d\xcf\x13\xe1\x1e\xc5\x52\x03\xa6\x74\xc8\xe0\xc0\x44\x01\x92\xbd\xb5\x4e\x9c\x12\x9e\x0d\x72\x7c\xe4\xd9\x3b\xba\x61\x6e\x02\x45\x47\xce\x9a\x67\x92\x55\xc5\x65\xa4\xe0\x1a\xa6\xc3\xf9\x82\x02\x7b\x8d\x16\x80\x35\xf8\x7c\xc0\x10\x46\x42\x57\x08\x8f\x00\x57\x70\x69\x23\x1f\x98\x42\xe4\xf6\x64\xf6\x0e\xc1\xd2\x2f\x51\x23\xc3\xe2\xef\xe3\xfd\x00\xaf\x7e\xba\xf9\x1d\x5c\x5c\x66\x2e\x62\x34\xb2\x75\xbc\x47\x21\xc0\xe4\x1c\x32\xbb\x40\xb0\xbd\x34\x38\x7e\xa0\xad\x0c\xb4\xf1\xee\x81\xed\x9c\x6e\xd0\x87\x18\xd1\x33\xd2\x69\x5d\xc0\x28\xba\x14\x67\xeb\x90\x68\x62\x50\xcc\xa9\x35\xd2\xaa\x40\x5b\xe7\x1f\x02\x55\x48\xf3\x64\x36\xc9\x09\x33\x70\xd9\x35\x67\xd7\xb7\x03\xfd\xa7\xb7\x7d\x99\xe6\xe7\x21\xea\x67\xa5\x6d\x86\x4d\x20\x02\x61\xaa\xc7\x43\x24\xc5\x9b\xf1\x60\xfb\x0d\x31\x9c\x64\x9a\xcb\x53\x0c\x08\x66\x73\x80\x1e\xe9\xbf\x83\x38\x68\x00\x5f\x80\x7c\x99\x3e\x48\x2f\x1b\xab\xc9\x8e\xfb\x38\x81\xc6\x65\x37\xc5\xf6\x5b\x6f\x0a\xfe\xcf\xfa\xeb\x15\x6f\x36\xe0\x54\x31\xae\xc2\x29\xb6\xdf\x89\x7b\xf0\x8b\xe5\x28\xfa\xed\x54\x4c\x8a\xd4\x52\x81\x37\x9d\x6b\xc3\x97\x98\xee\xfd\x3b\x41\xe4\xd9\xbf\x01\x00\x00\xff\xff\x04\x2f\xf6\xea\x0b\x06\x00\x00") 104 | 105 | func dataDockerfileXenialTemplateBytes() ([]byte, error) { 106 | return bindataRead( 107 | _dataDockerfileXenialTemplate, 108 | "data/Dockerfile-xenial.template", 109 | ) 110 | } 111 | 112 | func dataDockerfileXenialTemplate() (*asset, error) { 113 | bytes, err := dataDockerfileXenialTemplateBytes() 114 | if err != nil { 115 | return nil, err 116 | } 117 | 118 | info := bindataFileInfo{name: "data/Dockerfile-xenial.template", size: 1547, mode: os.FileMode(420), modTime: time.Unix(1467328168, 0)} 119 | a := &asset{bytes: bytes, info: info} 120 | return a, nil 121 | } 122 | 123 | var _dataDockerfileTemplate = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x6c\x54\x5b\x4f\xe4\x36\x14\x7e\x9f\x5f\x71\xc4\x56\x5a\xa9\xc2\x93\xa2\x6d\x11\x43\xcb\x03\x62\x4a\x85\xda\x02\x1a\x4a\x79\xe8\x56\x5a\x4f\x7c\x12\x5c\x1c\x3b\xb2\x1d\x86\x4b\xe7\xbf\xf7\xb3\x93\xcc\x86\xee\xce\xc3\xd8\xfe\xce\x25\xe7\xf2\x9d\x73\xbe\xba\xfa\x9d\x5e\x5f\xe7\x4b\x1d\xa2\x77\xdb\xed\x6c\x75\x7b\x49\xb2\x8d\xa2\xe6\x48\x5d\xab\x64\xe4\x37\x90\xb6\x21\x4a\x63\x48\x3c\x93\xef\xd6\xcf\x07\xf3\xc5\xfc\x03\xad\x3b\x6d\x94\xe0\x10\xd8\x46\x2d\x0d\x7d\x9c\x11\x7e\x46\xaf\xcb\x43\xa1\xf8\x31\xdd\xaa\x4a\x8f\xd7\x5a\xad\x9b\xf1\x6e\xcb\xce\x07\x0e\x3f\xe4\xf7\xce\xcc\xb3\x54\x46\x5b\x1e\xb5\x42\x30\xe3\xf5\x59\x36\xfd\xfd\x05\x8f\x83\x7a\x62\x07\x4f\x26\x87\xfa\xd7\x5e\xd1\x05\x5f\xac\xb5\x2d\x6a\x6e\xf6\xf6\x69\x6f\x08\x3a\x5d\xab\x36\x23\x42\x40\xac\xb4\x3f\x19\x55\x7b\xd0\x3a\xe1\x95\x2b\x3f\x3f\xf4\xde\xdf\xd9\x67\x72\x9e\xcb\xe4\x36\xd6\x38\xa9\x6e\xbd\xd9\x6e\xff\x8d\xd2\x93\x7b\x7a\x39\xa3\x22\x36\xed\xec\xf5\xd5\x4b\x5b\x33\xcd\xaf\x65\x2c\xef\x39\x6c\xb7\xa7\xcb\x65\x32\xda\x6e\xa9\x80\x94\xad\x42\x7d\xef\xae\x56\xbf\x2e\x2f\x56\xd9\xa4\x48\x25\x14\xd0\x58\xe1\xfc\x93\x7d\xd0\xce\x0e\x2d\xa8\x9c\x27\x8d\x6a\xd3\xa7\x9c\x88\x09\x54\x7c\x3b\x6f\x93\xe3\x4f\x3f\x92\x72\x94\xaf\x24\xda\xef\xe8\x27\xfa\x46\x27\xc8\xf6\x8d\x3a\x3b\xff\xed\xf4\x97\x9b\x93\xf7\xa2\x91\xbe\xbc\x3f\x79\x3a\x3a\x14\x87\xdf\x93\xb8\xfa\x40\xa2\x42\x46\x95\x0c\x11\xa2\x08\xdb\x1a\x50\x8d\x66\x90\xb8\xcb\x1d\xbd\xe3\xa7\xe8\x25\x4e\xa8\x75\xb6\x0b\xac\x44\x2b\xbd\x6c\x38\xb2\xef\x51\x3c\xd1\x61\xa4\xc6\xa1\x07\x8c\xb3\x75\xfe\xeb\x9f\x8d\x0e\x41\x03\xa9\x34\x83\x0f\xda\xea\xc4\x06\xfd\x82\xc4\x20\x1f\x5c\x3e\x4a\xaf\xe5\xda\x30\x90\xd6\x69\x0b\xdf\x02\x48\x8a\xe7\x6e\x83\x93\x05\x78\x08\x1f\xc9\x42\x71\x69\x10\x40\x44\x55\x84\xac\x92\x26\xda\x18\xb9\x41\x0c\x90\xea\xa6\x35\xba\xd4\x51\x54\x9d\x2d\xb3\xce\x44\x3f\x5b\xb7\x9e\x4b\xe8\xab\xa9\x20\x8c\x99\x94\x0f\x10\xac\x75\xec\x63\x2d\x5d\x83\x8a\x12\x3e\xa0\x4e\x74\x70\x8b\xa3\xc5\xe2\xf8\x60\xb1\x58\x10\xaa\x76\x7d\x71\xf6\x9e\xe6\x45\xe9\x6c\xa5\xeb\xce\x73\xe6\x9b\x10\xf0\x5e\xe9\xa7\x9e\x40\xc6\x95\x03\xed\x85\x60\x9b\xd2\x13\xe1\x1e\xc5\x52\x03\xa6\x74\xc8\xe0\x40\x44\x01\x8e\xbd\xd5\x4e\x9c\x12\x9e\x0d\x62\x7c\xe4\xd9\x3b\xba\x61\x6e\x02\x45\x47\xce\x9a\x67\x92\x55\xc5\x65\xa4\xe0\x1a\x26\x4c\x1c\x05\xf6\x1a\x2d\x00\x6b\x70\xec\x63\xfc\x22\xa1\x2b\x84\x24\xc0\x15\x7c\xb4\x91\x0f\x4c\x21\x72\x7b\x3c\x7b\x07\x67\xe9\x97\xa8\x91\x61\xf1\xcf\xd1\x6e\x88\x97\x3f\xdf\xfc\x01\x2e\x9e\x64\x2e\x62\x32\xb2\x76\xbc\x47\x21\xc0\xe4\xec\x32\x9b\xe0\x62\xfb\xdb\x60\xb8\x4f\x1b\x19\x68\xed\xdd\x03\xdb\x39\xdd\xa0\x0f\x31\xa2\x67\xa4\xd3\xca\x80\x52\x74\xc9\xcf\xc6\x21\xd0\xc4\xa0\x98\x43\x6b\xa4\x55\x81\x36\xce\x3f\x04\xaa\x10\xe6\xf1\x6c\x12\x13\x66\xe0\xb2\x6b\xce\xae\x6f\x07\xfa\x4f\xbf\xf6\x65\x98\x9f\x87\xa8\x9f\x95\xb6\x19\x76\x80\x08\x84\xa1\x1e\x1f\x91\x14\xaf\xc7\x87\xcd\xfb\x6a\x7c\xc9\x34\x97\xa7\x18\x10\xcc\xe6\x00\x3d\xd2\xff\x07\x71\x90\x00\xbe\x00\xf9\x32\x7d\x10\x5e\x56\x56\x93\xed\xf6\x71\x02\x8d\x6b\x6e\x8a\xed\xf6\xdd\x14\xfc\xca\xe2\xeb\x05\x6f\x76\xdf\x54\x30\x2e\xc1\x29\xb6\xdb\x86\x3b\xf0\x8b\xb5\x28\xfa\xed\x54\x4c\x8a\xd4\x52\x81\x9c\xce\xb5\xe1\x4b\x4c\xf7\x2e\x4f\x10\x79\xf6\x5f\x00\x00\x00\xff\xff\x5a\xb5\x63\x7b\x0f\x06\x00\x00") 124 | 125 | func dataDockerfileTemplateBytes() ([]byte, error) { 126 | return bindataRead( 127 | _dataDockerfileTemplate, 128 | "data/Dockerfile.template", 129 | ) 130 | } 131 | 132 | func dataDockerfileTemplate() (*asset, error) { 133 | bytes, err := dataDockerfileTemplateBytes() 134 | if err != nil { 135 | return nil, err 136 | } 137 | 138 | info := bindataFileInfo{name: "data/Dockerfile.template", size: 1551, mode: os.FileMode(420), modTime: time.Unix(1467243481, 0)} 139 | a := &asset{bytes: bytes, info: info} 140 | return a, nil 141 | } 142 | 143 | var _dataPatches10001_for_tests = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x4a\x4a\x2c\x02\x04\x00\x00\xff\xff\xaa\x8c\xff\x76\x03\x00\x00\x00") 144 | 145 | func dataPatches10001_for_testsBytes() ([]byte, error) { 146 | return bindataRead( 147 | _dataPatches10001_for_tests, 148 | "data/patches/1.0.0/01_for_tests", 149 | ) 150 | } 151 | 152 | func dataPatches10001_for_tests() (*asset, error) { 153 | bytes, err := dataPatches10001_for_testsBytes() 154 | if err != nil { 155 | return nil, err 156 | } 157 | 158 | info := bindataFileInfo{name: "data/patches/1.0.0/01_for_tests", size: 3, mode: os.FileMode(420), modTime: time.Unix(1448757621, 0)} 159 | a := &asset{bytes: bytes, info: info} 160 | return a, nil 161 | } 162 | 163 | var _dataPatches10002_for_tests = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x4a\x4a\xac\x02\x04\x00\x00\xff\xff\x98\x04\x24\x78\x03\x00\x00\x00") 164 | 165 | func dataPatches10002_for_testsBytes() ([]byte, error) { 166 | return bindataRead( 167 | _dataPatches10002_for_tests, 168 | "data/patches/1.0.0/02_for_tests", 169 | ) 170 | } 171 | 172 | func dataPatches10002_for_tests() (*asset, error) { 173 | bytes, err := dataPatches10002_for_testsBytes() 174 | if err != nil { 175 | return nil, err 176 | } 177 | 178 | info := bindataFileInfo{name: "data/patches/1.0.0/02_for_tests", size: 3, mode: os.FileMode(420), modTime: time.Unix(1448757621, 0)} 179 | a := &asset{bytes: bytes, info: info} 180 | return a, nil 181 | } 182 | 183 | var _dataPatches193P55101_strict_hostname_checkingPatch = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xec\x5a\x7b\x73\xda\x48\x12\xff\x9f\x4f\xd1\x07\x55\x31\xd8\x20\x1e\x06\x3f\xa8\xf5\x6e\x38\xdb\xd9\x4d\x55\x8c\x53\xc1\xa9\xbd\x2b\xdb\x47\x8d\xa4\x11\x68\x23\x46\xac\x34\x18\x9c\xdd\xbd\xef\xb2\x9f\x65\xbf\xd8\x75\xeb\x39\xe2\x1d\x87\x38\xa9\xad\xa3\x12\x83\x66\x5a\x3d\xfd\xf8\x4d\x3f\x46\x7a\xe5\xb9\x23\x38\x35\x1a\x87\xc7\xec\xe4\xb8\xa1\x1f\xd6\xf4\x5a\xb3\xae\x37\xeb\xcd\x66\xad\xd5\x68\x9d\x1c\x9d\x36\x2c\x5e\xab\xd5\x4f\x4e\x8c\x06\x6f\xc1\x95\x2b\xa0\xc7\xc7\x50\x3f\x86\x5a\xad\x1d\xfc\x83\x06\x4e\xe7\x88\x4d\x1b\x6e\x5c\xf1\x08\x1d\xcf\xb0\xb9\x67\xc3\x77\x3a\xf3\x8d\x89\xc3\x5f\x0e\x46\xcc\x76\x34\xc3\x1d\x7d\x9f\xbb\x60\x92\xb7\xa1\x37\x11\x65\x68\x9c\xc2\x15\xf3\xf0\xee\x7a\x0b\xd9\xb5\x1b\x27\xed\x66\x13\x2a\xb5\xe3\x5a\x2d\xd7\x9b\xe8\xbf\x70\x43\xb6\xe1\xf6\x6d\xe7\xe6\xfc\xa7\x7b\xe8\x49\xcf\x36\x24\xf7\x60\xe8\xfa\x52\xb0\x11\x87\x07\x5c\xc1\xb2\x0d\x26\x6d\x94\xc8\x72\x1d\xc7\x9d\xda\x62\x00\xef\x5e\x9d\xc3\x51\xbd\xd1\xd2\x72\xb9\x9b\x21\x13\x1f\x7c\x90\x2e\xbc\x14\x6c\x68\x23\x91\x07\x72\xc8\x41\x72\x5f\xfa\xc0\x84\x09\xb6\xb0\xa5\xcd\x1c\x30\x5d\x63\x32\xe2\x42\x06\xcc\xb4\x5c\xa5\x52\xc9\x01\x9f\xc9\xaa\x3b\xe6\xc2\xf7\x9d\xaa\x63\xeb\xc9\x6f\xfc\x5f\xb1\x05\x8a\x22\x98\xa3\x79\x3a\xfc\x0e\x70\xd4\x80\x83\x25\x1f\xe2\x42\x6b\x25\xb7\xd2\x45\x1f\x7f\xd0\x6d\x80\x37\xd6\x5b\xb5\xa5\x37\x6e\xfc\xe4\xa0\x01\x96\xed\x70\x1f\x0c\xd4\x71\xc0\x4d\x34\x66\xed\x04\xd5\xf1\xb9\x47\x2a\xf8\xc5\x83\x52\x19\x9a\x60\x72\x87\x87\xd7\x95\x52\x2e\x67\xda\x96\x05\x95\xca\xc0\x96\xc0\xaa\x6b\xd4\x23\xf1\xf4\x0d\x04\x39\x5b\x98\x7c\x06\x96\x55\x37\x9b\xdc\xd2\x34\x83\x59\x35\xfd\x94\x41\xbd\x56\x3b\x6a\x36\xc9\x82\xdb\x1a\x30\x87\xfa\x6c\x4d\xfb\xf2\x25\x54\xea\xcd\xc3\xf2\x09\x1c\xd0\xd7\x31\xe0\x80\xc9\xad\x10\x0c\x8f\x7d\x83\xd4\x0f\x40\xc1\xfb\xb6\x89\x0e\xb5\xe5\x63\x91\x06\xcb\x09\x6e\x4a\x39\x48\x3f\x06\xf3\x39\xf8\x4c\x68\x92\x0d\xd4\xf1\xe9\x90\x0b\x34\x71\x01\xcc\x6e\xaf\x4b\x60\xb3\x05\xfc\xc8\x05\xf7\x98\x13\x5c\x16\x11\x65\xad\xc6\x49\x2d\xc3\x0c\xc0\x1f\xba\x13\xc7\xec\xc7\xc2\xb8\xa3\x91\x2b\xfa\x01\x58\xcf\xc0\x62\x8e\xcf\x73\x15\x95\xdc\xe3\x03\x9c\x78\xc7\x07\x7c\x36\xd6\xb8\x6f\xb0\x31\x2f\x92\x30\x0f\xcc\x99\xf0\x92\x36\xf0\x27\x7a\xb1\x7a\x77\x77\xb7\x5f\x2d\x43\xfe\xf6\x3f\xda\xfd\x41\xbe\x34\xcf\x41\x4e\x3c\x01\xd2\x9b\xa0\x88\x16\x54\xef\x3a\x85\xdf\x90\xeb\x1f\x77\x1f\xab\x36\x9c\xfd\x37\x51\x3a\x77\xb0\xe6\xae\x48\xdc\x98\xb6\x18\xff\x28\x43\x2a\xcc\x82\x71\x8e\xd1\x38\xf6\xdb\x8e\x69\x7a\xdc\xf7\x77\x66\x9e\x0c\x79\x21\xda\xd5\x3e\xfc\x78\xd9\xbd\x7c\xd7\x79\xd3\xef\x76\xae\x2e\xfb\x63\x0f\x01\x51\x2c\xd1\x9a\xb3\x56\xed\xf4\xe1\xb0\xfa\x70\xd8\x67\x8e\xd4\x8c\x10\x1d\xad\xd3\x00\x1d\xad\x93\xcf\x42\x07\xda\x65\xa5\xb8\xa9\x98\x74\xb3\xe6\x87\xb1\x4a\x93\x6e\x9f\x69\x9c\x19\xc3\xdf\x7e\x77\x6d\xdc\x91\x81\xe5\x7e\x57\x75\x42\xa6\x38\x03\x67\x67\x90\x3f\xef\xe6\x37\x83\xe1\x9b\x01\xc2\x22\x08\xb8\x30\xd3\xcb\x3f\x72\xca\x68\xe0\x84\xa3\x93\x72\xbd\x8e\x5e\x38\x3a\x2a\x1f\x3d\xdd\x0d\xc9\x22\x23\xd7\xc4\x34\xd2\xb7\x26\xc2\x08\xc2\x7d\x7b\x0d\xab\x5c\xa8\xa3\xb2\xe0\x72\x64\x97\x10\x60\x6d\xe1\x62\xe8\x6f\xc7\x56\x29\x04\xd9\x83\x90\x5b\x86\xd7\x9d\x16\xe5\x1c\xcc\x28\xb6\x0f\x8e\x3d\xb2\x25\x37\x29\x95\x50\x02\xf1\xb9\x04\xd7\x82\x4e\xef\xfc\xf5\x6b\x8a\xc0\x1e\xa3\xd4\xe4\xc7\x6c\x22\xb3\x06\x90\x86\x89\x70\x68\x87\xd0\x56\xc2\x64\x68\xdb\x7d\x57\x38\x8f\x3f\xac\x23\x8d\xa5\xcc\xd2\xa7\x32\xf6\x38\x4f\xb2\x1c\x6a\xc2\x43\x93\x1c\x69\x4d\xad\x9e\x12\x5d\x31\x69\x0c\x23\xe9\x29\xca\x55\x28\x37\x08\x1f\xd3\xdd\x03\xd7\x62\x32\x14\xaa\x3f\x66\x1e\x26\xc3\xb3\x40\x40\xd3\x9d\x0a\x22\xd6\xfc\xb1\x63\xcb\x62\x5e\x43\x98\x29\x0b\xdf\x5c\x5f\x5c\xb7\xd1\x00\xc8\x52\xe7\x43\xf6\x60\x63\x3e\x0d\x37\x09\x8c\x3d\x57\x67\xba\xf3\x88\x13\xe8\x2c\x0f\x4d\x14\xe4\xeb\x39\x35\x71\x0d\x02\x7f\x92\xc2\x69\x93\xc5\x22\x68\xbe\xfd\x91\xc3\x77\xd0\x50\x57\xdc\x4a\x0b\x62\x97\xa8\x91\x18\x6f\x83\x2e\xcb\x0d\x78\x88\x97\x13\x1d\x5d\x3d\x82\x86\x96\x12\xbf\xb6\x02\xb7\x4f\x6d\xc7\x34\x98\x67\xa6\x2e\x27\xb9\x68\x86\x7c\xa4\x8c\xba\x21\xbd\xc3\x2d\x59\x19\xa1\x40\x29\x27\x87\xe9\xdc\xa1\xd0\x45\xf3\x63\x8c\x9d\x88\x59\xc4\x55\x88\x5d\x0b\x8b\xa6\x72\x30\x63\x38\x36\x0e\x40\xef\xa7\xeb\xf7\x6f\x2e\xa0\x7b\x7d\x03\x18\x7e\x50\x45\x9e\x72\x62\x03\x86\xc6\xc0\x4c\x2e\x1e\x65\x60\x22\x7d\x22\xb3\xab\x46\x8b\x45\xc2\x78\xdc\xe2\x1e\x17\x86\xc2\x22\x5d\x15\x8a\x5c\x1b\x68\x65\xd8\xd7\xf8\x8c\x8d\xc6\x0e\xa7\x5a\x0d\xa6\x81\x6b\x47\xe4\x03\x0c\xc5\x6e\x66\x0e\x57\x4b\x19\x09\x57\x82\xce\x3c\x6d\x9e\x08\xf1\xa1\x5c\x96\xb4\x0d\x1b\x44\x05\x42\x04\x13\x65\xe8\x93\xbc\x57\x57\xbc\x77\xb3\xd4\xa0\x4c\x22\xdd\x58\xd2\x96\x0e\x35\x64\x4b\xfd\x81\xbe\x4a\x39\x4d\x87\x36\x12\xae\x80\x02\x79\xc8\xb3\x7d\xac\xc9\x58\x6c\x79\xa4\xa4\x8a\x93\x05\xee\x56\x40\x30\xe7\xa1\xc8\xf8\xa6\x1b\x18\x32\x94\x86\xcc\x99\x7a\x43\x70\xb9\xde\x7a\x51\xa4\x8b\xc5\x2a\xaa\xb6\x1b\xda\x96\x2c\xab\xf6\xa5\x01\x65\x33\xa4\x33\xbf\xb8\xb6\x08\x76\xca\x9c\xf9\x93\xf1\xf0\x16\x0a\xcb\x07\xeb\xc2\x72\x9a\x6d\x16\x62\x71\x22\xa1\xe9\x62\x4f\x20\x28\xad\x8e\x5d\x81\xd6\x0e\x25\x4c\x2e\x97\x44\x67\x25\x52\xa5\x74\xf1\xf6\xde\xcf\x97\x31\xed\x28\x5a\x65\xac\x84\x81\x46\xc1\xd6\xf7\x14\x64\xe6\x03\x53\xca\x92\x94\x9f\x97\x6e\x8e\x03\x52\xd4\x3f\x09\x8f\x87\xbb\xc2\xa3\x0a\x46\xdc\xcf\x6b\xe2\x12\x1f\xe9\xdc\x34\xf1\xe6\xa9\x4d\x01\x02\x03\x05\x74\x2a\x11\x30\x15\x36\xef\x2b\x49\x98\x40\x8a\xa8\xd6\x26\x15\x98\x83\x9a\x9a\x91\x25\x20\x88\xa9\xab\x6c\x3b\x6f\x2d\xcd\x97\x68\xab\x3e\x2d\xfc\x43\x31\x3f\x13\x95\x0a\x42\xea\xc5\x8b\x39\x33\xff\x03\xcb\xa0\xfd\x7c\x6a\xc6\xc0\xbe\xb7\xb5\x7b\xcd\xe1\x62\x20\x87\x70\x10\x8d\xd4\x93\x91\xef\x16\x57\x8a\x66\x5e\xbc\x88\xb9\xac\x95\x25\x5e\xa2\xb4\xee\x06\x84\x77\x86\xbc\x7e\xbf\x2d\xee\x63\x47\xa0\x4e\x01\x6b\xc3\x61\xb8\x37\x7b\xbd\x37\x3d\xd7\xf8\xc0\x65\x52\x5b\x0a\xc3\x99\x98\x1c\xfe\x39\xb1\x30\x26\x63\xec\x9e\x9f\x08\xc9\x5f\xb9\xde\x14\x99\xa1\xcf\xe7\xa6\xbb\xae\xd0\x1d\x24\xc9\x25\x5e\x2c\xa4\xfe\x7c\xcb\x3d\xec\x73\x47\x2b\xfa\x64\x66\x11\x3a\xd0\xd1\x28\x14\x46\x2c\x21\x22\xb8\x12\x5e\xd0\x50\xba\x63\xfb\x43\x6e\x26\xdc\x54\xd0\x22\xc9\x88\xcb\xa1\x6b\xc2\xd5\xfb\xde\x0d\x25\x7a\x83\x39\x0e\x22\x24\xe4\x49\x17\x94\x86\x0a\x11\x57\x02\x32\xa6\xea\x49\x80\x51\x26\xb3\x11\x30\x11\x8e\x50\x87\x70\x1a\xb9\x12\xd3\x21\xa7\xf6\x9e\x51\x71\x81\x0d\x46\x28\x36\x37\xb5\x58\x7b\x0a\x22\x63\x8a\x49\xa9\xd8\x7d\x63\xc8\x8d\x0f\xc5\x25\xad\x5d\x14\x16\xaf\xb1\x8d\x44\x4d\xdb\x6d\xfc\xa3\xad\x2b\x3f\x69\xed\xfe\x9a\x46\xd1\x63\x18\xd9\xc9\x68\x97\x9e\xe7\x62\x92\xce\x27\x1a\xdc\xe5\x0b\xbf\xc5\x17\x7f\xdc\xe5\x11\x4e\x98\x01\xd2\x38\x1e\x96\x8b\xde\x03\x59\x28\x5d\x38\x9f\xed\xc5\x57\x1e\x12\xe8\x2b\xa7\xa2\xfe\x5b\x3f\x6a\x1d\x9e\x9e\x62\xff\xdd\x6c\x34\x6b\xf5\x93\x86\xda\x7f\xaf\xbc\x95\x1a\xee\x95\x93\x54\xbe\x37\x1b\x58\xb6\xc3\x01\x7d\xd5\x5b\x47\x71\xf9\x1e\x50\xad\x2b\xbc\x21\xde\x24\xd1\x17\xf9\x7b\xfe\xc6\x6c\x23\x82\xdb\x03\x19\xf5\xf9\xaf\x13\xe6\x14\xa9\x0d\x29\xc3\x52\x9f\x25\x15\x7c\x7e\x3a\x9d\xaa\x25\x06\x46\xfd\x7c\xa6\x68\xc9\x97\x4a\x4b\x58\x07\x91\xaa\xbc\x05\x6b\x8c\xd7\x61\x3c\xd8\x66\x91\x20\x1e\x2c\x53\x32\x8d\x03\x9f\x22\x49\x92\x1a\xf3\x58\x47\xd1\x9a\xb3\xfd\xe5\xda\xac\x31\xd4\x02\x0f\xfa\xfa\x7c\x26\x3b\x10\x64\x05\x8b\xad\xec\xc1\x74\x63\x5f\x37\x4c\x62\xc3\xe8\xfb\xe9\x9c\x28\x17\xfd\x6a\x7e\x68\xea\xa7\xfa\x3a\x0b\x3f\x85\xd7\x7e\x7a\xf5\x74\x63\xcd\xcb\x27\xe6\x99\x26\x98\x2b\xc0\xb9\x3b\xa2\x33\x4b\x3f\x6c\x27\xa8\x13\x41\x08\x06\x91\x7c\x86\xdb\x73\x4c\x75\x83\x45\x47\xbb\x43\x29\xc7\xed\x6a\x55\xba\xae\xe3\x6b\x36\x97\x96\xe6\x7a\x83\xea\x50\x8e\x9c\xaa\x67\x19\x54\xb6\x14\xc6\x6c\xc0\x2b\x8d\xe3\x0c\x96\x97\xc6\xda\x44\xd4\x3e\xe6\xf2\x50\xc9\xc2\x42\x67\x16\x37\xc6\x41\xcb\x62\xfb\x6e\x42\xb8\xb6\x6b\x2d\xc4\x54\x79\x4d\x1b\xc5\x7d\xdf\x7c\xf3\xa2\x56\xe6\x71\x07\xb4\xaa\x95\x8a\xf9\xa1\x45\xc6\x61\x52\xc4\x69\xfd\x31\x96\x0b\xb9\x2b\xbd\xbc\x52\xe6\x84\x55\xb9\x0f\x13\x9f\x68\xd8\xd6\x5a\x96\xd1\xdf\x94\xf2\xc3\xbc\x45\x2b\xdd\x5e\x74\x7b\x95\xf3\x4e\xef\xf2\x3e\xaa\xf1\x13\x15\x7f\xfe\xf9\x67\xed\x32\x0a\x28\xe8\xc7\x7c\xd4\x6b\x61\x52\x75\xdc\x29\xf7\x2a\xb4\x58\x70\xdc\xb0\x10\xf0\xe8\x14\x3b\x11\x29\x59\x1b\xc6\x13\x0f\x1d\xc6\xfd\xd5\xc8\xdb\x3a\x17\xc6\x69\xda\xf0\x38\x8d\x13\x4d\x50\x0f\x91\xcb\x8b\x7b\xa8\x52\x3b\x13\x0c\xf7\x4a\x65\xd8\x9b\x93\x72\x6f\xcd\x0e\xd8\xa9\x1c\x89\x0d\xaf\xaf\xbe\xaa\x1c\xf3\xf6\xc8\xf8\x97\x64\x2b\xc5\x3e\xab\x6b\xb0\xa3\x8e\xb4\x10\x48\xb5\x83\x9e\x34\x64\xf4\x59\x5d\xe9\xb6\xd1\xf3\x89\x06\x26\xb7\xee\x6f\x04\x5b\x01\x1a\x68\xdc\xdd\x1c\xd6\x44\x36\xd9\xc9\x71\x4d\xc8\xeb\x33\x0f\x6c\x42\x26\x3b\x39\xb2\x09\x59\x7d\xda\xa1\xcd\x73\x6f\xa0\x39\xa9\x96\x6f\xe4\xdd\x03\x6d\x51\x90\x25\x26\x52\x00\x77\x98\xdd\xcd\x57\x9d\x7f\x6f\xda\xbb\x4b\x36\xac\xea\x95\x0c\x5a\xc9\x45\x6b\x10\xab\x6c\x53\x95\x85\xce\x3e\x66\xf6\x68\xf0\xa4\x73\x1f\x47\x17\x06\xf5\xfd\xec\x58\x80\x9e\x0c\x2b\x6c\xde\xd8\x07\xec\xc6\x92\x98\x84\x6c\xea\x0b\x7c\xd0\x3e\x4b\xd8\x67\x18\x4d\x3e\x66\xe6\xcb\x08\x6f\x7f\x4c\x45\xc0\x03\x77\x1e\x4b\x68\x45\x4d\x7b\x16\xa4\x65\x8c\x93\xfa\x58\x51\xea\x19\xd3\x86\x6a\x34\x05\xf8\x0b\xc3\xcf\x22\x8d\x0a\x86\xc4\x30\xaa\xdb\xb2\xc8\xef\xa9\x07\x5d\x04\x49\x2c\xee\xa8\xb6\x03\x5f\xe2\x02\x7e\xd8\xf4\x47\xdb\x22\x7a\x48\x40\x81\x31\x44\xd1\x62\x91\x16\x9e\x66\x25\x41\x1b\xc1\xaf\x64\xaa\xb9\x08\xa9\xcd\x15\x8c\x1d\xc7\x77\xc1\x46\x19\x6d\xc3\x96\xb8\x53\xa8\x2a\xa6\x87\xde\xab\xf2\x40\xb0\x9d\x70\x27\x52\x7d\x37\xc1\x7a\x8d\x4a\xaa\x51\xb2\x85\x08\xd0\xa6\xed\x1b\xee\xc4\xc3\xaa\xd8\x87\xa4\x16\x8d\x03\x78\xf0\x7c\x23\x90\xcb\x15\x29\xff\x79\xa1\x96\x3f\xa5\x39\xd6\x1a\x8b\x8f\x18\xbe\x74\x4c\xd3\x17\x11\x8f\x6d\xd4\x57\x09\xaf\x4b\x45\xf9\x56\x24\x59\x61\x93\x30\x82\xad\xf9\x60\xe8\x02\xf8\x09\xeb\xf6\x87\x95\x05\x41\xca\x69\xdb\x2a\x6f\xf1\x78\x37\xe5\xb1\xfd\x39\x6f\x72\xbc\x7b\xfb\xfa\xa2\xdb\xa9\x5c\x5c\xbe\xea\xdd\xe3\x66\x55\xc4\xd9\x70\xe6\x1b\xdd\xf8\xf6\xdd\xf5\xcd\xf5\xfd\xb3\x44\xe8\x99\x58\xf4\xcc\x4c\xd4\x0d\xb6\xc2\x39\x74\x48\x1b\x3c\x8d\x0d\x35\x7d\x16\xf4\x50\x5f\xbe\x4c\xca\x4a\x65\xb3\x9c\xef\x55\x39\x33\x6f\x98\x44\x6f\x4d\x90\x53\xd1\x2d\xe9\x03\x68\x8c\x6e\xb1\x1b\x95\x48\x8a\xb9\x99\xd1\xeb\x11\x3c\x01\x86\xc7\x07\x08\x93\xe0\xe0\x13\xd7\x59\x17\x98\x7a\x69\x38\x8a\x42\x77\xf0\xd4\xbb\x9d\xe2\xe2\x09\x8f\xbf\x9f\x27\x9a\xfd\xf5\xe7\xa2\xe1\xff\xfa\x73\x59\xfa\x5e\x3c\x9e\xdb\x70\xa4\x61\x88\x2f\x88\xef\xe0\x8c\x71\xef\x2b\x77\xce\xb1\x10\x5f\xb5\x6d\x5e\x65\x89\x55\x3d\xf3\x97\x01\x54\x28\xc5\x76\x8d\xe5\xb3\x9a\xe1\x79\x3b\x9f\x55\x52\xac\x6b\x7b\xbe\xa0\x39\xbe\x81\xf2\x3c\xb2\xc8\xb7\x50\x9b\x47\x36\xf9\x7f\x61\x0e\x7f\xa7\xc2\x3c\x06\xd8\xd7\xae\xca\xd7\xc9\xf1\x4d\x88\xb1\x8d\x35\x76\xbb\xd5\x3e\xad\xf6\xfc\x92\xf6\xd8\x61\x85\x19\xbd\x4b\xaf\x56\x98\x51\x28\xd8\xf8\x48\xe3\xef\x51\x3b\x86\x16\x7d\x62\xe1\xb8\xb4\x12\xa5\xd7\x47\xc3\xe5\x90\xe2\x2c\x15\xf1\x5f\xad\xda\x69\xbb\x7d\x39\x93\x64\x51\x57\xbc\x42\xe5\x5c\xef\x51\x13\x7c\x1a\x52\x13\x97\x45\xfa\xf3\x54\x9b\x2c\x69\xfc\x6a\xf1\xe2\x2d\xd4\x32\x68\xe8\x24\x9f\x17\xf3\xd5\x8b\xf3\x33\xdf\x1d\xf1\xe0\x1b\x6d\x5d\x3d\xef\x9e\xf5\xf0\x1a\x7a\x78\x91\xbc\xb3\x35\x23\x2e\xdc\xd2\x22\x7d\xf0\xba\xb8\x17\xb1\xef\x38\x92\xf8\xed\x85\xaf\xc5\x2a\xcb\x33\xd3\x24\xc2\x50\x99\x22\xfe\x52\x26\x37\x1b\x2a\x30\x7b\xf8\x26\xc5\x17\x50\x1e\x69\x8b\xb7\xb7\x7b\x17\xe7\x28\xf6\x1e\xa9\xbf\x77\x5f\x86\xe4\x1a\x35\x0f\xaf\xcf\xbb\x78\x4d\x42\xdc\xdf\x2f\x17\x3e\x17\x80\xf6\x3c\x10\x1e\xba\xef\xdf\xbc\x01\xfd\x11\x7f\xf5\x3a\x5d\xf5\x85\x0d\xa2\x52\x94\x14\x13\xc7\xe9\x13\x5d\x1f\xe9\x54\x34\x16\x0d\x0f\x77\x92\xc1\x9c\xf8\x95\xf6\xf8\x4d\xe6\x2d\x61\xf2\xbf\x00\x00\x00\xff\xff\x3c\x67\x0d\x81\x8c\x33\x00\x00") 184 | 185 | func dataPatches193P55101_strict_hostname_checkingPatchBytes() ([]byte, error) { 186 | return bindataRead( 187 | _dataPatches193P55101_strict_hostname_checkingPatch, 188 | "data/patches/1.9.3-p551/01_strict_hostname_checking.patch", 189 | ) 190 | } 191 | 192 | func dataPatches193P55101_strict_hostname_checkingPatch() (*asset, error) { 193 | bytes, err := dataPatches193P55101_strict_hostname_checkingPatchBytes() 194 | if err != nil { 195 | return nil, err 196 | } 197 | 198 | info := bindataFileInfo{name: "data/patches/1.9.3-p551/01_strict_hostname_checking.patch", size: 13196, mode: os.FileMode(420), modTime: time.Unix(1448757621, 0)} 199 | a := &asset{bytes: bytes, info: info} 200 | return a, nil 201 | } 202 | 203 | var _dataPatches200P001_readlinePatch = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x84\x53\xef\x4f\xdb\x30\x10\xfd\xee\xbf\xe2\x54\x26\x91\xcc\x4d\x48\x7f\x8c\xa6\x2a\x48\x54\x8c\xad\xd5\x10\x20\x60\xfb\x6a\x85\xe4\xd2\x5a\xa4\x4e\x64\x3b\x13\xfc\xf7\x3b\x67\x6d\xd5\x8e\xa6\xfb\xe2\xd4\xef\x9e\xdf\xd9\xef\x5e\x33\x99\xe7\x10\x04\x0b\x69\x01\xdf\xec\x99\xc6\x24\x2b\xa4\xc2\x33\xda\xa4\xa5\xca\x43\xfd\xd2\x86\x33\xa9\x32\x7c\x83\xe1\xb8\x1f\xf5\x06\xa3\x30\x8c\x31\xee\xf5\xbf\x0c\xa0\x17\x45\xe7\xc3\x21\x0b\x82\xa0\xf5\x24\xe7\xbc\xb5\x76\x75\x05\x41\x6f\xdc\x3d\x07\x4e\x6b\x2f\x02\xda\x67\x98\xc3\x86\x1a\x2e\x93\xdf\x28\xf2\x5a\xa5\x9e\x5b\x7c\x06\x40\x35\x5b\x6b\x05\xa6\xae\x50\x37\x68\x17\x96\x44\x47\x6d\xa8\x8c\x2a\x63\x8c\x7f\x94\xb0\xef\x15\x7a\x6e\xf1\x19\xff\x47\xc2\xa1\x3b\x12\xdc\x49\x70\x06\x99\xd4\xc2\xdd\x52\x2e\xbc\xd3\xb4\xd6\x06\xcd\xa9\xbf\x8f\xaa\xc3\xb0\x45\xbd\x4a\x93\x8a\x60\xf7\xb8\xf1\xa0\x3b\x04\x3e\x1e\x75\xc7\xee\x6d\x07\xde\xd5\xd1\xb8\x2a\x69\xb3\x94\xc6\x96\xfa\xbd\x43\x6a\x87\x58\x69\x81\x89\xfe\x1f\x49\x17\x42\x63\x26\x4d\x55\x24\xc7\x38\x52\x19\xd4\x56\x58\x9a\x03\xb1\x38\xe3\xb5\x2a\xd0\x98\x43\x96\x39\xfa\xb2\x2c\x5f\x9b\xc3\xa2\xa1\x03\x7c\x22\x7f\x0d\x5c\x5c\x40\x27\xf8\xba\x5f\xbf\xfc\x46\x1f\x2b\x4b\xd5\xd9\xfa\x98\x92\xaa\x45\xb1\x4a\x5e\x31\x97\x85\x53\x5c\x77\x21\xad\xb6\x38\x6e\x2f\x92\xb6\xe1\xeb\x38\x0e\x70\x94\x23\x26\x61\x38\x8c\xfb\x2f\x79\x1c\xb5\xc6\x71\xe7\xe4\x87\x38\xee\xd4\x9a\x38\xc6\xf1\xa0\x3b\xa2\x40\xfe\xfd\x12\x34\x57\xd2\x8a\x0d\xcb\xf3\x99\x4b\x21\x85\xa8\x10\x89\xb5\xb8\xaa\x2c\x66\x34\xfc\x55\x55\xa0\x7b\x79\xe3\x84\xfb\x01\x97\x5b\x43\x8f\x13\x27\x0c\x4e\x64\xee\x72\x4f\xd4\xcc\x9b\x4d\x7f\xdd\x88\xc7\x5b\xf1\xf0\x78\x23\xe6\x77\x0f\x3f\x9f\xc5\xec\xfe\xfe\x87\xcf\x82\x75\xd3\x4a\x23\x4d\xb0\xaa\x6d\x63\x3c\x75\xf1\x36\xa6\xc3\x67\x7f\xdb\x71\x9f\x35\x71\x63\x6b\x39\xbd\x3f\xc1\x63\x1a\x70\x42\x33\x95\x79\x73\x5d\xf7\x17\xdb\xdc\xf4\x7a\xfa\x7c\x3d\x13\x4f\xf3\xef\x77\xd3\xdb\xa7\xad\x39\x69\x62\xd3\xa5\x30\x72\xa1\x92\xc2\x50\xa3\x68\xc2\xfe\x04\x00\x00\xff\xff\x71\xae\x9c\xc9\x7f\x04\x00\x00") 204 | 205 | func dataPatches200P001_readlinePatchBytes() ([]byte, error) { 206 | return bindataRead( 207 | _dataPatches200P001_readlinePatch, 208 | "data/patches/2.0.0-p0/01_readline.patch", 209 | ) 210 | } 211 | 212 | func dataPatches200P001_readlinePatch() (*asset, error) { 213 | bytes, err := dataPatches200P001_readlinePatchBytes() 214 | if err != nil { 215 | return nil, err 216 | } 217 | 218 | info := bindataFileInfo{name: "data/patches/2.0.0-p0/01_readline.patch", size: 1151, mode: os.FileMode(420), modTime: time.Unix(1448757621, 0)} 219 | a := &asset{bytes: bytes, info: info} 220 | return a, nil 221 | } 222 | 223 | var _dataPatches200P19501_readlinePatch = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x84\x53\xef\x4f\xdb\x30\x10\xfd\xee\xbf\xe2\x54\x26\x91\xcc\x4d\x48\x7f\x8c\xa6\x2a\x48\x54\x8c\xad\xd5\x10\x20\x60\xfb\x6a\x85\xe4\xd2\x5a\xa4\x4e\x64\x3b\x13\xfc\xf7\x3b\x67\x6d\xd5\x8e\xa6\xfb\xe2\xd4\xef\x9e\xdf\xd9\xef\x5e\x33\x99\xe7\x10\x04\x0b\x69\x01\xdf\xec\x99\xc6\x24\x2b\xa4\xc2\x33\xda\xa4\xa5\xca\x43\xfd\xd2\x86\x33\xa9\x32\x7c\x83\xe1\xb8\x1f\xf5\x06\xa3\x30\x8c\x31\xee\xf5\xbf\x0c\xa0\x17\x45\xe7\xc3\x21\x0b\x82\xa0\xf5\x24\xe7\xbc\xb5\x76\x75\x05\x41\x6f\xdc\x3d\x07\x4e\x6b\x2f\x02\xda\x67\x98\xc3\x86\x1a\x2e\x93\xdf\x28\xf2\x5a\xa5\x9e\x5b\x7c\x06\x40\x35\x5b\x6b\x05\xa6\xae\x50\x37\x68\x17\x96\x44\x47\x6d\xa8\x8c\x2a\x63\x8c\x7f\x94\xb0\xef\x15\x7a\x6e\xf1\x19\xff\x47\xc2\xa1\x3b\x12\xdc\x49\x70\x06\x99\xd4\xc2\xdd\x52\x2e\xbc\xd3\xb4\xd6\x06\xcd\xa9\xbf\x8f\xaa\xc3\xb0\x45\xbd\x4a\x93\x8a\x60\xf7\xb8\xf1\xa0\x3b\x04\x3e\x1e\x75\xc7\xee\x6d\x07\xde\xd5\xd1\xb8\x2a\x69\xb3\x94\xc6\x96\xfa\xbd\x43\x6a\x87\x58\x69\x81\x89\xfe\x1f\x49\x17\x42\x63\x26\x4d\x55\x24\xc7\x38\x52\x19\xd4\x56\x58\x9a\x03\xb1\x38\xe3\xb5\x2a\xd0\x98\x43\x96\x39\xfa\xb2\x2c\x5f\x9b\xc3\xa2\xa1\x03\x7c\x22\x7f\x0d\x5c\x5c\x40\x27\xf8\xba\x5f\xbf\xfc\x46\x1f\x2b\x4b\xd5\xd9\xfa\x98\x92\xaa\x45\xb1\x4a\x5e\x31\x97\x85\x53\x5c\x77\x21\xad\xb6\x38\x6e\x2f\x92\xb6\xe1\xeb\x38\x0e\x70\x94\x23\x26\x61\x38\x8c\xfb\x2f\x79\x1c\xb5\xc6\x71\xe7\xe4\x87\x38\xee\xd4\x9a\x38\xc6\xf1\xa0\x3b\xa2\x40\xfe\xfd\x12\x34\x57\xd2\x8a\x0d\xcb\xf3\x99\x4b\x21\x85\xa8\x10\x89\xb5\xb8\xaa\x2c\x66\x34\xfc\x55\x55\xa0\x7b\x79\xe3\x84\xfb\x01\x97\x5b\x43\x8f\x13\x27\x0c\x4e\x64\xee\x72\x4f\xd4\xcc\x9b\x4d\x7f\xdd\x88\xc7\x5b\xf1\xf0\x78\x23\xe6\x77\x0f\x3f\x9f\xc5\xec\xfe\xfe\x87\xcf\x82\x75\xd3\x4a\x23\x4d\xb0\xaa\x6d\x63\x3c\x75\xf1\x36\xa6\xc3\x67\x7f\xdb\x71\x9f\x35\x71\x63\x6b\x39\xbd\x3f\xc1\x63\x1a\x70\x42\x33\x95\x79\x73\x5d\xf7\x17\xdb\xdc\xf4\x7a\xfa\x7c\x3d\x13\x4f\xf3\xef\x77\xd3\xdb\xa7\xad\x39\x69\x62\xd3\xa5\x30\x72\xa1\x92\xc2\x50\xa3\x68\xc2\xfe\x04\x00\x00\xff\xff\x71\xae\x9c\xc9\x7f\x04\x00\x00") 224 | 225 | func dataPatches200P19501_readlinePatchBytes() ([]byte, error) { 226 | return bindataRead( 227 | _dataPatches200P19501_readlinePatch, 228 | "data/patches/2.0.0-p195/01_readline.patch", 229 | ) 230 | } 231 | 232 | func dataPatches200P19501_readlinePatch() (*asset, error) { 233 | bytes, err := dataPatches200P19501_readlinePatchBytes() 234 | if err != nil { 235 | return nil, err 236 | } 237 | 238 | info := bindataFileInfo{name: "data/patches/2.0.0-p195/01_readline.patch", size: 1151, mode: os.FileMode(420), modTime: time.Unix(1448757621, 0)} 239 | a := &asset{bytes: bytes, info: info} 240 | return a, nil 241 | } 242 | 243 | var _dataPatches200P24701_readlinePatch = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x84\x53\xef\x4f\xdb\x30\x10\xfd\xee\xbf\xe2\x54\x26\x91\xcc\x4d\x48\x7f\x8c\xa6\x2a\x48\x54\x8c\xad\xd5\x10\x20\x60\xfb\x6a\x85\xe4\xd2\x5a\xa4\x4e\x64\x3b\x13\xfc\xf7\x3b\x67\x6d\xd5\x8e\xa6\xfb\xe2\xd4\xef\x9e\xdf\xd9\xef\x5e\x33\x99\xe7\x10\x04\x0b\x69\x01\xdf\xec\x99\xc6\x24\x2b\xa4\xc2\x33\xda\xa4\xa5\xca\x43\xfd\xd2\x86\x33\xa9\x32\x7c\x83\xe1\xb8\x1f\xf5\x06\xa3\x30\x8c\x31\xee\xf5\xbf\x0c\xa0\x17\x45\xe7\xc3\x21\x0b\x82\xa0\xf5\x24\xe7\xbc\xb5\x76\x75\x05\x41\x6f\xdc\x3d\x07\x4e\x6b\x2f\x02\xda\x67\x98\xc3\x86\x1a\x2e\x93\xdf\x28\xf2\x5a\xa5\x9e\x5b\x7c\x06\x40\x35\x5b\x6b\x05\xa6\xae\x50\x37\x68\x17\x96\x44\x47\x6d\xa8\x8c\x2a\x63\x8c\x7f\x94\xb0\xef\x15\x7a\x6e\xf1\x19\xff\x47\xc2\xa1\x3b\x12\xdc\x49\x70\x06\x99\xd4\xc2\xdd\x52\x2e\xbc\xd3\xb4\xd6\x06\xcd\xa9\xbf\x8f\xaa\xc3\xb0\x45\xbd\x4a\x93\x8a\x60\xf7\xb8\xf1\xa0\x3b\x04\x3e\x1e\x75\xc7\xee\x6d\x07\xde\xd5\xd1\xb8\x2a\x69\xb3\x94\xc6\x96\xfa\xbd\x43\x6a\x87\x58\x69\x81\x89\xfe\x1f\x49\x17\x42\x63\x26\x4d\x55\x24\xc7\x38\x52\x19\xd4\x56\x58\x9a\x03\xb1\x38\xe3\xb5\x2a\xd0\x98\x43\x96\x39\xfa\xb2\x2c\x5f\x9b\xc3\xa2\xa1\x03\x7c\x22\x7f\x0d\x5c\x5c\x40\x27\xf8\xba\x5f\xbf\xfc\x46\x1f\x2b\x4b\xd5\xd9\xfa\x98\x92\xaa\x45\xb1\x4a\x5e\x31\x97\x85\x53\x5c\x77\x21\xad\xb6\x38\x6e\x2f\x92\xb6\xe1\xeb\x38\x0e\x70\x94\x23\x26\x61\x38\x8c\xfb\x2f\x79\x1c\xb5\xc6\x71\xe7\xe4\x87\x38\xee\xd4\x9a\x38\xc6\xf1\xa0\x3b\xa2\x40\xfe\xfd\x12\x34\x57\xd2\x8a\x0d\xcb\xf3\x99\x4b\x21\x85\xa8\x10\x89\xb5\xb8\xaa\x2c\x66\x34\xfc\x55\x55\xa0\x7b\x79\xe3\x84\xfb\x01\x97\x5b\x43\x8f\x13\x27\x0c\x4e\x64\xee\x72\x4f\xd4\xcc\x9b\x4d\x7f\xdd\x88\xc7\x5b\xf1\xf0\x78\x23\xe6\x77\x0f\x3f\x9f\xc5\xec\xfe\xfe\x87\xcf\x82\x75\xd3\x4a\x23\x4d\xb0\xaa\x6d\x63\x3c\x75\xf1\x36\xa6\xc3\x67\x7f\xdb\x71\x9f\x35\x71\x63\x6b\x39\xbd\x3f\xc1\x63\x1a\x70\x42\x33\x95\x79\x73\x5d\xf7\x17\xdb\xdc\xf4\x7a\xfa\x7c\x3d\x13\x4f\xf3\xef\x77\xd3\xdb\xa7\xad\x39\x69\x62\xd3\xa5\x30\x72\xa1\x92\xc2\x50\xa3\x68\xc2\xfe\x04\x00\x00\xff\xff\x71\xae\x9c\xc9\x7f\x04\x00\x00") 244 | 245 | func dataPatches200P24701_readlinePatchBytes() ([]byte, error) { 246 | return bindataRead( 247 | _dataPatches200P24701_readlinePatch, 248 | "data/patches/2.0.0-p247/01_readline.patch", 249 | ) 250 | } 251 | 252 | func dataPatches200P24701_readlinePatch() (*asset, error) { 253 | bytes, err := dataPatches200P24701_readlinePatchBytes() 254 | if err != nil { 255 | return nil, err 256 | } 257 | 258 | info := bindataFileInfo{name: "data/patches/2.0.0-p247/01_readline.patch", size: 1151, mode: os.FileMode(420), modTime: time.Unix(1448757621, 0)} 259 | a := &asset{bytes: bytes, info: info} 260 | return a, nil 261 | } 262 | 263 | var _dataPatches200P35301_readlinePatch = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x84\x53\xef\x4f\xdb\x30\x10\xfd\xee\xbf\xe2\x54\x26\x91\xcc\x4d\x48\x7f\x8c\xa6\x2a\x48\x54\x8c\xad\xd5\x10\x20\x60\xfb\x6a\x85\xe4\xd2\x5a\xa4\x4e\x64\x3b\x13\xfc\xf7\x3b\x67\x6d\xd5\x8e\xa6\xfb\xe2\xd4\xef\x9e\xdf\xd9\xef\x5e\x33\x99\xe7\x10\x04\x0b\x69\x01\xdf\xec\x99\xc6\x24\x2b\xa4\xc2\x33\xda\xa4\xa5\xca\x43\xfd\xd2\x86\x33\xa9\x32\x7c\x83\xe1\xb8\x1f\xf5\x06\xa3\x30\x8c\x31\xee\xf5\xbf\x0c\xa0\x17\x45\xe7\xc3\x21\x0b\x82\xa0\xf5\x24\xe7\xbc\xb5\x76\x75\x05\x41\x6f\xdc\x3d\x07\x4e\x6b\x2f\x02\xda\x67\x98\xc3\x86\x1a\x2e\x93\xdf\x28\xf2\x5a\xa5\x9e\x5b\x7c\x06\x40\x35\x5b\x6b\x05\xa6\xae\x50\x37\x68\x17\x96\x44\x47\x6d\xa8\x8c\x2a\x63\x8c\x7f\x94\xb0\xef\x15\x7a\x6e\xf1\x19\xff\x47\xc2\xa1\x3b\x12\xdc\x49\x70\x06\x99\xd4\xc2\xdd\x52\x2e\xbc\xd3\xb4\xd6\x06\xcd\xa9\xbf\x8f\xaa\xc3\xb0\x45\xbd\x4a\x93\x8a\x60\xf7\xb8\xf1\xa0\x3b\x04\x3e\x1e\x75\xc7\xee\x6d\x07\xde\xd5\xd1\xb8\x2a\x69\xb3\x94\xc6\x96\xfa\xbd\x43\x6a\x87\x58\x69\x81\x89\xfe\x1f\x49\x17\x42\x63\x26\x4d\x55\x24\xc7\x38\x52\x19\xd4\x56\x58\x9a\x03\xb1\x38\xe3\xb5\x2a\xd0\x98\x43\x96\x39\xfa\xb2\x2c\x5f\x9b\xc3\xa2\xa1\x03\x7c\x22\x7f\x0d\x5c\x5c\x40\x27\xf8\xba\x5f\xbf\xfc\x46\x1f\x2b\x4b\xd5\xd9\xfa\x98\x92\xaa\x45\xb1\x4a\x5e\x31\x97\x85\x53\x5c\x77\x21\xad\xb6\x38\x6e\x2f\x92\xb6\xe1\xeb\x38\x0e\x70\x94\x23\x26\x61\x38\x8c\xfb\x2f\x79\x1c\xb5\xc6\x71\xe7\xe4\x87\x38\xee\xd4\x9a\x38\xc6\xf1\xa0\x3b\xa2\x40\xfe\xfd\x12\x34\x57\xd2\x8a\x0d\xcb\xf3\x99\x4b\x21\x85\xa8\x10\x89\xb5\xb8\xaa\x2c\x66\x34\xfc\x55\x55\xa0\x7b\x79\xe3\x84\xfb\x01\x97\x5b\x43\x8f\x13\x27\x0c\x4e\x64\xee\x72\x4f\xd4\xcc\x9b\x4d\x7f\xdd\x88\xc7\x5b\xf1\xf0\x78\x23\xe6\x77\x0f\x3f\x9f\xc5\xec\xfe\xfe\x87\xcf\x82\x75\xd3\x4a\x23\x4d\xb0\xaa\x6d\x63\x3c\x75\xf1\x36\xa6\xc3\x67\x7f\xdb\x71\x9f\x35\x71\x63\x6b\x39\xbd\x3f\xc1\x63\x1a\x70\x42\x33\x95\x79\x73\x5d\xf7\x17\xdb\xdc\xf4\x7a\xfa\x7c\x3d\x13\x4f\xf3\xef\x77\xd3\xdb\xa7\xad\x39\x69\x62\xd3\xa5\x30\x72\xa1\x92\xc2\x50\xa3\x68\xc2\xfe\x04\x00\x00\xff\xff\x71\xae\x9c\xc9\x7f\x04\x00\x00") 264 | 265 | func dataPatches200P35301_readlinePatchBytes() ([]byte, error) { 266 | return bindataRead( 267 | _dataPatches200P35301_readlinePatch, 268 | "data/patches/2.0.0-p353/01_readline.patch", 269 | ) 270 | } 271 | 272 | func dataPatches200P35301_readlinePatch() (*asset, error) { 273 | bytes, err := dataPatches200P35301_readlinePatchBytes() 274 | if err != nil { 275 | return nil, err 276 | } 277 | 278 | info := bindataFileInfo{name: "data/patches/2.0.0-p353/01_readline.patch", size: 1151, mode: os.FileMode(420), modTime: time.Unix(1448757621, 0)} 279 | a := &asset{bytes: bytes, info: info} 280 | return a, nil 281 | } 282 | 283 | var _dataPatches200P45101_readlinePatch = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x84\x53\xef\x4f\xdb\x30\x10\xfd\xee\xbf\xe2\x54\x26\x91\xcc\x4d\x48\x7f\x8c\xa6\x2a\x48\x54\x8c\xad\xd5\x10\x20\x60\xfb\x6a\x85\xe4\xd2\x5a\xa4\x4e\x64\x3b\x13\xfc\xf7\x3b\x67\x6d\xd5\x8e\xa6\xfb\xe2\xd4\xef\x9e\xdf\xd9\xef\x5e\x33\x99\xe7\x10\x04\x0b\x69\x01\xdf\xec\x99\xc6\x24\x2b\xa4\xc2\x33\xda\xa4\xa5\xca\x43\xfd\xd2\x86\x33\xa9\x32\x7c\x83\xe1\xb8\x1f\xf5\x06\xa3\x30\x8c\x31\xee\xf5\xbf\x0c\xa0\x17\x45\xe7\xc3\x21\x0b\x82\xa0\xf5\x24\xe7\xbc\xb5\x76\x75\x05\x41\x6f\xdc\x3d\x07\x4e\x6b\x2f\x02\xda\x67\x98\xc3\x86\x1a\x2e\x93\xdf\x28\xf2\x5a\xa5\x9e\x5b\x7c\x06\x40\x35\x5b\x6b\x05\xa6\xae\x50\x37\x68\x17\x96\x44\x47\x6d\xa8\x8c\x2a\x63\x8c\x7f\x94\xb0\xef\x15\x7a\x6e\xf1\x19\xff\x47\xc2\xa1\x3b\x12\xdc\x49\x70\x06\x99\xd4\xc2\xdd\x52\x2e\xbc\xd3\xb4\xd6\x06\xcd\xa9\xbf\x8f\xaa\xc3\xb0\x45\xbd\x4a\x93\x8a\x60\xf7\xb8\xf1\xa0\x3b\x04\x3e\x1e\x75\xc7\xee\x6d\x07\xde\xd5\xd1\xb8\x2a\x69\xb3\x94\xc6\x96\xfa\xbd\x43\x6a\x87\x58\x69\x81\x89\xfe\x1f\x49\x17\x42\x63\x26\x4d\x55\x24\xc7\x38\x52\x19\xd4\x56\x58\x9a\x03\xb1\x38\xe3\xb5\x2a\xd0\x98\x43\x96\x39\xfa\xb2\x2c\x5f\x9b\xc3\xa2\xa1\x03\x7c\x22\x7f\x0d\x5c\x5c\x40\x27\xf8\xba\x5f\xbf\xfc\x46\x1f\x2b\x4b\xd5\xd9\xfa\x98\x92\xaa\x45\xb1\x4a\x5e\x31\x97\x85\x53\x5c\x77\x21\xad\xb6\x38\x6e\x2f\x92\xb6\xe1\xeb\x38\x0e\x70\x94\x23\x26\x61\x38\x8c\xfb\x2f\x79\x1c\xb5\xc6\x71\xe7\xe4\x87\x38\xee\xd4\x9a\x38\xc6\xf1\xa0\x3b\xa2\x40\xfe\xfd\x12\x34\x57\xd2\x8a\x0d\xcb\xf3\x99\x4b\x21\x85\xa8\x10\x89\xb5\xb8\xaa\x2c\x66\x34\xfc\x55\x55\xa0\x7b\x79\xe3\x84\xfb\x01\x97\x5b\x43\x8f\x13\x27\x0c\x4e\x64\xee\x72\x4f\xd4\xcc\x9b\x4d\x7f\xdd\x88\xc7\x5b\xf1\xf0\x78\x23\xe6\x77\x0f\x3f\x9f\xc5\xec\xfe\xfe\x87\xcf\x82\x75\xd3\x4a\x23\x4d\xb0\xaa\x6d\x63\x3c\x75\xf1\x36\xa6\xc3\x67\x7f\xdb\x71\x9f\x35\x71\x63\x6b\x39\xbd\x3f\xc1\x63\x1a\x70\x42\x33\x95\x79\x73\x5d\xf7\x17\xdb\xdc\xf4\x7a\xfa\x7c\x3d\x13\x4f\xf3\xef\x77\xd3\xdb\xa7\xad\x39\x69\x62\xd3\xa5\x30\x72\xa1\x92\xc2\x50\xa3\x68\xc2\xfe\x04\x00\x00\xff\xff\x71\xae\x9c\xc9\x7f\x04\x00\x00") 284 | 285 | func dataPatches200P45101_readlinePatchBytes() ([]byte, error) { 286 | return bindataRead( 287 | _dataPatches200P45101_readlinePatch, 288 | "data/patches/2.0.0-p451/01_readline.patch", 289 | ) 290 | } 291 | 292 | func dataPatches200P45101_readlinePatch() (*asset, error) { 293 | bytes, err := dataPatches200P45101_readlinePatchBytes() 294 | if err != nil { 295 | return nil, err 296 | } 297 | 298 | info := bindataFileInfo{name: "data/patches/2.0.0-p451/01_readline.patch", size: 1151, mode: os.FileMode(420), modTime: time.Unix(1448757621, 0)} 299 | a := &asset{bytes: bytes, info: info} 300 | return a, nil 301 | } 302 | 303 | var _dataPatches21001_readlinePatch = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xcc\x54\xeb\x4f\xdb\x3e\x14\xfd\xfc\xf3\x5f\x71\x15\x7e\x52\x93\xe5\xb1\x3e\xc2\xa3\x03\xa4\x32\x1e\x2b\x1a\x02\x44\xd9\xbe\x5a\x26\xb9\xa5\x16\xa9\x13\xd9\x4e\x07\xff\xfd\xec\xd0\x84\x05\xb5\x15\x6c\x9a\xb4\x7c\x48\x5d\xe7\xdc\x73\x4f\xce\x3d\xce\xb9\x48\xf1\xf1\x13\xe0\xa3\xfe\x28\x91\xa5\x19\x17\xd8\x2c\xa2\x84\x1c\xfe\xf9\x45\xc2\x30\x5c\xc7\xff\x9f\x2b\x71\xc1\x15\xcf\x05\xc4\xdb\xfd\x7e\xec\x11\xdf\xf7\xdf\x08\xde\xf6\xc8\x68\x04\x61\x6f\xb8\x1b\x07\xbb\xe0\x2f\x7f\x47\x23\x02\x04\xec\x25\x33\xca\xb4\xc6\x79\xa1\x31\xa5\x49\x3e\x2f\x32\xd4\xa6\x96\x4e\x4b\x91\xd8\x05\x1c\x42\xcd\xbd\x19\xb8\x4f\x60\x8b\x4f\x21\xc5\xa9\x81\xa6\xee\xf8\xe8\xfb\x29\xbd\xb9\xa0\xd7\x37\xa7\xf4\xfc\xf2\xfa\xdb\x2d\x1d\x5f\x5d\x7d\xf5\x48\xb8\x6c\x5a\x48\xa4\x5c\x14\xa5\xa6\xb3\x3c\x7f\x30\x5d\xdc\xb3\xba\xe3\x07\xaf\xe9\xd8\x46\xed\x13\x7f\x6d\xb5\xd9\xb4\xcb\x4a\x0e\xd5\x9b\x38\x60\x0b\x45\xca\xa7\x95\x5c\xa3\x16\x6a\xa5\xc7\x47\xb7\xc7\x63\x3a\x39\xff\x72\x79\x74\x31\x69\xcc\x49\x98\x4e\x66\x54\xf1\x7b\xc1\x32\x65\x1a\x75\xf7\xc9\xaa\x30\x98\x3f\x49\x2e\xa6\x91\xbc\xfb\x3b\x61\x78\xe1\x6f\xcf\x77\x30\x5c\x11\x86\x75\xe0\xb8\x5b\x87\x21\xd8\xb1\x51\x08\x7a\xdd\x2a\x09\xe6\x45\x51\x97\x52\x80\x2a\x0b\x94\xae\xb5\x30\x80\x99\x61\x43\xa9\x3c\x02\xc6\x2e\x93\x16\xdf\x7a\xd5\xc4\x6c\xc6\x16\x48\xf5\x53\x81\xae\xbd\x79\x76\x30\x2d\x0e\xbb\xfb\x0b\x87\x6f\x39\x7c\x02\x29\x97\xd4\x4a\xe3\xf7\x6e\x27\x29\xa5\x42\xd5\xf1\xda\xbb\x62\xf5\xb6\x46\x39\x4f\x58\xd1\x79\x7e\x81\x61\x1c\xc4\xe0\x0f\xf7\x82\xbd\x4a\x7f\x5b\x95\x95\xef\x3a\x66\x74\x12\x53\xae\x8a\x8c\x3d\x39\xde\x5a\x0c\x17\x0a\xa5\xa6\xda\x58\xb6\x01\x95\xa2\x09\x3b\xd6\x28\xbf\x14\x19\x2a\xb5\xca\x0c\xa7\x1d\x43\xa7\x32\xe6\xff\x93\xd3\xb3\x09\x1c\x1c\x80\x13\x9e\xb4\x9f\x1f\xd6\x99\x77\x1a\x87\x12\xc3\x6a\x5a\xcd\xd9\x83\x39\x48\x99\x65\x5c\x76\x31\x5c\xff\x52\xf0\xe2\xfe\x7b\x82\x37\x58\xce\xad\x0a\x9e\xb9\x0f\x37\xcd\xed\x77\x66\x02\xef\x9c\xc9\x16\xbc\xfa\x60\x70\x05\x6c\xc1\x78\xc6\xee\x32\x04\xc5\x45\x82\x0d\x57\x18\x47\x7d\x70\xfb\xdd\x6e\xcf\x8b\x9e\x6b\x9b\x4f\x15\xb7\x1d\xe7\xf9\x02\x53\x60\xfa\xa5\x60\x27\x1a\xd8\x82\x5e\x5c\x17\x8c\xf3\x1f\xb8\x40\x19\x80\x89\xa4\xb6\x10\x70\x2f\x51\x7f\x9e\x9c\xc0\x4e\xd4\x8b\x06\x01\x54\x60\x48\x73\x54\xa2\xa3\xc1\x8a\x7f\x25\x30\xb2\xc7\xf4\x4d\x49\xb2\xe7\xf5\x67\x00\x00\x00\xff\xff\xdd\x85\xa5\xd3\xb0\x06\x00\x00") 304 | 305 | func dataPatches21001_readlinePatchBytes() ([]byte, error) { 306 | return bindataRead( 307 | _dataPatches21001_readlinePatch, 308 | "data/patches/2.1.0/01_readline.patch", 309 | ) 310 | } 311 | 312 | func dataPatches21001_readlinePatch() (*asset, error) { 313 | bytes, err := dataPatches21001_readlinePatchBytes() 314 | if err != nil { 315 | return nil, err 316 | } 317 | 318 | info := bindataFileInfo{name: "data/patches/2.1.0/01_readline.patch", size: 1712, mode: os.FileMode(420), modTime: time.Unix(1448757621, 0)} 319 | a := &asset{bytes: bytes, info: info} 320 | return a, nil 321 | } 322 | 323 | var _dataPatches21101_readlinePatch = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xcc\x54\xeb\x4f\xdb\x3e\x14\xfd\xfc\xf3\x5f\x71\x15\x7e\x52\x93\xe5\xb1\x3e\xc2\xa3\x03\xa4\x32\x1e\x2b\x1a\x02\x44\xd9\xbe\x5a\x26\xb9\xa5\x16\xa9\x13\xd9\x4e\x07\xff\xfd\xec\xd0\x84\x05\xb5\x15\x6c\x9a\xb4\x7c\x48\x5d\xe7\xdc\x73\x4f\xce\x3d\xce\xb9\x48\xf1\xf1\x13\xe0\xa3\xfe\x28\x91\xa5\x19\x17\xd8\x2c\xa2\x84\x1c\xfe\xf9\x45\xc2\x30\x5c\xc7\xff\x9f\x2b\x71\xc1\x15\xcf\x05\xc4\xdb\xfd\x7e\xec\x11\xdf\xf7\xdf\x08\xde\xf6\xc8\x68\x04\x61\x6f\xb8\x1b\x07\xbb\xe0\x2f\x7f\x47\x23\x02\x04\xec\x25\x33\xca\xb4\xc6\x79\xa1\x31\xa5\x49\x3e\x2f\x32\xd4\xa6\x96\x4e\x4b\x91\xd8\x05\x1c\x42\xcd\xbd\x19\xb8\x4f\x60\x8b\x4f\x21\xc5\xa9\x81\xa6\xee\xf8\xe8\xfb\x29\xbd\xb9\xa0\xd7\x37\xa7\xf4\xfc\xf2\xfa\xdb\x2d\x1d\x5f\x5d\x7d\xf5\x48\xb8\x6c\x5a\x48\xa4\x5c\x14\xa5\xa6\xb3\x3c\x7f\x30\x5d\xdc\xb3\xba\xe3\x07\xaf\xe9\xd8\x46\xed\x13\x7f\x6d\xb5\xd9\xb4\xcb\x4a\x0e\xd5\x9b\x38\x60\x0b\x45\xca\xa7\x95\x5c\xa3\x16\x6a\xa5\xc7\x47\xb7\xc7\x63\x3a\x39\xff\x72\x79\x74\x31\x69\xcc\x49\x98\x4e\x66\x54\xf1\x7b\xc1\x32\x65\x1a\x75\xf7\xc9\xaa\x30\x98\x3f\x49\x2e\xa6\x91\xbc\xfb\x3b\x61\x78\xe1\x6f\xcf\x77\x30\x5c\x11\x86\x75\xe0\xb8\x5b\x87\x21\xd8\xb1\x51\x08\x7a\xdd\x2a\x09\xe6\x45\x51\x97\x52\x80\x2a\x0b\x94\xae\xb5\x30\x80\x99\x61\x43\xa9\x3c\x02\xc6\x2e\x93\x16\xdf\x7a\xd5\xc4\x6c\xc6\x16\x48\xf5\x53\x81\xae\xbd\x79\x76\x30\x2d\x0e\xbb\xfb\x0b\x87\x6f\x39\x7c\x02\x29\x97\xd4\x4a\xe3\xf7\x6e\x27\x29\xa5\x42\xd5\xf1\xda\xbb\x62\xf5\xb6\x46\x39\x4f\x58\xd1\x79\x7e\x81\x61\x1c\xc4\xe0\x0f\xf7\x82\xbd\x4a\x7f\x5b\x95\x95\xef\x3a\x66\x74\x12\x53\xae\x8a\x8c\x3d\x39\xde\x5a\x0c\x17\x0a\xa5\xa6\xda\x58\xb6\x01\x95\xa2\x09\x3b\xd6\x28\xbf\x14\x19\x2a\xb5\xca\x0c\xa7\x1d\x43\xa7\x32\xe6\xff\x93\xd3\xb3\x09\x1c\x1c\x80\x13\x9e\xb4\x9f\x1f\xd6\x99\x77\x1a\x87\x12\xc3\x6a\x5a\xcd\xd9\x83\x39\x48\x99\x65\x5c\x76\x31\x5c\xff\x52\xf0\xe2\xfe\x7b\x82\x37\x58\xce\xad\x0a\x9e\xb9\x0f\x37\xcd\xed\x77\x66\x02\xef\x9c\xc9\x16\xbc\xfa\x60\x70\x05\x6c\xc1\x78\xc6\xee\x32\x04\xc5\x45\x82\x0d\x57\x18\x47\x7d\x70\xfb\xdd\x6e\xcf\x8b\x9e\x6b\x9b\x4f\x15\xb7\x1d\xe7\xf9\x02\x53\x60\xfa\xa5\x60\x27\x1a\xd8\x82\x5e\x5c\x17\x8c\xf3\x1f\xb8\x40\x19\x80\x89\xa4\xb6\x10\x70\x2f\x51\x7f\x9e\x9c\xc0\x4e\xd4\x8b\x06\x01\x54\x60\x48\x73\x54\xa2\xa3\xc1\x8a\x7f\x25\x30\xb2\xc7\xf4\x4d\x49\xb2\xe7\xf5\x67\x00\x00\x00\xff\xff\xdd\x85\xa5\xd3\xb0\x06\x00\x00") 324 | 325 | func dataPatches21101_readlinePatchBytes() ([]byte, error) { 326 | return bindataRead( 327 | _dataPatches21101_readlinePatch, 328 | "data/patches/2.1.1/01_readline.patch", 329 | ) 330 | } 331 | 332 | func dataPatches21101_readlinePatch() (*asset, error) { 333 | bytes, err := dataPatches21101_readlinePatchBytes() 334 | if err != nil { 335 | return nil, err 336 | } 337 | 338 | info := bindataFileInfo{name: "data/patches/2.1.1/01_readline.patch", size: 1712, mode: os.FileMode(420), modTime: time.Unix(1448757621, 0)} 339 | a := &asset{bytes: bytes, info: info} 340 | return a, nil 341 | } 342 | 343 | // Asset loads and returns the asset for the given name. 344 | // It returns an error if the asset could not be found or 345 | // could not be loaded. 346 | func Asset(name string) ([]byte, error) { 347 | cannonicalName := strings.Replace(name, "\\", "/", -1) 348 | if f, ok := _bindata[cannonicalName]; ok { 349 | a, err := f() 350 | if err != nil { 351 | return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) 352 | } 353 | return a.bytes, nil 354 | } 355 | return nil, fmt.Errorf("Asset %s not found", name) 356 | } 357 | 358 | // MustAsset is like Asset but panics when Asset would return an error. 359 | // It simplifies safe initialization of global variables. 360 | func MustAsset(name string) []byte { 361 | a, err := Asset(name) 362 | if err != nil { 363 | panic("asset: Asset(" + name + "): " + err.Error()) 364 | } 365 | 366 | return a 367 | } 368 | 369 | // AssetInfo loads and returns the asset info for the given name. 370 | // It returns an error if the asset could not be found or 371 | // could not be loaded. 372 | func AssetInfo(name string) (os.FileInfo, error) { 373 | cannonicalName := strings.Replace(name, "\\", "/", -1) 374 | if f, ok := _bindata[cannonicalName]; ok { 375 | a, err := f() 376 | if err != nil { 377 | return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) 378 | } 379 | return a.info, nil 380 | } 381 | return nil, fmt.Errorf("AssetInfo %s not found", name) 382 | } 383 | 384 | // AssetNames returns the names of the assets. 385 | func AssetNames() []string { 386 | names := make([]string, 0, len(_bindata)) 387 | for name := range _bindata { 388 | names = append(names, name) 389 | } 390 | return names 391 | } 392 | 393 | // _bindata is a table, holding each asset generator, mapped to its name. 394 | var _bindata = map[string]func() (*asset, error){ 395 | "data/Dockerfile-centos.template": dataDockerfileCentosTemplate, 396 | "data/Dockerfile-xenial.template": dataDockerfileXenialTemplate, 397 | "data/Dockerfile.template": dataDockerfileTemplate, 398 | "data/patches/1.0.0/01_for_tests": dataPatches10001_for_tests, 399 | "data/patches/1.0.0/02_for_tests": dataPatches10002_for_tests, 400 | "data/patches/1.9.3-p551/01_strict_hostname_checking.patch": dataPatches193P55101_strict_hostname_checkingPatch, 401 | "data/patches/2.0.0-p0/01_readline.patch": dataPatches200P001_readlinePatch, 402 | "data/patches/2.0.0-p195/01_readline.patch": dataPatches200P19501_readlinePatch, 403 | "data/patches/2.0.0-p247/01_readline.patch": dataPatches200P24701_readlinePatch, 404 | "data/patches/2.0.0-p353/01_readline.patch": dataPatches200P35301_readlinePatch, 405 | "data/patches/2.0.0-p451/01_readline.patch": dataPatches200P45101_readlinePatch, 406 | "data/patches/2.1.0/01_readline.patch": dataPatches21001_readlinePatch, 407 | "data/patches/2.1.1/01_readline.patch": dataPatches21101_readlinePatch, 408 | } 409 | 410 | // AssetDir returns the file names below a certain 411 | // directory embedded in the file by go-bindata. 412 | // For example if you run go-bindata on data/... and data contains the 413 | // following hierarchy: 414 | // data/ 415 | // foo.txt 416 | // img/ 417 | // a.png 418 | // b.png 419 | // then AssetDir("data") would return []string{"foo.txt", "img"} 420 | // AssetDir("data/img") would return []string{"a.png", "b.png"} 421 | // AssetDir("foo.txt") and AssetDir("notexist") would return an error 422 | // AssetDir("") will return []string{"data"}. 423 | func AssetDir(name string) ([]string, error) { 424 | node := _bintree 425 | if len(name) != 0 { 426 | cannonicalName := strings.Replace(name, "\\", "/", -1) 427 | pathList := strings.Split(cannonicalName, "/") 428 | for _, p := range pathList { 429 | node = node.Children[p] 430 | if node == nil { 431 | return nil, fmt.Errorf("Asset %s not found", name) 432 | } 433 | } 434 | } 435 | if node.Func != nil { 436 | return nil, fmt.Errorf("Asset %s not found", name) 437 | } 438 | rv := make([]string, 0, len(node.Children)) 439 | for childName := range node.Children { 440 | rv = append(rv, childName) 441 | } 442 | return rv, nil 443 | } 444 | 445 | type bintree struct { 446 | Func func() (*asset, error) 447 | Children map[string]*bintree 448 | } 449 | var _bintree = &bintree{nil, map[string]*bintree{ 450 | "data": &bintree{nil, map[string]*bintree{ 451 | "Dockerfile-centos.template": &bintree{dataDockerfileCentosTemplate, map[string]*bintree{}}, 452 | "Dockerfile-xenial.template": &bintree{dataDockerfileXenialTemplate, map[string]*bintree{}}, 453 | "Dockerfile.template": &bintree{dataDockerfileTemplate, map[string]*bintree{}}, 454 | "patches": &bintree{nil, map[string]*bintree{ 455 | "1.0.0": &bintree{nil, map[string]*bintree{ 456 | "01_for_tests": &bintree{dataPatches10001_for_tests, map[string]*bintree{}}, 457 | "02_for_tests": &bintree{dataPatches10002_for_tests, map[string]*bintree{}}, 458 | }}, 459 | "1.9.3-p551": &bintree{nil, map[string]*bintree{ 460 | "01_strict_hostname_checking.patch": &bintree{dataPatches193P55101_strict_hostname_checkingPatch, map[string]*bintree{}}, 461 | }}, 462 | "2.0.0-p0": &bintree{nil, map[string]*bintree{ 463 | "01_readline.patch": &bintree{dataPatches200P001_readlinePatch, map[string]*bintree{}}, 464 | }}, 465 | "2.0.0-p195": &bintree{nil, map[string]*bintree{ 466 | "01_readline.patch": &bintree{dataPatches200P19501_readlinePatch, map[string]*bintree{}}, 467 | }}, 468 | "2.0.0-p247": &bintree{nil, map[string]*bintree{ 469 | "01_readline.patch": &bintree{dataPatches200P24701_readlinePatch, map[string]*bintree{}}, 470 | }}, 471 | "2.0.0-p353": &bintree{nil, map[string]*bintree{ 472 | "01_readline.patch": &bintree{dataPatches200P35301_readlinePatch, map[string]*bintree{}}, 473 | }}, 474 | "2.0.0-p451": &bintree{nil, map[string]*bintree{ 475 | "01_readline.patch": &bintree{dataPatches200P45101_readlinePatch, map[string]*bintree{}}, 476 | }}, 477 | "2.1.0": &bintree{nil, map[string]*bintree{ 478 | "01_readline.patch": &bintree{dataPatches21001_readlinePatch, map[string]*bintree{}}, 479 | }}, 480 | "2.1.1": &bintree{nil, map[string]*bintree{ 481 | "01_readline.patch": &bintree{dataPatches21101_readlinePatch, map[string]*bintree{}}, 482 | }}, 483 | }}, 484 | }}, 485 | }} 486 | 487 | // RestoreAsset restores an asset under the given directory 488 | func RestoreAsset(dir, name string) error { 489 | data, err := Asset(name) 490 | if err != nil { 491 | return err 492 | } 493 | info, err := AssetInfo(name) 494 | if err != nil { 495 | return err 496 | } 497 | err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) 498 | if err != nil { 499 | return err 500 | } 501 | err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) 502 | if err != nil { 503 | return err 504 | } 505 | err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) 506 | if err != nil { 507 | return err 508 | } 509 | return nil 510 | } 511 | 512 | // RestoreAssets restores an asset under the given directory recursively 513 | func RestoreAssets(dir, name string) error { 514 | children, err := AssetDir(name) 515 | // File 516 | if err != nil { 517 | return RestoreAsset(dir, name) 518 | } 519 | // Dir 520 | for _, child := range children { 521 | err = RestoreAssets(dir, filepath.Join(name, child)) 522 | if err != nil { 523 | return err 524 | } 525 | } 526 | return nil 527 | } 528 | 529 | func _filePath(dir, name string) string { 530 | cannonicalName := strings.Replace(name, "\\", "/", -1) 531 | return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) 532 | } 533 | 534 | -------------------------------------------------------------------------------- /build_ruby.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "archive/tar" 5 | "bytes" 6 | "fmt" 7 | "github.com/fsouza/go-dockerclient" 8 | "github.com/google/uuid" 9 | "github.com/urfave/cli" 10 | "github.com/wsxiaoys/terminal/color" 11 | "io" 12 | "net/url" 13 | "os" 14 | "path/filepath" 15 | "runtime" 16 | "sort" 17 | "strings" 18 | "text/template" 19 | ) 20 | 21 | var ( 22 | distros = map[string]string{ 23 | "ubuntu_precise": "ubuntu:12.04", 24 | "ubuntu:12.04": "ubuntu:12.04", 25 | 26 | "ubuntu_raring": "ubuntu:13.04", 27 | "ubuntu:13.04": "ubuntu:13.04", 28 | 29 | "ubuntu_trusty": "ubuntu:14.04", 30 | "ubuntu:14.04": "ubuntu:14.04", 31 | 32 | "ubuntu_xenial": "ubuntu:16.04", 33 | "ubuntu:16.04": "ubuntu:16.04", 34 | 35 | "centos:6.6": "centos:6.6", 36 | } 37 | 38 | docker_client *docker.Client 39 | docker_endpoint string 40 | red func(string) string 41 | green func(string) string 42 | light_green func(string) string 43 | ) 44 | 45 | const image_tag string = "ruby_build" 46 | 47 | func init() { 48 | u, err := url.Parse(os.Getenv("DOCKER_HOST")) 49 | if err != nil { 50 | panic(err) 51 | } 52 | u.Scheme = "https" 53 | docker_endpoint = u.String() 54 | 55 | c, err := docker.NewClient(docker_endpoint) 56 | 57 | tr, err := NewHTTPSClient(os.Getenv("DOCKER_CERT_PATH")) 58 | if err != nil { 59 | panic(err) 60 | } 61 | c.HTTPClient = tr 62 | 63 | if err != nil { 64 | panic(err) 65 | } 66 | docker_client = c 67 | } 68 | 69 | func main() { 70 | 71 | app := cli.NewApp() 72 | app.Name = "build_ruby" 73 | app.Usage = "Build ruby debs from source for Ubuntu" 74 | 75 | app.Flags = []cli.Flag{ 76 | cli.StringFlag{ 77 | Name: "ruby, r", 78 | Value: "", 79 | Usage: "Required. The version to build, eg. 2.1.0 (for recent versions with no patch release) or 2.0.0-p451", 80 | }, 81 | cli.StringFlag{ 82 | Name: "distro, d", 83 | Value: "ubuntu:12.04", 84 | Usage: "Which distro to use for the build", 85 | }, 86 | cli.StringFlag{ 87 | Name: "arch, a", 88 | Value: "amd64", 89 | Usage: "Arch to use in package filename, eg: 'none', 'all', 'amd64' etc.", 90 | }, 91 | cli.StringFlag{ 92 | Name: "iteration, i", 93 | Value: "", 94 | Usage: "eg: 37s~precise", 95 | }, 96 | cli.IntFlag{ 97 | Name: "cpus, c", 98 | Usage: "The number of CPUs to use for the make process, defaults to the number in the local machine. Change if you're running on a remote docker host", 99 | }, 100 | } 101 | app.Action = buildRuby 102 | app.Run(os.Args) 103 | } 104 | 105 | func buildRuby(c *cli.Context) error { 106 | if c.String("ruby") == "" { 107 | color.Fprintln(os.Stderr, "@{r!}You didn't specify a Ruby version to build!") 108 | cli.ShowAppHelp(c) 109 | os.Exit(1) 110 | } 111 | 112 | if distros[c.String("distro")] == "" { 113 | color.Fprintln(os.Stderr, "@{r!}You specified a distro that I don't know how to build for") 114 | cli.ShowAppHelp(c) 115 | os.Exit(1) 116 | } 117 | 118 | var parallel_make_tasks int 119 | if c.Int("cpus") != 0 { 120 | parallel_make_tasks = c.Int("cpus") 121 | } else { 122 | parallel_make_tasks = runtime.NumCPU() 123 | } 124 | 125 | var patch_file_full_paths []string = patchFilePathsFromRubyVersion(c.String("ruby")) 126 | 127 | var dockerfile *bytes.Buffer = dockerFileFromTemplate(distros[c.String("distro")], c.String("ruby"), c.String("arch"), c.String("iteration"), fileBasePaths(patch_file_full_paths), parallel_make_tasks) 128 | color.Println("@{g!}Using Dockerfile:") 129 | color.Printf("@{gc}%s\n", dockerfile) 130 | 131 | var build_tarfile *bytes.Buffer = createTarFileFromDockerfile(dockerfile, patch_file_full_paths) 132 | 133 | image_uuid, err := uuid.NewRandom() 134 | if err != nil { 135 | panic(err) 136 | } 137 | image_name := fmt.Sprintf("ruby_build_%s_image", image_uuid) 138 | opts := docker.BuildImageOptions{ 139 | Name: image_name, 140 | NoCache: true, 141 | SuppressOutput: false, 142 | RmTmpContainer: true, 143 | ForceRmTmpContainer: true, 144 | InputStream: build_tarfile, 145 | OutputStream: os.Stdout, 146 | } 147 | if err := docker_client.BuildImage(opts); err != nil { 148 | panic(err) 149 | } 150 | color.Printf("@{g!}Created image with name %s\n", image_name) 151 | 152 | image, err := docker_client.InspectImage(image_name) 153 | if err != nil { 154 | panic(err) 155 | } 156 | 157 | /* 158 | Create a container with the created image id 159 | 160 | This seems like a hack. We need a "container" to enable us to copy the ruby 161 | package out, but I can't see how to do this without needed to run a command 162 | or just use specify an image ID directly, hence the noop 'date' command. 163 | 164 | */ 165 | 166 | color.Printf("@{g!}Creating container with from image id %s\n", image.ID) 167 | config := docker.Config{AttachStdout: false, AttachStdin: false, Image: image.ID, Cmd: []string{"date"}} 168 | container_uuid, err := uuid.NewRandom() 169 | if err != nil { 170 | panic(err) 171 | } 172 | container_name := fmt.Sprintf("ruby_build_%s_container", container_uuid) 173 | create_container_opts := docker.CreateContainerOptions{Name: container_name, Config: &config} 174 | container, err := docker_client.CreateContainer(create_container_opts) 175 | if err != nil { 176 | panic(err) 177 | } 178 | 179 | // See https://github.com/wjessop/build_ruby/issues/2 180 | if err := docker_client.StopContainer(container.ID, 1); err != nil { 181 | // panic(err) 182 | color.Printf("@{f}Failed to stop container %d, error was: %s\n", container.ID, err.Error()) 183 | } 184 | 185 | copyPackageFromContainerToLocalFs(container, rubyPackageFileName(c.String("ruby"), c.String("iteration"), c.String("arch"), c.String("distro"))) 186 | 187 | color.Println("@{g!}Removing container:", container.ID) 188 | if err := docker_client.RemoveContainer(docker.RemoveContainerOptions{ID: container.ID, RemoveVolumes: true, Force: false}); err != nil { 189 | panic(err) 190 | } 191 | 192 | return nil 193 | } 194 | 195 | func patchFilePathsFromRubyVersion(version string) []string { 196 | var patch_files []string 197 | for _, name := range AssetNames() { 198 | if strings.Contains(name, fmt.Sprintf("/%s/", version)) { 199 | patch_files = append(patch_files, name) 200 | } 201 | } 202 | 203 | sort.Strings(patch_files) 204 | color.Printf("@{g}Found patch files for current Ruby version: %v\n", patch_files) 205 | return patch_files 206 | } 207 | 208 | func createTarFileFromDockerfile(dockerfile *bytes.Buffer, patch_file_paths []string) *bytes.Buffer { 209 | // Create a buffer to write our archive to. 210 | buf := new(bytes.Buffer) 211 | 212 | // Create a new tar archive. 213 | tw := tar.NewWriter(buf) 214 | 215 | // Add the Dockerfile 216 | hdr := &tar.Header{ 217 | Name: "Dockerfile", 218 | Size: int64(dockerfile.Len()), 219 | } 220 | 221 | if err := tw.WriteHeader(hdr); err != nil { 222 | panic(err) 223 | } 224 | 225 | if _, err := tw.Write(dockerfile.Bytes()); err != nil { 226 | panic(err) 227 | } 228 | 229 | for _, path := range patch_file_paths { 230 | color.Printf("@{g}Adding patch file to the tar: %s (at path %s)\n", patch_file_paths, filepath.Base(path)) 231 | 232 | asset_bytes, err := Asset(path) 233 | if err != nil { 234 | panic(err) 235 | } 236 | 237 | // We store the patch files flat in the root dir, hence the Base call 238 | hdr := &tar.Header{ 239 | Name: filepath.Base(path), 240 | Size: int64(len(asset_bytes)), 241 | } 242 | if err := tw.WriteHeader(hdr); err != nil { 243 | panic(err) 244 | } 245 | 246 | if _, err := tw.Write(asset_bytes); err != nil { 247 | panic(err) 248 | } 249 | } 250 | 251 | // Make sure to check the error on Close. 252 | if err := tw.Close(); err != nil { 253 | panic(err) 254 | } 255 | 256 | return buf 257 | } 258 | 259 | func copyPackageFromContainerToLocalFs(container *docker.Container, filename string) { 260 | color.Println("@{g!}Copying package out of the container") 261 | 262 | var buf bytes.Buffer 263 | if err := docker_client.CopyFromContainer(docker.CopyFromContainerOptions{ 264 | Container: container.ID, 265 | Resource: filename, 266 | OutputStream: &buf, 267 | }); err != nil { 268 | panic(err) 269 | } 270 | 271 | buffer := bytes.NewReader(buf.Bytes()) 272 | 273 | var tar_out *tar.Reader = tar.NewReader(buffer) 274 | tar_header, err := tar_out.Next() 275 | if err != nil { 276 | panic(err) 277 | } 278 | 279 | color.Printf("@{g!}Extracting pckage file %s (%d bytes)\n", tar_header.Name, tar_header.Size) 280 | 281 | out, err := os.Create(filename) 282 | if err != nil { 283 | panic(err) 284 | } 285 | defer out.Close() 286 | 287 | io.Copy(out, tar_out) 288 | } 289 | 290 | func rubyPackageFileName(version, iteration, arch string, distro string) string { 291 | var formatted_iteration = "" 292 | if iteration != "" { 293 | formatted_iteration = "_" + iteration 294 | } 295 | 296 | var formatted_arch = "" 297 | if arch != "none" { 298 | formatted_arch = "_" + arch 299 | } 300 | return "ruby-" + version + formatted_iteration + formatted_arch + packageFormat(distro) 301 | } 302 | 303 | func packageFormat(distro string) string { 304 | if strings.Contains(distro, "centos") || strings.Contains(distro, "rhel") { 305 | return ".rpm" 306 | } else { 307 | return ".deb" 308 | } 309 | } 310 | 311 | func dockerFileFromTemplate(distro, ruby_version, arch, iteration string, patches []string, parallel_make_jobs int) *bytes.Buffer { 312 | type buildVars struct { 313 | Distro string 314 | RubyVersion string 315 | Arch string 316 | Iteration string 317 | DownloadUrl string 318 | FileName string 319 | Patches []string 320 | NumCPU int 321 | } 322 | 323 | var formatted_iteration = "" 324 | if iteration != "" { 325 | formatted_iteration = fmt.Sprintf("--iteration %s \\", iteration) 326 | } 327 | 328 | download_url := rubyDownloadUrl(ruby_version) 329 | dockerfile_vars := buildVars{distro, ruby_version, arch, formatted_iteration, download_url, rubyPackageFileName(ruby_version, iteration, arch, distro), patches, parallel_make_jobs} 330 | 331 | // This would be way better as a look up table, or with a more formal lookup process 332 | var template_location string 333 | switch distro { 334 | case "centos:6.6": 335 | template_location = "data/Dockerfile-centos.template" 336 | case "ubuntu:16.04": 337 | template_location = "data/Dockerfile-xenial.template" 338 | default: 339 | template_location = "data/Dockerfile.template" 340 | } 341 | 342 | dockerfile_template, err := Asset(template_location) 343 | if err != nil { 344 | panic(err) 345 | } 346 | if len(dockerfile_template) == 0 { 347 | panic("Couldn't find Dockerfile template in bindata") 348 | } 349 | 350 | tmpl, err := template.New("dockerfile_template").Parse(string(dockerfile_template)) 351 | if err != nil { 352 | panic(err) 353 | } 354 | 355 | buf := new(bytes.Buffer) 356 | 357 | err = tmpl.Execute(buf, dockerfile_vars) 358 | if err != nil { 359 | panic(err) 360 | } 361 | 362 | return buf 363 | } 364 | 365 | func rubyDownloadUrl(version string) string { 366 | // eg: 367 | // http://cache.ruby-lang.org/pub/ruby/2.1/ruby-2.1.1.tar.gz 368 | // http://cache.ruby-lang.org/pub/ruby/2.0/ruby-2.0.0-p451.tar.gz 369 | 370 | v := majorMinorVersionOnly(version) 371 | return "http://cache.ruby-lang.org/pub/ruby/" + v + "/ruby-" + version + ".tar.gz" 372 | } 373 | 374 | func majorMinorVersionOnly(full_version string) string { 375 | return strings.Join(strings.SplitN(full_version, ".", 3)[0:2], ".") 376 | } 377 | 378 | func fileBasePaths(full_paths []string) (base_paths []string) { 379 | for _, p := range full_paths { 380 | base_paths = append(base_paths, filepath.Base(p)) 381 | } 382 | 383 | return 384 | } 385 | -------------------------------------------------------------------------------- /build_ruby_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "archive/tar" 5 | "bytes" 6 | "fmt" 7 | "github.com/stretchr/testify/assert" 8 | "io/ioutil" 9 | "path/filepath" 10 | "testing" 11 | ) 12 | 13 | /* 14 | 15 | Unit tests. Skipped the tests that would have required mocking the Docker API 16 | for now, may make them actually create package files. 17 | 18 | */ 19 | 20 | func Test_majorMinorVersionOnly(t *testing.T) { 21 | assert.Equal(t, majorMinorVersionOnly("2.1.34"), "2.1") 22 | assert.Equal(t, majorMinorVersionOnly("1.9.3-p635"), "1.9") 23 | } 24 | 25 | func Test_rubyDownloadUrl(t *testing.T) { 26 | assert.Equal(t, rubyDownloadUrl("2.1.34"), "http://cache.ruby-lang.org/pub/ruby/2.1/ruby-2.1.34.tar.gz") 27 | assert.Equal(t, rubyDownloadUrl("2.0.34-p451"), "http://cache.ruby-lang.org/pub/ruby/2.0/ruby-2.0.34-p451.tar.gz") 28 | } 29 | 30 | // Could do with pushing this out to go-bindata or similar 31 | func Test_dockerFileFromTemplate(t *testing.T) { 32 | dockerfile_output := fmt.Sprintf(`FROM ubuntu:12.04 33 | RUN apt-get update 34 | RUN apt-get install -y ruby1.9.3 build-essential \ 35 | libc6-dev libffi-dev libgdbm-dev libncurses5-dev \ 36 | libreadline-dev libssl-dev libyaml-dev zlib1g-dev \ 37 | curl 38 | RUN ["/usr/bin/gem", "install", "fpm", "--bindir=/usr/bin", "--no-rdoc", "--no-ri"] 39 | RUN curl http://cache.ruby-lang.org/pub/ruby/2.1/ruby-2.1.34.tar.gz|tar oxzC /tmp 40 | ADD 01_strict_hostname_checking.patch / 41 | 42 | WORKDIR /tmp/ruby-2.1.34 43 | RUN for i in `+"`/bin/ls /*.patch`"+`; do patch -p0 < $i; done 44 | RUN CFLAGS='-march=x86-64 -O3 -fno-fast-math -g3 -ggdb -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wunused-variable -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wimplicit-function-declaration -Wdeprecated-declarations -Wno-packed-bitfield-compat -std=iso9899:1999 -fPIC' ./configure \ 45 | --prefix=/usr/local \ 46 | --enable-shared \ 47 | --disable-install-doc \ 48 | --enable-load-relative 49 | # Seems to only affect some 1.9 series Rubies, but the combined make step: 50 | # 51 | # RUN make -j8 install DESTDIR=/tmp/fpm 52 | # 53 | # that ran the make then make install, was broken. Splitting it up into 54 | # two separate commands works fine: 55 | RUN make -j%d 56 | RUN make install DESTDIR=/tmp/fpm 57 | 58 | WORKDIR / 59 | RUN fpm \ 60 | -s dir \ 61 | -t deb \ 62 | -n ruby \ 63 | -a amd64 \ 64 | -v 2.1.34 \ 65 | --iteration 37s~precise \ 66 | -d libc6-dev \ 67 | -d libffi-dev \ 68 | -d libgdbm-dev \ 69 | -d libncurses5-dev \ 70 | -d libreadline-dev \ 71 | -d libssl-dev \ 72 | -d libyaml-dev \ 73 | -d zlib1g-dev \ 74 | -C /tmp/fpm \ 75 | -p /ruby-2.1.34_37s~precise_amd64.deb \ 76 | usr 77 | `, 18) 78 | 79 | assert.Equal(t, dockerFileFromTemplate("ubuntu:12.04", "2.1.34", "amd64", "37s~precise", []string{"01_strict_hostname_checking.patch"}, 18).String(), dockerfile_output) 80 | } 81 | 82 | func Test_rubyPackageFileName(t *testing.T) { 83 | assert.Equal(t, "ruby-2.1.0_37s~raring_amd64.deb", rubyPackageFileName("2.1.0", "37s~raring", "amd64", "ubuntu:12.04")) 84 | } 85 | 86 | func Test_createTarFileFromDockerfile(t *testing.T) { 87 | patch_files := []string{"Dockerfile", "data/patches/1.0.0/01_for_tests", "data/patches/1.0.0/02_for_tests"} 88 | file_data := []string{"foo", "bar", "baz"} 89 | 90 | tar_in_buffer := createTarFileFromDockerfile(bytes.NewBufferString("foo"), patch_files[1:3]) 91 | 92 | var tar_out *tar.Reader = tar.NewReader(tar_in_buffer) 93 | 94 | for i, filename := range patch_files { 95 | // Get the header so we can check the names of the files 96 | tar_header, err := tar_out.Next() 97 | if err != nil { 98 | panic(err) 99 | } 100 | 101 | var out_bytes []byte 102 | out_bytes, err = ioutil.ReadAll(tar_out) 103 | if err != nil { 104 | panic(err) 105 | } 106 | 107 | assert.Equal(t, tar_header.Name, filepath.Base(filename)) 108 | assert.Equal(t, string(out_bytes), file_data[i]) 109 | } 110 | } 111 | 112 | func Test_patchFilePathsFromRubyVersion(t *testing.T) { 113 | patches := patchFilePathsFromRubyVersion("1.0.0") 114 | expected_patches := []string{"data/patches/1.0.0/01_for_tests", "data/patches/1.0.0/02_for_tests"} 115 | assert.Equal(t, patches, expected_patches) 116 | } 117 | 118 | func Test_copyPackageFromContainerToLocalFs(t *testing.T) { 119 | t.Skip() 120 | } 121 | 122 | func Test_buildRuby(t *testing.T) { 123 | t.Skip() 124 | } 125 | -------------------------------------------------------------------------------- /client.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/tls" 5 | "crypto/x509" 6 | "io/ioutil" 7 | "net/http" 8 | "path/filepath" 9 | ) 10 | 11 | /* 12 | We need to create our own TLS connection for the new boot2docker 13 | version, see https://github.com/fsouza/go-dockerclient/issues/166 14 | for details, this code based on stuff found there. 15 | */ 16 | 17 | func NewHTTPSClient(cert string) (*http.Client, error) { 18 | cas := x509.NewCertPool() 19 | pemData, err := ioutil.ReadFile(filepath.Join(cert, "ca.pem")) 20 | if err != nil { 21 | return nil, err 22 | } 23 | 24 | //add to pool and configrue tls 25 | cas.AppendCertsFromPEM(pemData) 26 | 27 | //load pair 28 | pair, err := tls.LoadX509KeyPair(filepath.Join(cert, "cert.pem"), filepath.Join(cert, "key.pem")) 29 | if err != nil { 30 | return nil, err 31 | } 32 | 33 | //create new tls config with the created ca and pair 34 | conf := &tls.Config{ 35 | RootCAs: cas, 36 | Certificates: []tls.Certificate{pair}, 37 | } 38 | 39 | //create our own transport 40 | tr := &http.Transport{ 41 | TLSClientConfig: conf, 42 | } 43 | 44 | return &http.Client{Transport: tr}, nil 45 | } 46 | -------------------------------------------------------------------------------- /data/Dockerfile-centos.template: -------------------------------------------------------------------------------- 1 | FROM {{.Distro}} 2 | RUN yum update -y 3 | RUN yum install -y gcc gcc-c++ make automake kernel-devel rpm-build \ 4 | glibc-devel libffi-devel gdbm-devel ncurses-devel \ 5 | readline-devel openssl-devel libyaml-devel zlib-devel \ 6 | curl tar 7 | # Install a more modern version of Ruby. A dep of fpm got updated and isn't 8 | # compatible with ruby 1.8.7 which is what is installed via yum 9 | ADD https://sendcat.com/dl/BadJLd0pAxQ1JVCJ4jLCtf5MrF8E3A9bn2vKSmanZfOt1DQQ91zjCgw/1651/ruby-2.3.0_37s~centos_amd64.rpm /tmp/ 10 | RUN rpm -i /tmp/ruby-2.3.0_37s~centos_amd64.rpm 11 | RUN ["/opt/ruby2.3.0/bin/gem", "install", "fpm", "--bindir=/usr/bin", "--no-rdoc", "--no-ri"] 12 | RUN curl {{.DownloadUrl}}|tar oxzC /tmp 13 | {{range .Patches}}ADD {{.}} / 14 | {{end}} 15 | WORKDIR /tmp/ruby-{{.RubyVersion}} 16 | RUN for i in `/bin/ls /*.patch`; do patch -p0 < $i; done 17 | RUN CFLAGS='-march=x86-64 -O3 -fno-fast-math -g3 -ggdb -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wunused-variable -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wimplicit-function-declaration -Wdeprecated-declarations -Wno-packed-bitfield-compat -std=iso9899:1999 -fPIC' ./configure \ 18 | --prefix=/usr/local \ 19 | --enable-shared \ 20 | --disable-install-doc \ 21 | --enable-load-relative 22 | # Seems to only affect some 1.9 series Rubies, but the combined make step: 23 | # 24 | # RUN make -j8 install DESTDIR=/tmp/fpm 25 | # 26 | # that ran the make then make install, was broken. Splitting it up into 27 | # two separate commands works fine: 28 | RUN make -j{{.NumCPU}} 29 | RUN make install DESTDIR=/tmp/fpm 30 | 31 | WORKDIR / 32 | RUN fpm \ 33 | -s dir \ 34 | -t rpm \ 35 | -n ruby \ 36 | -a {{.Arch}} \ 37 | -v {{.RubyVersion}} \ 38 | {{.Iteration}} 39 | -d glibc-devel \ 40 | -d libffi-devel \ 41 | -d gdbm-devel \ 42 | -d ncurses-devel \ 43 | -d readline-devel \ 44 | -d openssl-devel \ 45 | -d libyaml-devel \ 46 | -d zlib-devel \ 47 | -C /tmp/fpm \ 48 | -p /{{.FileName}} \ 49 | usr 50 | -------------------------------------------------------------------------------- /data/Dockerfile-xenial.template: -------------------------------------------------------------------------------- 1 | FROM {{.Distro}} 2 | RUN apt-get update 3 | RUN apt-get install -y build-essential \ 4 | libc6-dev libffi-dev libgdbm-dev libncurses5-dev \ 5 | libreadline-dev libssl-dev libyaml-dev zlib1g-dev \ 6 | curl ruby ruby-dev 7 | RUN ["gem", "install", "fpm", "--bindir=/usr/bin", "--no-rdoc", "--no-ri"] 8 | 9 | RUN curl {{.DownloadUrl}}|tar oxzC /tmp 10 | {{range .Patches}}ADD {{.}} / 11 | {{end}} 12 | WORKDIR /tmp/ruby-{{.RubyVersion}} 13 | RUN for i in `/bin/ls /*.patch`; do patch -p0 < $i; done 14 | RUN CFLAGS='-march=x86-64 -O3 -fno-fast-math -g3 -ggdb -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wunused-variable -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wimplicit-function-declaration -Wdeprecated-declarations -Wno-packed-bitfield-compat -std=iso9899:1999 -fPIC' ./configure \ 15 | --prefix=/usr/local \ 16 | --enable-shared \ 17 | --disable-install-doc \ 18 | --enable-load-relative 19 | # Seems to only affect some 1.9 series Rubies, but the combined make step: 20 | # 21 | # RUN make -j8 install DESTDIR=/tmp/fpm 22 | # 23 | # that ran the make then make install, was broken. Splitting it up into 24 | # two separate commands works fine: 25 | RUN make -j{{.NumCPU}} 26 | RUN make install DESTDIR=/tmp/fpm 27 | 28 | WORKDIR / 29 | RUN fpm \ 30 | -s dir \ 31 | -t deb \ 32 | -n ruby \ 33 | -a {{.Arch}} \ 34 | -v {{.RubyVersion}} \ 35 | {{.Iteration}} 36 | -d libc6-dev \ 37 | -d libffi-dev \ 38 | -d libgdbm-dev \ 39 | -d libncurses5-dev \ 40 | -d libreadline-dev \ 41 | -d libssl-dev \ 42 | -d libyaml-dev \ 43 | -d zlib1g-dev \ 44 | -C /tmp/fpm \ 45 | -p /{{.FileName}} \ 46 | usr 47 | -------------------------------------------------------------------------------- /data/Dockerfile.template: -------------------------------------------------------------------------------- 1 | FROM {{.Distro}} 2 | RUN apt-get update 3 | RUN apt-get install -y ruby1.9.3 build-essential \ 4 | libc6-dev libffi-dev libgdbm-dev libncurses5-dev \ 5 | libreadline-dev libssl-dev libyaml-dev zlib1g-dev \ 6 | curl 7 | RUN ["/usr/bin/gem", "install", "fpm", "--bindir=/usr/bin", "--no-rdoc", "--no-ri"] 8 | RUN curl {{.DownloadUrl}}|tar oxzC /tmp 9 | {{range .Patches}}ADD {{.}} / 10 | {{end}} 11 | WORKDIR /tmp/ruby-{{.RubyVersion}} 12 | RUN for i in `/bin/ls /*.patch`; do patch -p0 < $i; done 13 | RUN CFLAGS='-march=x86-64 -O3 -fno-fast-math -g3 -ggdb -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wunused-variable -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wimplicit-function-declaration -Wdeprecated-declarations -Wno-packed-bitfield-compat -std=iso9899:1999 -fPIC' ./configure \ 14 | --prefix=/usr/local \ 15 | --enable-shared \ 16 | --disable-install-doc \ 17 | --enable-load-relative 18 | # Seems to only affect some 1.9 series Rubies, but the combined make step: 19 | # 20 | # RUN make -j8 install DESTDIR=/tmp/fpm 21 | # 22 | # that ran the make then make install, was broken. Splitting it up into 23 | # two separate commands works fine: 24 | RUN make -j{{.NumCPU}} 25 | RUN make install DESTDIR=/tmp/fpm 26 | 27 | WORKDIR / 28 | RUN fpm \ 29 | -s dir \ 30 | -t deb \ 31 | -n ruby \ 32 | -a {{.Arch}} \ 33 | -v {{.RubyVersion}} \ 34 | {{.Iteration}} 35 | -d libc6-dev \ 36 | -d libffi-dev \ 37 | -d libgdbm-dev \ 38 | -d libncurses5-dev \ 39 | -d libreadline-dev \ 40 | -d libssl-dev \ 41 | -d libyaml-dev \ 42 | -d zlib1g-dev \ 43 | -C /tmp/fpm \ 44 | -p /{{.FileName}} \ 45 | usr 46 | -------------------------------------------------------------------------------- /data/patches/1.0.0/01_for_tests: -------------------------------------------------------------------------------- 1 | bar -------------------------------------------------------------------------------- /data/patches/1.0.0/02_for_tests: -------------------------------------------------------------------------------- 1 | baz -------------------------------------------------------------------------------- /data/patches/1.9.3-p551/01_strict_hostname_checking.patch: -------------------------------------------------------------------------------- 1 | From 9c237a872b30b041b414405258692fe00188c2e5 Mon Sep 17 00:00:00 2001 2 | From: Tony Arcieri 3 | Date: Sun, 29 Mar 2015 17:28:44 -0700 4 | Subject: [PATCH] Stricter hostname verification following RFC 6125. 5 | 6 | Thanks to @nahi for the tests and initial documentation. 7 | --- 8 | ext/openssl/lib/openssl/ssl-internal.rb | 62 ++++++++++++++++++++-- 9 | test/openssl/test_ssl.rb | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 10 | 2 files changed, 208 insertions(+), 4 deletions(-) 11 | 12 | diff --git a/ext/openssl/lib/openssl/ssl.rb b/ext/openssl/lib/openssl/ssl.rb 13 | index ff1d4ef..caf0b9a 100644 14 | --- ext/openssl/lib/openssl/ssl-internal.rb 15 | +++ ext/openssl/lib/openssl/ssl-internal.rb 16 | @@ -143,8 +143,7 @@ def verify_certificate_identity(cert, hostname) 17 | case san.tag 18 | when 2 # dNSName in GeneralName (RFC5280) 19 | should_verify_common_name = false 20 | - reg = Regexp.escape(san.value).gsub(/\\\*/, "[^.]+") 21 | - return true if /\A#{reg}\z/i =~ hostname 22 | + return true if verify_hostname(hostname, san.value) 23 | when 7 # iPAddress in GeneralName (RFC5280) 24 | should_verify_common_name = false 25 | # follows GENERAL_NAME_print() in x509v3/v3_alt.c 26 | @@ -159,8 +158,7 @@ def verify_certificate_identity(cert, hostname) 27 | if should_verify_common_name 28 | cert.subject.to_a.each{|oid, value| 29 | if oid == "CN" 30 | - reg = Regexp.escape(value).gsub(/\\\*/, "[^.]+") 31 | - return true if /\A#{reg}\z/i =~ hostname 32 | + return true if verify_hostname(hostname, value) 33 | end 34 | } 35 | end 36 | @@ -168,11 +166,67 @@ def verify_certificate_identity(cert, hostname) 37 | end 38 | module_function :verify_certificate_identity 39 | 40 | + def verify_hostname(hostname, san) # :nodoc: 41 | + # RFC 5280, IA5String is limited to the set of ASCII characters 42 | + return false unless san.ascii_only? 43 | + return false unless hostname.ascii_only? 44 | + 45 | + # See RFC 6125, section 6.4.1 46 | + # Matching is case-insensitive. 47 | + san_parts = san.downcase.split(".") 48 | + 49 | + # TODO: this behavior should probably be more strict 50 | + return san == hostname if san_parts.size < 2 51 | + 52 | + # Matching is case-insensitive. 53 | + host_parts = hostname.downcase.split(".") 54 | + 55 | + # RFC 6125, section 6.4.3, subitem 2. 56 | + # If the wildcard character is the only character of the left-most 57 | + # label in the presented identifier, the client SHOULD NOT compare 58 | + # against anything but the left-most label of the reference 59 | + # identifier (e.g., *.example.com would match foo.example.com but 60 | + # not bar.foo.example.com or example.com). 61 | + return false unless san_parts.size == host_parts.size 62 | + 63 | + # RFC 6125, section 6.4.3, subitem 1. 64 | + # The client SHOULD NOT attempt to match a presented identifier in 65 | + # which the wildcard character comprises a label other than the 66 | + # left-most label (e.g., do not match bar.*.example.net). 67 | + return false unless verify_wildcard(host_parts.shift, san_parts.shift) 68 | + 69 | + san_parts.join(".") == host_parts.join(".") 70 | + end 71 | + module_function :verify_hostname 72 | + 73 | + def verify_wildcard(domain_component, san_component) # :nodoc: 74 | + parts = san_component.split("*", -1) 75 | + 76 | + return false if parts.size > 2 77 | + return san_component == domain_component if parts.size == 1 78 | + 79 | + # RFC 6125, section 6.4.3, subitem 3. 80 | + # The client SHOULD NOT attempt to match a presented identifier 81 | + # where the wildcard character is embedded within an A-label or 82 | + # U-label of an internationalized domain name. 83 | + return false if domain_component.start_with?("xn--") && san_component != "*" 84 | + 85 | + parts[0].length + parts[1].length < domain_component.length && 86 | + domain_component.start_with?(parts[0]) && 87 | + domain_component.end_with?(parts[1]) 88 | + end 89 | + module_function :verify_wildcard 90 | + 91 | class SSLSocket 92 | include Buffering 93 | include SocketForwarder 94 | include Nonblock 95 | 96 | + ## 97 | + # Perform hostname verification after an SSL connection is established 98 | + # 99 | + # This method MUST be called after calling #connect to ensure that the 100 | + # hostname of a remote peer has been verified. 101 | def post_connection_check(hostname) 102 | unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname) 103 | raise SSLError, "hostname \"#{hostname}\" does not match the server certificate" 104 | diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb 105 | index b65399f..4240182 100644 106 | --- test/openssl/test_ssl.rb 107 | +++ test/openssl/test_ssl.rb 108 | @@ -426,6 +426,156 @@ def test_verify_certificate_identity 109 | end 110 | end 111 | 112 | + def test_verify_hostname 113 | + assert_equal(true, OpenSSL::SSL.verify_hostname("www.example.com", "*.example.com")) 114 | + assert_equal(false, OpenSSL::SSL.verify_hostname("www.subdomain.example.com", "*.example.com")) 115 | + end 116 | + 117 | + def test_verify_wildcard 118 | + assert_equal(false, OpenSSL::SSL.verify_wildcard("foo", "x*")) 119 | + assert_equal(true, OpenSSL::SSL.verify_wildcard("foo", "foo")) 120 | + assert_equal(true, OpenSSL::SSL.verify_wildcard("foo", "f*")) 121 | + assert_equal(true, OpenSSL::SSL.verify_wildcard("foo", "*")) 122 | + assert_equal(false, OpenSSL::SSL.verify_wildcard("abc*bcd", "abcd")) 123 | + assert_equal(false, OpenSSL::SSL.verify_wildcard("xn--qdk4b9b", "x*")) 124 | + assert_equal(false, OpenSSL::SSL.verify_wildcard("xn--qdk4b9b", "*--qdk4b9b")) 125 | + assert_equal(true, OpenSSL::SSL.verify_wildcard("xn--qdk4b9b", "xn--qdk4b9b")) 126 | + end 127 | + 128 | + # Comments in this test is excerpted from http://tools.ietf.org/html/rfc6125#page-27 129 | + def test_post_connection_check_wildcard_san 130 | + # case-insensitive ASCII comparison 131 | + # RFC 6125, section 6.4.1 132 | + # 133 | + # "..matching of the reference identifier against the presented identifier 134 | + # is performed by comparing the set of domain name labels using a 135 | + # case-insensitive ASCII comparison, as clarified by [DNS-CASE] (e.g., 136 | + # "WWW.Example.Com" would be lower-cased to "www.example.com" for 137 | + # comparison purposes) 138 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 139 | + create_cert_with_san('DNS:*.example.com'), 'www.example.com')) 140 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 141 | + create_cert_with_san('DNS:*.Example.COM'), 'www.example.com')) 142 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 143 | + create_cert_with_san('DNS:*.example.com'), 'WWW.Example.COM')) 144 | + # 1. The client SHOULD NOT attempt to match a presented identifier in 145 | + # which the wildcard character comprises a label other than the 146 | + # left-most label (e.g., do not match bar.*.example.net). 147 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 148 | + create_cert_with_san('DNS:www.*.com'), 'www.example.com')) 149 | + # 2. If the wildcard character is the only character of the left-most 150 | + # label in the presented identifier, the client SHOULD NOT compare 151 | + # against anything but the left-most label of the reference 152 | + # identifier (e.g., *.example.com would match foo.example.com but 153 | + # not bar.foo.example.com or example.com). 154 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 155 | + create_cert_with_san('DNS:*.example.com'), 'foo.example.com')) 156 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 157 | + create_cert_with_san('DNS:*.example.com'), 'bar.foo.example.com')) 158 | + # 3. The client MAY match a presented identifier in which the wildcard 159 | + # character is not the only character of the label (e.g., 160 | + # baz*.example.net and *baz.example.net and b*z.example.net would 161 | + # be taken to match baz1.example.net and foobaz.example.net and 162 | + # buzz.example.net, respectively). ... 163 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 164 | + create_cert_with_san('DNS:baz*.example.com'), 'baz1.example.com')) 165 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 166 | + create_cert_with_san('DNS:*baz.example.com'), 'foobaz.example.com')) 167 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 168 | + create_cert_with_san('DNS:b*z.example.com'), 'buzz.example.com')) 169 | + # Section 6.4.3 of RFC6125 states that client should NOT match identifier 170 | + # where wildcard is other than left-most label. 171 | + # 172 | + # Also implicitly mentions the wildcard character only in singular form, 173 | + # and discourages matching against more than one wildcard. 174 | + # 175 | + # See RFC 6125, section 7.2, subitem 2. 176 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 177 | + create_cert_with_san('DNS:*b*.example.com'), 'abc.example.com')) 178 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 179 | + create_cert_with_san('DNS:*b*.example.com'), 'ab.example.com')) 180 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 181 | + create_cert_with_san('DNS:*b*.example.com'), 'bc.example.com')) 182 | + # ... However, the client SHOULD NOT 183 | + # attempt to match a presented identifier where the wildcard 184 | + # character is embedded within an A-label or U-label [IDNA-DEFS] of 185 | + # an internationalized domain name [IDNA-PROTO]. 186 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 187 | + create_cert_with_san('DNS:xn*.example.com'), 'xn1ca.example.com')) 188 | + # part of A-label 189 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 190 | + create_cert_with_san('DNS:xn--*.example.com'), 'xn--1ca.example.com')) 191 | + # part of U-label 192 | + # dNSName in RFC5280 is an IA5String so U-label should NOT be allowed 193 | + # regardless of wildcard. 194 | + # 195 | + # See Section 7.2 of RFC 5280: 196 | + # IA5String is limited to the set of ASCII characters. 197 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 198 | + create_cert_with_san('DNS:á*.example.com'), 'á1.example.com')) 199 | + end 200 | + 201 | + def test_post_connection_check_wildcard_cn 202 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 203 | + create_cert_with_name('*.example.com'), 'www.example.com')) 204 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 205 | + create_cert_with_name('*.Example.COM'), 'www.example.com')) 206 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 207 | + create_cert_with_name('*.example.com'), 'WWW.Example.COM')) 208 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 209 | + create_cert_with_name('www.*.com'), 'www.example.com')) 210 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 211 | + create_cert_with_name('*.example.com'), 'foo.example.com')) 212 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 213 | + create_cert_with_name('*.example.com'), 'bar.foo.example.com')) 214 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 215 | + create_cert_with_name('baz*.example.com'), 'baz1.example.com')) 216 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 217 | + create_cert_with_name('*baz.example.com'), 'foobaz.example.com')) 218 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 219 | + create_cert_with_name('b*z.example.com'), 'buzz.example.com')) 220 | + # Section 6.4.3 of RFC6125 states that client should NOT match identifier 221 | + # where wildcard is other than left-most label. 222 | + # 223 | + # Also implicitly mentions the wildcard character only in singular form, 224 | + # and discourages matching against more than one wildcard. 225 | + # 226 | + # See RFC 6125, section 7.2, subitem 2. 227 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 228 | + create_cert_with_name('*b*.example.com'), 'abc.example.com')) 229 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 230 | + create_cert_with_name('*b*.example.com'), 'ab.example.com')) 231 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 232 | + create_cert_with_name('*b*.example.com'), 'bc.example.com')) 233 | + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( 234 | + create_cert_with_name('xn*.example.com'), 'xn1ca.example.com')) 235 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 236 | + create_cert_with_name('xn--*.example.com'), 'xn--1ca.example.com')) 237 | + # part of U-label 238 | + # Subject in RFC5280 states case-insensitive ASCII comparison. 239 | + # 240 | + # See Section 7.2 of RFC 5280: 241 | + # IA5String is limited to the set of ASCII characters. 242 | + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( 243 | + create_cert_with_name('á*.example.com'), 'á1.example.com')) 244 | + end 245 | + 246 | + def create_cert_with_san(san) 247 | + ef = OpenSSL::X509::ExtensionFactory.new 248 | + cert = OpenSSL::X509::Certificate.new 249 | + cert.subject = OpenSSL::X509::Name.parse("/DC=some/DC=site/CN=Some Site") 250 | + ext = ef.create_ext('subjectAltName', san) 251 | + cert.add_extension(ext) 252 | + cert 253 | + end 254 | + 255 | + def create_cert_with_name(name) 256 | + cert = OpenSSL::X509::Certificate.new 257 | + cert.subject = OpenSSL::X509::Name.new([['DC', 'some'], ['DC', 'site'], ['CN', name]]) 258 | + cert 259 | + end 260 | + 261 | + 262 | # Create NULL byte SAN certificate 263 | def create_null_byte_SAN_certificate(critical = false) 264 | ef = OpenSSL::X509::ExtensionFactory.new -------------------------------------------------------------------------------- /data/patches/2.0.0-p0/01_readline.patch: -------------------------------------------------------------------------------- 1 | diff --git ext/readline/extconf.rb ext/readline/extconf.rb 2 | index 4920137..8e81253 100644 3 | --- ext/readline/extconf.rb 4 | +++ ext/readline/extconf.rb 5 | @@ -19,6 +19,10 @@ def readline.have_func(func) 6 | return super(func, headers) 7 | end 8 | 9 | +def readline.have_type(type) 10 | + return super(type, headers) 11 | +end 12 | + 13 | dir_config('curses') 14 | dir_config('ncurses') 15 | dir_config('termcap') 16 | @@ -93,4 +97,9 @@ readline.have_func("remove_history") 17 | readline.have_func("clear_history") 18 | readline.have_func("rl_redisplay") 19 | readline.have_func("rl_insert_text") 20 | + 21 | +unless readline.have_type("rl_hook_func_t") 22 | + $defs << "-Drl_hook_func_t=Function" 23 | +end 24 | + 25 | create_makefile("readline") 26 | diff --git ext/readline/readline.c ext/readline/readline.c 27 | index 3e7feea..482bf80 100644 28 | --- ext/readline/readline.c 29 | +++ ext/readline/readline.c 30 | @@ -1883,7 +1883,7 @@ Init_readline() 31 | 32 | rl_attempted_completion_function = readline_attempted_completion_function; 33 | #if defined(HAVE_RL_PRE_INPUT_HOOK) 34 | - rl_pre_input_hook = (Function *)readline_pre_input_hook; 35 | + rl_pre_input_hook = (rl_hook_func_t *)readline_pre_input_hook; 36 | #endif 37 | #ifdef HAVE_RL_CATCH_SIGNALS 38 | rl_catch_signals = 0; 39 | -------------------------------------------------------------------------------- /data/patches/2.0.0-p195/01_readline.patch: -------------------------------------------------------------------------------- 1 | diff --git ext/readline/extconf.rb ext/readline/extconf.rb 2 | index 4920137..8e81253 100644 3 | --- ext/readline/extconf.rb 4 | +++ ext/readline/extconf.rb 5 | @@ -19,6 +19,10 @@ def readline.have_func(func) 6 | return super(func, headers) 7 | end 8 | 9 | +def readline.have_type(type) 10 | + return super(type, headers) 11 | +end 12 | + 13 | dir_config('curses') 14 | dir_config('ncurses') 15 | dir_config('termcap') 16 | @@ -93,4 +97,9 @@ readline.have_func("remove_history") 17 | readline.have_func("clear_history") 18 | readline.have_func("rl_redisplay") 19 | readline.have_func("rl_insert_text") 20 | + 21 | +unless readline.have_type("rl_hook_func_t") 22 | + $defs << "-Drl_hook_func_t=Function" 23 | +end 24 | + 25 | create_makefile("readline") 26 | diff --git ext/readline/readline.c ext/readline/readline.c 27 | index 3e7feea..482bf80 100644 28 | --- ext/readline/readline.c 29 | +++ ext/readline/readline.c 30 | @@ -1883,7 +1883,7 @@ Init_readline() 31 | 32 | rl_attempted_completion_function = readline_attempted_completion_function; 33 | #if defined(HAVE_RL_PRE_INPUT_HOOK) 34 | - rl_pre_input_hook = (Function *)readline_pre_input_hook; 35 | + rl_pre_input_hook = (rl_hook_func_t *)readline_pre_input_hook; 36 | #endif 37 | #ifdef HAVE_RL_CATCH_SIGNALS 38 | rl_catch_signals = 0; 39 | -------------------------------------------------------------------------------- /data/patches/2.0.0-p247/01_readline.patch: -------------------------------------------------------------------------------- 1 | diff --git ext/readline/extconf.rb ext/readline/extconf.rb 2 | index 4920137..8e81253 100644 3 | --- ext/readline/extconf.rb 4 | +++ ext/readline/extconf.rb 5 | @@ -19,6 +19,10 @@ def readline.have_func(func) 6 | return super(func, headers) 7 | end 8 | 9 | +def readline.have_type(type) 10 | + return super(type, headers) 11 | +end 12 | + 13 | dir_config('curses') 14 | dir_config('ncurses') 15 | dir_config('termcap') 16 | @@ -93,4 +97,9 @@ readline.have_func("remove_history") 17 | readline.have_func("clear_history") 18 | readline.have_func("rl_redisplay") 19 | readline.have_func("rl_insert_text") 20 | + 21 | +unless readline.have_type("rl_hook_func_t") 22 | + $defs << "-Drl_hook_func_t=Function" 23 | +end 24 | + 25 | create_makefile("readline") 26 | diff --git ext/readline/readline.c ext/readline/readline.c 27 | index 3e7feea..482bf80 100644 28 | --- ext/readline/readline.c 29 | +++ ext/readline/readline.c 30 | @@ -1883,7 +1883,7 @@ Init_readline() 31 | 32 | rl_attempted_completion_function = readline_attempted_completion_function; 33 | #if defined(HAVE_RL_PRE_INPUT_HOOK) 34 | - rl_pre_input_hook = (Function *)readline_pre_input_hook; 35 | + rl_pre_input_hook = (rl_hook_func_t *)readline_pre_input_hook; 36 | #endif 37 | #ifdef HAVE_RL_CATCH_SIGNALS 38 | rl_catch_signals = 0; 39 | -------------------------------------------------------------------------------- /data/patches/2.0.0-p353/01_readline.patch: -------------------------------------------------------------------------------- 1 | diff --git ext/readline/extconf.rb ext/readline/extconf.rb 2 | index 4920137..8e81253 100644 3 | --- ext/readline/extconf.rb 4 | +++ ext/readline/extconf.rb 5 | @@ -19,6 +19,10 @@ def readline.have_func(func) 6 | return super(func, headers) 7 | end 8 | 9 | +def readline.have_type(type) 10 | + return super(type, headers) 11 | +end 12 | + 13 | dir_config('curses') 14 | dir_config('ncurses') 15 | dir_config('termcap') 16 | @@ -93,4 +97,9 @@ readline.have_func("remove_history") 17 | readline.have_func("clear_history") 18 | readline.have_func("rl_redisplay") 19 | readline.have_func("rl_insert_text") 20 | + 21 | +unless readline.have_type("rl_hook_func_t") 22 | + $defs << "-Drl_hook_func_t=Function" 23 | +end 24 | + 25 | create_makefile("readline") 26 | diff --git ext/readline/readline.c ext/readline/readline.c 27 | index 3e7feea..482bf80 100644 28 | --- ext/readline/readline.c 29 | +++ ext/readline/readline.c 30 | @@ -1883,7 +1883,7 @@ Init_readline() 31 | 32 | rl_attempted_completion_function = readline_attempted_completion_function; 33 | #if defined(HAVE_RL_PRE_INPUT_HOOK) 34 | - rl_pre_input_hook = (Function *)readline_pre_input_hook; 35 | + rl_pre_input_hook = (rl_hook_func_t *)readline_pre_input_hook; 36 | #endif 37 | #ifdef HAVE_RL_CATCH_SIGNALS 38 | rl_catch_signals = 0; 39 | -------------------------------------------------------------------------------- /data/patches/2.0.0-p451/01_readline.patch: -------------------------------------------------------------------------------- 1 | diff --git ext/readline/extconf.rb ext/readline/extconf.rb 2 | index 4920137..8e81253 100644 3 | --- ext/readline/extconf.rb 4 | +++ ext/readline/extconf.rb 5 | @@ -19,6 +19,10 @@ def readline.have_func(func) 6 | return super(func, headers) 7 | end 8 | 9 | +def readline.have_type(type) 10 | + return super(type, headers) 11 | +end 12 | + 13 | dir_config('curses') 14 | dir_config('ncurses') 15 | dir_config('termcap') 16 | @@ -93,4 +97,9 @@ readline.have_func("remove_history") 17 | readline.have_func("clear_history") 18 | readline.have_func("rl_redisplay") 19 | readline.have_func("rl_insert_text") 20 | + 21 | +unless readline.have_type("rl_hook_func_t") 22 | + $defs << "-Drl_hook_func_t=Function" 23 | +end 24 | + 25 | create_makefile("readline") 26 | diff --git ext/readline/readline.c ext/readline/readline.c 27 | index 3e7feea..482bf80 100644 28 | --- ext/readline/readline.c 29 | +++ ext/readline/readline.c 30 | @@ -1883,7 +1883,7 @@ Init_readline() 31 | 32 | rl_attempted_completion_function = readline_attempted_completion_function; 33 | #if defined(HAVE_RL_PRE_INPUT_HOOK) 34 | - rl_pre_input_hook = (Function *)readline_pre_input_hook; 35 | + rl_pre_input_hook = (rl_hook_func_t *)readline_pre_input_hook; 36 | #endif 37 | #ifdef HAVE_RL_CATCH_SIGNALS 38 | rl_catch_signals = 0; 39 | -------------------------------------------------------------------------------- /data/patches/2.1.0/01_readline.patch: -------------------------------------------------------------------------------- 1 | Index: ext/readline/readline.c 2 | =================================================================== 3 | --- ext/readline/readline.c (revision 45224) 4 | +++ ext/readline/readline.c (revision 45225) 5 | @@ -1974,7 +1974,7 @@ 6 | 7 | rl_attempted_completion_function = readline_attempted_completion_function; 8 | #if defined(HAVE_RL_PRE_INPUT_HOOK) 9 | - rl_pre_input_hook = (Function *)readline_pre_input_hook; 10 | + rl_pre_input_hook = (rl_hook_func_t *)readline_pre_input_hook; 11 | #endif 12 | #ifdef HAVE_RL_CATCH_SIGNALS 13 | rl_catch_signals = 0; 14 | Index: ext/readline/extconf.rb 15 | =================================================================== 16 | --- ext/readline/extconf.rb (revision 45239) 17 | +++ ext/readline/extconf.rb (revision 45240) 18 | @@ -19,6 +19,10 @@ 19 | return super(func, headers) 20 | end 21 | 22 | +def readline.have_type(type) 23 | + return super(type, headers) 24 | +end 25 | + 26 | dir_config('curses') 27 | dir_config('ncurses') 28 | dir_config('termcap') 29 | @@ -94,4 +98,8 @@ 30 | readline.have_func("rl_redisplay") 31 | readline.have_func("rl_insert_text") 32 | readline.have_func("rl_delete_text") 33 | +unless readline.have_type("rl_hook_func_t") 34 | + $DEFS << "-Drl_hook_func_t=Function" 35 | +end 36 | + 37 | create_makefile("readline") 38 | Index: ext/readline/extconf.rb 39 | =================================================================== 40 | --- ext/readline/extconf.rb (revision 45242) 41 | +++ ext/readline/extconf.rb (revision 45243) 42 | @@ -99,6 +99,9 @@ 43 | readline.have_func("rl_insert_text") 44 | readline.have_func("rl_delete_text") 45 | unless readline.have_type("rl_hook_func_t") 46 | + # rl_hook_func_t is available since readline-4.2 (2001). 47 | + # Function is removed at readline-6.3 (2014). 48 | + # However, editline (NetBSD 6.1.3, 2014) doesn't have rl_hook_func_t. 49 | $DEFS << "-Drl_hook_func_t=Function" 50 | end -------------------------------------------------------------------------------- /data/patches/2.1.1/01_readline.patch: -------------------------------------------------------------------------------- 1 | Index: ext/readline/readline.c 2 | =================================================================== 3 | --- ext/readline/readline.c (revision 45224) 4 | +++ ext/readline/readline.c (revision 45225) 5 | @@ -1974,7 +1974,7 @@ 6 | 7 | rl_attempted_completion_function = readline_attempted_completion_function; 8 | #if defined(HAVE_RL_PRE_INPUT_HOOK) 9 | - rl_pre_input_hook = (Function *)readline_pre_input_hook; 10 | + rl_pre_input_hook = (rl_hook_func_t *)readline_pre_input_hook; 11 | #endif 12 | #ifdef HAVE_RL_CATCH_SIGNALS 13 | rl_catch_signals = 0; 14 | Index: ext/readline/extconf.rb 15 | =================================================================== 16 | --- ext/readline/extconf.rb (revision 45239) 17 | +++ ext/readline/extconf.rb (revision 45240) 18 | @@ -19,6 +19,10 @@ 19 | return super(func, headers) 20 | end 21 | 22 | +def readline.have_type(type) 23 | + return super(type, headers) 24 | +end 25 | + 26 | dir_config('curses') 27 | dir_config('ncurses') 28 | dir_config('termcap') 29 | @@ -94,4 +98,8 @@ 30 | readline.have_func("rl_redisplay") 31 | readline.have_func("rl_insert_text") 32 | readline.have_func("rl_delete_text") 33 | +unless readline.have_type("rl_hook_func_t") 34 | + $DEFS << "-Drl_hook_func_t=Function" 35 | +end 36 | + 37 | create_makefile("readline") 38 | Index: ext/readline/extconf.rb 39 | =================================================================== 40 | --- ext/readline/extconf.rb (revision 45242) 41 | +++ ext/readline/extconf.rb (revision 45243) 42 | @@ -99,6 +99,9 @@ 43 | readline.have_func("rl_insert_text") 44 | readline.have_func("rl_delete_text") 45 | unless readline.have_type("rl_hook_func_t") 46 | + # rl_hook_func_t is available since readline-4.2 (2001). 47 | + # Function is removed at readline-6.3 (2014). 48 | + # However, editline (NetBSD 6.1.3, 2014) doesn't have rl_hook_func_t. 49 | $DEFS << "-Drl_hook_func_t=Function" 50 | end --------------------------------------------------------------------------------