├── .chest ├── .babelrc ├── .eslintignore ├── .eslintrc └── .stylintrc ├── .dockerignore ├── .gitattributes ├── .gitignore ├── .node-version ├── Dockerfile ├── Godeps └── Godeps.json ├── LICENSE ├── Procfile ├── README.md ├── app.json ├── app ├── app.go ├── asset_hash.go ├── bindata.go ├── context.go ├── oauth.go ├── redis.go ├── repos.go ├── routes.go ├── session.go ├── template.go ├── utils.go ├── webhook_payload.go └── webhooks.go ├── assets └── src │ ├── actions │ ├── __tests__ │ │ └── repositories-test.js │ ├── repositories.js │ └── setRepositoryLock.js │ ├── components │ ├── App │ │ ├── components │ │ │ └── GlobalNav │ │ │ │ ├── index.js │ │ │ │ └── index.styl │ │ ├── index.js │ │ └── index.styl │ ├── Repositories │ │ ├── components │ │ │ └── ListItem │ │ │ │ ├── index.js │ │ │ │ └── index.styl │ │ ├── index.js │ │ └── index.styl │ ├── Signin │ │ ├── index.js │ │ └── index.styl │ └── Spinner │ │ ├── index.js │ │ └── index.styl │ ├── constants │ ├── ActionTypes.js │ └── apiBase.js │ ├── favicon.ico │ ├── index.js │ └── reducers │ ├── __tests__ │ └── reoositories-test.js │ ├── index.js │ └── repositories.js ├── circle.yml ├── main.go ├── package.json ├── vendor ├── github.com │ ├── eknkc │ │ └── amber │ │ │ ├── README.md │ │ │ ├── compiler.go │ │ │ ├── doc.go │ │ │ ├── parser │ │ │ ├── nodes.go │ │ │ ├── parser.go │ │ │ └── scanner.go │ │ │ └── runtime.go │ ├── garyburd │ │ └── redigo │ │ │ ├── LICENSE │ │ │ ├── internal │ │ │ └── commandinfo.go │ │ │ └── redis │ │ │ ├── conn.go │ │ │ ├── doc.go │ │ │ ├── log.go │ │ │ ├── pool.go │ │ │ ├── pubsub.go │ │ │ ├── redis.go │ │ │ ├── reply.go │ │ │ ├── scan.go │ │ │ └── script.go │ ├── google │ │ ├── go-github │ │ │ ├── LICENSE │ │ │ └── github │ │ │ │ ├── activity.go │ │ │ │ ├── activity_events.go │ │ │ │ ├── activity_notifications.go │ │ │ │ ├── activity_star.go │ │ │ │ ├── activity_watching.go │ │ │ │ ├── authorizations.go │ │ │ │ ├── doc.go │ │ │ │ ├── event_types.go │ │ │ │ ├── gists.go │ │ │ │ ├── gists_comments.go │ │ │ │ ├── git.go │ │ │ │ ├── git_blobs.go │ │ │ │ ├── git_commits.go │ │ │ │ ├── git_refs.go │ │ │ │ ├── git_tags.go │ │ │ │ ├── git_trees.go │ │ │ │ ├── github.go │ │ │ │ ├── gitignore.go │ │ │ │ ├── issues.go │ │ │ │ ├── issues_assignees.go │ │ │ │ ├── issues_comments.go │ │ │ │ ├── issues_events.go │ │ │ │ ├── issues_labels.go │ │ │ │ ├── issues_milestones.go │ │ │ │ ├── issues_timeline.go │ │ │ │ ├── licenses.go │ │ │ │ ├── messages.go │ │ │ │ ├── migrations.go │ │ │ │ ├── migrations_source_import.go │ │ │ │ ├── misc.go │ │ │ │ ├── orgs.go │ │ │ │ ├── orgs_hooks.go │ │ │ │ ├── orgs_members.go │ │ │ │ ├── orgs_teams.go │ │ │ │ ├── pulls.go │ │ │ │ ├── pulls_comments.go │ │ │ │ ├── reactions.go │ │ │ │ ├── repos.go │ │ │ │ ├── repos_collaborators.go │ │ │ │ ├── repos_comments.go │ │ │ │ ├── repos_commits.go │ │ │ │ ├── repos_contents.go │ │ │ │ ├── repos_deployments.go │ │ │ │ ├── repos_forks.go │ │ │ │ ├── repos_hooks.go │ │ │ │ ├── repos_invitations.go │ │ │ │ ├── repos_keys.go │ │ │ │ ├── repos_merging.go │ │ │ │ ├── repos_pages.go │ │ │ │ ├── repos_releases.go │ │ │ │ ├── repos_stats.go │ │ │ │ ├── repos_statuses.go │ │ │ │ ├── repos_traffic.go │ │ │ │ ├── search.go │ │ │ │ ├── strings.go │ │ │ │ ├── timestamp.go │ │ │ │ ├── users.go │ │ │ │ ├── users_administration.go │ │ │ │ ├── users_emails.go │ │ │ │ ├── users_followers.go │ │ │ │ ├── users_gpg_keys.go │ │ │ │ └── users_keys.go │ │ └── go-querystring │ │ │ ├── LICENSE │ │ │ └── query │ │ │ └── encode.go │ ├── gorilla │ │ ├── context │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── context.go │ │ │ └── doc.go │ │ ├── mux │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── context_gorilla.go │ │ │ ├── context_native.go │ │ │ ├── doc.go │ │ │ ├── mux.go │ │ │ ├── regexp.go │ │ │ └── route.go │ │ ├── securecookie │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── doc.go │ │ │ ├── fuzz.go │ │ │ └── securecookie.go │ │ └── sessions │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── doc.go │ │ │ ├── lex.go │ │ │ ├── sessions.go │ │ │ └── store.go │ ├── lestrrat │ │ └── go-apache-logformat │ │ │ ├── .gitignore │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── format.go │ │ │ ├── interface.go │ │ │ ├── logformat.go │ │ │ └── pool.go │ └── pkg │ │ └── errors │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── README.md │ │ ├── appveyor.yml │ │ ├── errors.go │ │ └── stack.go └── golang.org │ └── x │ ├── net │ ├── LICENSE │ ├── PATENTS │ └── context │ │ └── context.go │ └── oauth2 │ ├── .travis.yml │ ├── AUTHORS │ ├── CONTRIBUTING.md │ ├── CONTRIBUTORS │ ├── LICENSE │ ├── README.md │ ├── client_appengine.go │ ├── github │ └── github.go │ ├── internal │ ├── oauth2.go │ ├── token.go │ └── transport.go │ ├── oauth2.go │ ├── token.go │ └── transport.go └── webpack.config.babel.js /.chest/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "es2016", "stage-2", "react"], 3 | } 4 | -------------------------------------------------------------------------------- /.chest/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | assets/build 3 | cache 4 | -------------------------------------------------------------------------------- /.chest/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "ecmaFeatures": { 4 | "modules": true, 5 | "jsx": true 6 | }, 7 | "env": { 8 | "es6": true, 9 | "browser": true, 10 | "node": true, 11 | "jest": true 12 | }, 13 | "plugins": [ 14 | "react" 15 | ], 16 | "rules": { 17 | "block-scoped-var": 2, 18 | "comma-style": [2, "last"], 19 | "complexity": [1, 3], 20 | "curly": [2, "all"], 21 | "default-case": 2, 22 | "dot-notation": 1, 23 | "eol-last": 2, 24 | "eqeqeq": [2, "allow-null"], 25 | "guard-for-in": 1, 26 | "indent": [2, 2], 27 | "keyword-spacing": [2, { 28 | "before": true, 29 | "after": true, 30 | "overrides": { 31 | "return": { "after": true }, 32 | "throw": { "after": true }, 33 | "case": { "after": true } 34 | } 35 | }], 36 | "linebreak-style": [2, "unix"], 37 | "max-len": [2, 120, 2, { 38 | "ignoreUrls": true, 39 | "ignoreComments": false 40 | }], 41 | "no-alert": 1, 42 | "no-console": 1, 43 | "no-debugger": 1, 44 | "no-div-regex": 2, 45 | "no-else-return": 2, 46 | "no-eq-null": 2, 47 | "no-extend-native": 1, 48 | "no-extra-bind": 0, 49 | "no-extra-semi": 2, 50 | "no-floating-decimal": 2, 51 | "no-iterator": 1, 52 | "no-loop-func": 1, 53 | "no-multi-spaces": [2, {"exceptions": {"Property": true, "ImportDeclaration": true, "VariableDeclarator": true, "AssignmentExpression": true}}], 54 | "no-multi-str": 1, 55 | "no-multiple-empty-lines": [2, {"max": 1}], 56 | "no-param-reassign": [2, { "props": true }], 57 | "no-process-env": 1, 58 | "no-undef": 2, 59 | "no-var": 2, 60 | "object-curly-spacing": [2, "always"], 61 | "object-shorthand": [2, "always"], 62 | "one-var": [2, "never"], 63 | "one-var-declaration-per-line": [2, "always"], 64 | "prefer-const": 2, 65 | "quotes": [2, "single"], 66 | "semi": [2, "always"], 67 | "space-before-blocks": 2, 68 | "space-before-function-paren": [2, { "anonymous": "always", "named": "never" }], 69 | "no-proto": 2, 70 | "no-self-compare": 2, 71 | "no-throw-literal": 1, 72 | "no-trailing-spaces": [2, { "skipBlankLines": false }], 73 | "no-unused-expressions": 1, 74 | "no-unused-vars": [1, {"vars": "all", "args": "after-used"}], 75 | "radix": 1, 76 | "react/jsx-uses-vars": 2, 77 | "react/jsx-uses-react": 2, 78 | "react/no-multi-comp": 2, 79 | "react/jsx-no-undef": 2, 80 | "react/display-name": 2, 81 | "react/jsx-boolean-value": 2, 82 | "react/jsx-no-duplicate-props": 2, 83 | "jsx-quotes": [2, "prefer-single"], 84 | "react/prefer-es6-class": 2, 85 | "react/jsx-curly-spacing": 2, 86 | "react/forbid-prop-types": 2, 87 | "strict": 2, 88 | "wrap-iife": [2, "inside"], 89 | "yoda": 0, 90 | "no-dupe-keys": 2 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /.chest/.stylintrc: -------------------------------------------------------------------------------- 1 | { 2 | "reporter": "stylint-stylish", 3 | "blocks": false, 4 | "brackets": "never", 5 | "colons": "always", 6 | "colors": false, 7 | "commaSpace": "always", 8 | "commentSpace": "always", 9 | "cssLiteral": "never", 10 | "depthLimit": false, 11 | "duplicates": false, 12 | "efficient": "always", 13 | "extendPref": false, 14 | "globalDupe": false, 15 | "indentPref": false, 16 | "leadingZero": false, 17 | "maxErrors": false, 18 | "maxWarnings": false, 19 | "mixed": false, 20 | "namingConvention": false, 21 | "namingConventionStrict": false, 22 | "none": "never", 23 | "noImportant": true, 24 | "parenSpace": false, 25 | "placeholders": "always", 26 | "prefixVarsWithDollar": "always", 27 | "quotePref": "single", 28 | "semicolons": "never", 29 | "sortOrder": false, 30 | "stackedProperties": "never", 31 | "trailingWhitespace": "never", 32 | "universal": false, 33 | "valid": true, 34 | "zeroUnits": "never", 35 | "zIndexNormalize": false 36 | } 37 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | * 2 | !app 3 | !main.go 4 | !Godeps/Godeps.json 5 | !vendor 6 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | vendor/* linguist-vendored 2 | assets/* linguist-vendored 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | *.pid.lock 11 | 12 | # Directory for instrumented libs generated by jscoverage/JSCover 13 | lib-cov 14 | 15 | # Coverage directory used by tools like istanbul 16 | coverage 17 | 18 | # nyc test coverage 19 | .nyc_output 20 | 21 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 22 | .grunt 23 | 24 | # node-waf configuration 25 | .lock-wscript 26 | 27 | # Compiled binary addons (http://nodejs.org/api/addons.html) 28 | build/Release 29 | 30 | # Dependency directories 31 | node_modules 32 | jspm_packages 33 | 34 | # Optional npm cache directory 35 | .npm 36 | 37 | # Optional eslint cache 38 | .eslintcache 39 | 40 | # Optional REPL history 41 | .node_repl_history 42 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 43 | *.o 44 | *.a 45 | *.so 46 | 47 | # Folders 48 | _obj 49 | _test 50 | 51 | # Architecture specific extensions/prefixes 52 | *.[568vq] 53 | [568vq].out 54 | 55 | *.cgo1.go 56 | *.cgo2.c 57 | _cgo_defun.c 58 | _cgo_gotypes.go 59 | _cgo_export.* 60 | 61 | _testmain.go 62 | 63 | *.exe 64 | *.test 65 | *.prof 66 | 67 | # Output of the go coverage tool, specifically when used with LiteIDE 68 | *.out 69 | 70 | assets/build 71 | wiplock 72 | cache 73 | 74 | /.babelrc 75 | /.eslintignore 76 | /.eslintrc 77 | /.stylintrc 78 | /Godeps/Readme 79 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | v6.1.0 2 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.7.1 2 | MAINTAINER Atsushi Nagase 3 | 4 | ADD . /go/src/github.com/ngs/wiplock 5 | RUN go install github.com/ngs/wiplock 6 | 7 | ENTRYPOINT ["/go/bin/wiplock"] 8 | EXPOSE 8000 9 | -------------------------------------------------------------------------------- /Godeps/Godeps.json: -------------------------------------------------------------------------------- 1 | { 2 | "ImportPath": "github.com/ngs/wiplock", 3 | "GoVersion": "go1.7", 4 | "GodepVersion": "v74", 5 | "Packages": [ 6 | "./..." 7 | ], 8 | "Deps": [ 9 | { 10 | "ImportPath": "github.com/eknkc/amber", 11 | "Rev": "7875e9689d335cd15294cd6f4f0ef8322ce4c8e7" 12 | }, 13 | { 14 | "ImportPath": "github.com/eknkc/amber/parser", 15 | "Rev": "7875e9689d335cd15294cd6f4f0ef8322ce4c8e7" 16 | }, 17 | { 18 | "ImportPath": "github.com/garyburd/redigo/internal", 19 | "Comment": "v1.0.0-5-gffa8d46", 20 | "Rev": "ffa8d46ada782d81cfda81a0fbd9f45ceae448e8" 21 | }, 22 | { 23 | "ImportPath": "github.com/garyburd/redigo/redis", 24 | "Comment": "v1.0.0-5-gffa8d46", 25 | "Rev": "ffa8d46ada782d81cfda81a0fbd9f45ceae448e8" 26 | }, 27 | { 28 | "ImportPath": "github.com/google/go-github/github", 29 | "Rev": "6c0472a7690bdb983189bb16aa31512ae1928e6e" 30 | }, 31 | { 32 | "ImportPath": "github.com/google/go-querystring/query", 33 | "Rev": "9235644dd9e52eeae6fa48efd539fdc351a0af53" 34 | }, 35 | { 36 | "ImportPath": "github.com/gorilla/context", 37 | "Comment": "v1.1-7-g08b5f42", 38 | "Rev": "08b5f424b9271eedf6f9f0ce86cb9396ed337a42" 39 | }, 40 | { 41 | "ImportPath": "github.com/gorilla/mux", 42 | "Comment": "v1.1-25-g0a192a1", 43 | "Rev": "0a192a193177452756c362c20087ddafcf6829c4" 44 | }, 45 | { 46 | "ImportPath": "github.com/gorilla/securecookie", 47 | "Comment": "v1.1-4-gc13558c", 48 | "Rev": "c13558c2b1c44da35e0eb043053609a5ba3a1f19" 49 | }, 50 | { 51 | "ImportPath": "github.com/gorilla/sessions", 52 | "Rev": "7ab2742f1e374be6675e9a4eca54fe529221ae3a" 53 | }, 54 | { 55 | "ImportPath": "github.com/lestrrat/go-apache-logformat", 56 | "Comment": "v2.0.0-4-g0f5817c", 57 | "Rev": "0f5817c5c9e626d408c4d68e3d90fd7697e97d5f" 58 | }, 59 | { 60 | "ImportPath": "github.com/pkg/errors", 61 | "Comment": "v0.7.1", 62 | "Rev": "17b591df37844cde689f4d5813e5cea0927d8dd2" 63 | }, 64 | { 65 | "ImportPath": "golang.org/x/net/context", 66 | "Rev": "6d10a0c3eafbed530eb495a38c41ccdf8ebdcb4e" 67 | }, 68 | { 69 | "ImportPath": "golang.org/x/oauth2", 70 | "Rev": "ef4eca6b097fad7cec79afcc278d213a6de1c960" 71 | }, 72 | { 73 | "ImportPath": "golang.org/x/oauth2/github", 74 | "Rev": "ef4eca6b097fad7cec79afcc278d213a6de1c960" 75 | }, 76 | { 77 | "ImportPath": "golang.org/x/oauth2/internal", 78 | "Rev": "ef4eca6b097fad7cec79afcc278d213a6de1c960" 79 | }, 80 | { 81 | "ImportPath": "gopkg.in/go-playground/webhooks.v1", 82 | "Rev": "6bfbae2ae33d4c4cc08178f2d5fd77c465e16596" 83 | } 84 | ] 85 | } 86 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Atsushi NAGASE 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: wiplock 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Wiplock 2 | ======= 3 | 4 | [![CircleCI](https://circleci.com/gh/ngs/wiplock.svg?style=svg&circle-token=5420dff80ec6221981e5055999bf59705a25b696)](https://circleci.com/gh/ngs/wiplock) 5 | [![](https://img.shields.io/docker/automated/atsnngs/wiplock.svg)](https://hub.docker.com/r/atsnngs/wiplock/) 6 | 7 | Wiplock is a tiny webhook application that prevents mistakenly merging in progress pull requests 8 | 9 | https://wiplock.com 10 | 11 | ![](https://raw.githubusercontent.com/ngs/sources.ngs.io/master/source/images/2016-09-23-wiplock/screen.gif) 12 | 13 | Running 14 | ------- 15 | 16 | You need to grab your OAuth Application Client ID and Secret. 17 | 18 | https://github.com/settings/applications/new 19 | 20 | ### Heroku 21 | 22 | Just hit 23 | 24 | [![Deploy](https://www.herokucdn.com/deploy/button.png)](https://heroku.com/deploy) 25 | 26 | or 27 | 28 | ```sh 29 | git clone git://github.com/ngs/wiplock.git 30 | cd wiplock.git 31 | heroku create 32 | 33 | heroku addons:create heroku-redis:hobby-dev 34 | 35 | heroku config:set \ 36 | GITHUB_CLIENT_ID=${GITHUB_CLIENT_ID} \ 37 | GITHUB_CLIENT_SECRET=${GITHUB_CLIENT_SECRET} \ 38 | SECRET=${SECRET} 39 | 40 | git push heroku master 41 | heroku open 42 | ``` 43 | 44 | ### Docker 45 | 46 | ```sh 47 | docker pull redis 48 | docker pull atsnngs/wiplock 49 | 50 | docker run --name wiplock-redis -d redis 51 | docker run --name wiplock -p 8000:8000 -d --rm \ 52 | --link wiplock-redis:redis \ 53 | -e GITHUB_CLIENT_ID=${GITHUB_CLIENT_ID} \ 54 | -e GITHUB_CLIENT_SECRET=${GITHUB_CLIENT_SECRET} \ 55 | -e SECRET=${SECRET} \ 56 | -e REDIS_URL="redis://redis:6379" \ 57 | atsnngs/wiplock 58 | 59 | open http://localhost:8000 60 | ``` 61 | 62 | Author 63 | ====== 64 | 65 | [Atushi Nagase] 66 | 67 | License 68 | ======= 69 | 70 | Copyright © 2016 [Atushi Nagase]. All rights reserved. 71 | 72 | [Atushi Nagase]: https://ngs.io/ 73 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Wiplock", 3 | "description": "Wiplock protects mistakenly merging pull requests in progress", 4 | "keywords": [ 5 | "wip", 6 | "go", 7 | "workflow", 8 | "github", 9 | "pull requests" 10 | ], 11 | "env": { 12 | "GITHUB_CLIENT_ID": { 13 | "description": "GitHub's client ID. Grab yours from https://github.com/settings/applications/new" 14 | }, 15 | "GITHUB_CLIENT_SECRET": { 16 | "description": "GitHub's client secret." 17 | }, 18 | "SECRET": { 19 | "description": "Secret key for verifying GitHub Signed Webhook and secure sessions", 20 | "generator": "secret" 21 | } 22 | }, 23 | "addons": [ 24 | { 25 | "plan": "heroku-redis:hobby-dev" 26 | } 27 | ], 28 | "image": "heroku/go:1.7", 29 | "mount_dir": "src/github.com/ngs/wiplock", 30 | "website": "http://github.com/ngs/wiplock", 31 | "repository": "http://github.com/ngs/wiplock" 32 | } 33 | -------------------------------------------------------------------------------- /app/app.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "github.com/garyburd/redigo/redis" 7 | "github.com/gorilla/sessions" 8 | "github.com/lestrrat/go-apache-logformat" 9 | "html/template" 10 | "log" 11 | "net/http" 12 | "os" 13 | "strconv" 14 | "strings" 15 | ) 16 | 17 | type App struct { 18 | HTMLTemplate *template.Template 19 | Port int 20 | SessionStore *sessions.CookieStore 21 | AssetHash string 22 | Secret string 23 | ClientSecret string 24 | ClientID string 25 | LockStoreKey string 26 | RedisConn redis.Conn 27 | } 28 | 29 | func New() (*App, error) { 30 | app := &App{HTMLTemplate: NewTemplate()} 31 | if err := app.GetAssetHash(); err != nil { 32 | return app, err 33 | } 34 | secret := os.Getenv("SECRET") 35 | clientSecret := os.Getenv("GITHUB_CLIENT_SECRET") 36 | clientID := os.Getenv("GITHUB_CLIENT_ID") 37 | var errVars = []string{} 38 | if secret == "" { 39 | errVars = append(errVars, "SECRET") 40 | } 41 | if clientSecret == "" { 42 | errVars = append(errVars, "GITHUB_CLIENT_SECRET") 43 | } 44 | if clientID == "" { 45 | errVars = append(errVars, "GITHUB_CLIENT_ID") 46 | } 47 | if len(errVars) > 0 { 48 | return app, fmt.Errorf("%s are not configured.", strings.Join(errVars, ", ")) 49 | } 50 | if secret == "" { 51 | return app, errors.New("SECRET is not configured. try run\n$ echo \"export SECRET='$(openssl rand -hex 48)'\" >> .envrc") 52 | } 53 | if lockStoreKey := os.Getenv("LOCK_KEY"); lockStoreKey != "" { 54 | app.LockStoreKey = lockStoreKey 55 | } else { 56 | app.LockStoreKey = "wiplocks" 57 | } 58 | app.Secret = secret 59 | app.ClientID = clientID 60 | app.ClientSecret = clientSecret 61 | app.SetupSessionStore() 62 | if err := app.SetupRedis(); err != nil { 63 | return app, err 64 | } 65 | return app, nil 66 | } 67 | 68 | func Run() (*App, error) { 69 | app, err := New() 70 | if err != nil { 71 | return app, err 72 | } 73 | port, err := strconv.Atoi(os.Getenv("PORT")) 74 | if !(port > 0) { 75 | port = 8000 76 | } 77 | app.Port = port 78 | router := app.SetupRouter() 79 | log.Fatal(http.ListenAndServe(":"+strconv.Itoa(port), apachelog.CombinedLog.Wrap(router, os.Stderr))) 80 | return app, nil 81 | } 82 | 83 | func (app *App) GetJavaScriptPath() string { 84 | if os.Getenv("DEV_SERVER") == "1" { 85 | return "/assets/bundle.js" 86 | } 87 | return "/assets/bundle-" + app.AssetHash + ".js" 88 | } 89 | -------------------------------------------------------------------------------- /app/asset_hash.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "crypto/md5" 5 | "encoding/hex" 6 | ) 7 | 8 | func (app *App) GetAssetHash() error { 9 | data, err := Asset("assets/build/bundle.js") 10 | if err != nil { 11 | return err 12 | } 13 | h := md5.Sum(data) 14 | app.AssetHash = hex.EncodeToString(h[:]) 15 | return nil 16 | } 17 | -------------------------------------------------------------------------------- /app/context.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "github.com/garyburd/redigo/redis" 5 | "github.com/gorilla/sessions" 6 | "net/http" 7 | ) 8 | 9 | const SiteDescription = "A tiny app that protects mistakenly merging pull requests in progress" 10 | const SiteTitle = "Wiplock" 11 | 12 | type Context struct { 13 | AccessToken string 14 | BodyClassName string 15 | JavaScriptPath string 16 | LockStoreKey string 17 | RedisConn redis.Conn 18 | Request *http.Request 19 | Secret string 20 | Session *sessions.Session 21 | SiteDescription string 22 | SiteTitle string 23 | } 24 | 25 | func (app *App) CreateContext(r *http.Request) *Context { 26 | ctx := &Context{ 27 | JavaScriptPath: app.GetJavaScriptPath(), 28 | LockStoreKey: app.LockStoreKey, 29 | RedisConn: app.RedisConn, 30 | Request: r, 31 | Secret: app.Secret, 32 | Session: app.GetSession(r), 33 | SiteDescription: SiteDescription, 34 | SiteTitle: SiteTitle, 35 | } 36 | ctx.AccessToken = ctx.GetAccessToken() 37 | if ctx.AccessToken == "" { 38 | ctx.BodyClassName = "signin" 39 | } 40 | return ctx 41 | } 42 | 43 | func (context *Context) GetAccessToken() string { 44 | if token, ok := context.Session.Values["token"].(string); ok { 45 | return token 46 | } 47 | return "" 48 | } 49 | 50 | func (context *Context) GetHookURL() string { 51 | return "https://" + context.Request.Host + "/hooks" 52 | } 53 | 54 | func (context *Context) SetAccessToken(token string, w http.ResponseWriter) error { 55 | context.Session.Values["token"] = token 56 | return context.Session.Save(context.Request, w) 57 | } 58 | -------------------------------------------------------------------------------- /app/oauth.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "fmt" 5 | "golang.org/x/net/context" 6 | "golang.org/x/oauth2" 7 | githubEndpoint "golang.org/x/oauth2/github" 8 | "net/http" 9 | ) 10 | 11 | func (app *App) GetOAuth2Config() *oauth2.Config { 12 | return &oauth2.Config{ 13 | ClientID: app.ClientID, 14 | ClientSecret: app.ClientSecret, 15 | Endpoint: githubEndpoint.Endpoint, 16 | Scopes: []string{"repo", "admin:repo_hook", "read:org"}, 17 | } 18 | } 19 | 20 | func (app *App) GetAccessToken(code string, state string) (string, error) { 21 | config := app.GetOAuth2Config() 22 | fmt.Printf("state: %+v\n", state) 23 | ctx := context.TODO() 24 | t, err := config.Exchange(ctx, code) 25 | if err != nil { 26 | return "", err 27 | } 28 | return t.AccessToken, nil 29 | } 30 | 31 | func (context *Context) GetOAuth2Client() *http.Client { 32 | token := context.GetAccessToken() 33 | if token == "" { 34 | return nil 35 | } 36 | return GetOAuth2ClientForToken(token) 37 | } 38 | 39 | func GetOAuth2ClientForToken(token string) *http.Client { 40 | ts := oauth2.StaticTokenSource( 41 | &oauth2.Token{AccessToken: token}, 42 | ) 43 | return oauth2.NewClient(oauth2.NoContext, ts) 44 | } 45 | -------------------------------------------------------------------------------- /app/redis.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "errors" 5 | "github.com/garyburd/redigo/redis" 6 | "os" 7 | "time" 8 | ) 9 | 10 | func (app *App) ReconnectRedisIfNeeeded() { 11 | res, _ := app.RedisConn.Do("PING") 12 | if pong, ok := res.([]byte); !ok || string(pong) != "PONG" { 13 | err := app.SetupRedis() 14 | if err != nil { 15 | panic(err) 16 | } 17 | } 18 | } 19 | 20 | func (app *App) SetupRedis() error { 21 | connectTimeout := 1 * time.Second 22 | readTimeout := 1 * time.Second 23 | writeTimeout := 1 * time.Second 24 | 25 | if url := os.Getenv("REDIS_URL"); url != "" { 26 | conn, err := redis.DialURL(url, 27 | redis.DialConnectTimeout(connectTimeout), 28 | redis.DialReadTimeout(readTimeout), 29 | redis.DialWriteTimeout(writeTimeout)) 30 | if err != nil { 31 | return err 32 | } 33 | app.RedisConn = conn 34 | return nil 35 | } else { 36 | conn, err := redis.Dial("tcp", ":6379", 37 | redis.DialConnectTimeout(connectTimeout), 38 | redis.DialReadTimeout(readTimeout), 39 | redis.DialWriteTimeout(writeTimeout)) 40 | if err != nil { 41 | return err 42 | } 43 | app.RedisConn = conn 44 | return nil 45 | } 46 | return errors.New("Could not connect to Redis") 47 | } 48 | -------------------------------------------------------------------------------- /app/repos.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "encoding/json" 5 | "github.com/google/go-github/github" 6 | ) 7 | 8 | type Repository struct { 9 | ID *int `json:"id,omitempty"` 10 | Owner *github.User `json:"owner,omitempty"` 11 | Name *string `json:"name,omitempty"` 12 | HTMLURL *string `json:"html_url,omitempty"` 13 | Private *bool `json:"private"` 14 | Locked bool `json:"locked"` 15 | FullName string `json:"full_name"` 16 | } 17 | 18 | func RepositoryFromGitHub(repo *github.Repository) Repository { 19 | return Repository{ 20 | FullName: *repo.FullName, 21 | HTMLURL: repo.HTMLURL, 22 | ID: repo.ID, 23 | Locked: false, 24 | Name: repo.Name, 25 | Owner: repo.Owner, 26 | Private: repo.Private, 27 | } 28 | } 29 | 30 | func (context *Context) GetRepos() ([]Repository, error) { 31 | client := github.NewClient(context.GetOAuth2Client()) 32 | var allRepos []Repository 33 | var fullNames []string 34 | fullNames = append(fullNames, context.LockStoreKey) 35 | opt := &github.RepositoryListOptions{ 36 | ListOptions: github.ListOptions{PerPage: 100}, 37 | } 38 | for { 39 | repos, resp, err := client.Repositories.List("", opt) 40 | if err != nil { 41 | return []Repository{}, err 42 | } 43 | for _, repo := range repos { 44 | if (*repo.Permissions)["admin"] == true { 45 | allRepos = append(allRepos, RepositoryFromGitHub(repo)) 46 | fullNames = append(fullNames, *repo.FullName) 47 | } 48 | } 49 | if resp.NextPage == 0 { 50 | break 51 | } 52 | opt.ListOptions.Page = resp.NextPage 53 | } 54 | hmgetArgs := make([]interface{}, len(fullNames)) 55 | for i, v := range fullNames { 56 | hmgetArgs[i] = v 57 | } 58 | res, err := context.RedisConn.Do("HMGET", hmgetArgs...) 59 | if err != nil { 60 | return allRepos, err 61 | } 62 | for i, v := range res.([]interface{}) { 63 | allRepos[i].Locked = v != nil 64 | } 65 | return allRepos, nil 66 | } 67 | 68 | func (context *Context) GetReposJson() ([]byte, error) { 69 | repos, err := context.GetRepos() 70 | if err != nil { 71 | return []byte{}, err 72 | } 73 | return json.Marshal(repos) 74 | } 75 | 76 | func (context *Context) LockRepo(org string, repo string) error { 77 | fullName := org + "/" + repo 78 | hookURL := context.GetHookURL() 79 | client := github.NewClient(context.GetOAuth2Client()) 80 | active := true 81 | name := "web" 82 | _, res, err := client.Repositories.CreateHook(org, repo, &github.Hook{ 83 | Name: &name, 84 | Events: []string{"pull_request"}, 85 | Active: &active, 86 | // https://developer.github.com/v3/repos/hooks/ 87 | Config: map[string]interface{}{ 88 | "url": hookURL, 89 | "content_type": "json", 90 | "secret": context.Secret, 91 | }, 92 | }) 93 | if err != nil && res.StatusCode != 422 { 94 | return err 95 | } 96 | conn := context.RedisConn 97 | token := context.GetAccessToken() 98 | if _, err := conn.Do("HSET", context.LockStoreKey, fullName, token); err != nil { 99 | return err 100 | } 101 | if err := conn.Flush(); err != nil { 102 | return err 103 | } 104 | return nil 105 | } 106 | 107 | func (context *Context) UnlockRepo(org string, repo string) error { 108 | fullName := org + "/" + repo 109 | hookURL := context.GetHookURL() 110 | client := github.NewClient(context.GetOAuth2Client()) 111 | opt := &github.ListOptions{PerPage: 100} 112 | for { 113 | hooks, resp, err := client.Repositories.ListHooks(org, repo, opt) 114 | if err != nil { 115 | return err 116 | } 117 | for _, hook := range hooks { 118 | if hook.Config["url"] == hookURL { 119 | if _, err = client.Repositories.DeleteHook(org, repo, *hook.ID); err != nil { 120 | return err 121 | } 122 | } 123 | } 124 | if resp.NextPage == 0 { 125 | break 126 | } 127 | opt.Page = resp.NextPage 128 | } 129 | 130 | conn := context.RedisConn 131 | if _, err := conn.Do("HDEL", context.LockStoreKey, fullName); err != nil { 132 | return err 133 | } 134 | if err := conn.Flush(); err != nil { 135 | return err 136 | } 137 | return nil 138 | } 139 | -------------------------------------------------------------------------------- /app/session.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "github.com/gorilla/sessions" 5 | "net/http" 6 | ) 7 | 8 | func (app *App) SetupSessionStore() { 9 | store := sessions.NewCookieStore([]byte(app.Secret)) 10 | app.SessionStore = store 11 | } 12 | 13 | func (app *App) GetSession(r *http.Request) *sessions.Session { 14 | session, _ := app.SessionStore.Get(r, "__wlsess") 15 | return session 16 | } 17 | -------------------------------------------------------------------------------- /app/template.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "github.com/eknkc/amber" 5 | "html/template" 6 | ) 7 | 8 | func NewTemplate() *template.Template { 9 | return amber.MustCompile(`!!! 5 10 | html 11 | head 12 | title #{SiteTitle} 13 | meta[name="description"][content=SiteDescription] 14 | meta[content="width=device-width, initial-scale=1, maximum-scale=1"][name="viewport"] 15 | link[href="https://fonts.googleapis.com/css?family=Raleway"][rel="stylesheet"] 16 | body[class=BodyClassName] 17 | div#app-root[data-access-token=AccessToken] 18 | script[src=JavaScriptPath] 19 | `, amber.Options{PrettyPrint: false}) 20 | } 21 | -------------------------------------------------------------------------------- /app/utils.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "crypto/rand" 5 | "encoding/binary" 6 | "strconv" 7 | ) 8 | 9 | func RandomString(len int) string { 10 | var n uint64 11 | binary.Read(rand.Reader, binary.LittleEndian, &n) 12 | return strconv.FormatUint(n, len) 13 | } 14 | -------------------------------------------------------------------------------- /app/webhook_payload.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | // PullRequestPayload contains the information for GitHub's pull_request hook event 4 | type PullRequestPayload struct { 5 | PullRequest PullRequest `json:"pull_request"` 6 | Repository Repository `json:"repository"` 7 | } 8 | 9 | // PullRequest contains GitHub's pull_request information 10 | type PullRequest struct { 11 | ID int `json:"id"` 12 | Title string `json:"title"` 13 | Body string `json:"body"` 14 | Head Head `json:"head"` 15 | } 16 | 17 | // Head contains GitHub's head information 18 | type Head struct { 19 | Label string `json:"label"` 20 | Ref string `json:"ref"` 21 | SHA string `json:"sha"` 22 | User User `json:"user"` 23 | Repo Repository `json:"repo"` 24 | } 25 | 26 | // User contains GitHub's user information 27 | type User struct { 28 | Login string `json:"login"` 29 | } 30 | 31 | // Owner contains GitHub's owner information 32 | type Owner struct { 33 | User 34 | } 35 | -------------------------------------------------------------------------------- /app/webhooks.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "fmt" 5 | "github.com/google/go-github/github" 6 | "regexp" 7 | ) 8 | 9 | func (app *App) HandlePullRequest(payload PullRequestPayload) error { 10 | app.ReconnectRedisIfNeeeded() 11 | pr := payload.PullRequest 12 | repo := payload.Repository 13 | title := pr.Title 14 | body := pr.Body 15 | sha := pr.Head.SHA 16 | org := *repo.Owner.Login 17 | name := *repo.Name 18 | fullName := repo.FullName 19 | res, err := app.RedisConn.Do("HGET", app.LockStoreKey, fullName) 20 | if err != nil { 21 | fmt.Println(err) 22 | return err 23 | } 24 | tokenBytes, ok := res.([]byte) 25 | if !ok { 26 | return fmt.Errorf("Token not found for %v", fullName) 27 | } 28 | token := string(tokenBytes) 29 | client := github.NewClient(GetOAuth2ClientForToken(token)) 30 | targetURL := "https://wiplock.com/?q=" + name 31 | description := "This pull request" 32 | context := "wiplock" 33 | var state string 34 | containsWIP := regexp.MustCompile("(?i)wip").MatchString(title) 35 | containsUnchecked := regexp.MustCompile("\\n\\-\\s+\\[\\s+\\]([^\\n]+)").MatchString(body) 36 | if containsWIP || containsUnchecked { 37 | state = "pending" 38 | } else { 39 | state = "success" 40 | } 41 | if containsWIP { 42 | description = description + " contains WIP in the title" 43 | } 44 | if containsUnchecked { 45 | if containsWIP { 46 | description = description + " and" 47 | } 48 | description = description + " has unchecked checkboxes" 49 | } 50 | status := &github.RepoStatus{ 51 | TargetURL: &targetURL, 52 | Description: &description, 53 | Context: &context, 54 | State: &state, 55 | } 56 | if _, _, err := client.Repositories.CreateStatus(org, name, sha, status); err != nil { 57 | fmt.Println(err) 58 | return err 59 | } 60 | return nil 61 | } 62 | -------------------------------------------------------------------------------- /assets/src/actions/__tests__/repositories-test.js: -------------------------------------------------------------------------------- 1 | import configureMockStore from 'redux-mock-store'; 2 | import thunk from 'redux-thunk'; 3 | import { fetchRepositoriesIfNeeded } from '../repositories'; 4 | import ActionTypes from '../../constants/ActionTypes'; 5 | import nock from 'nock'; 6 | 7 | const middlewares = [thunk]; 8 | const mockStore = configureMockStore(middlewares); 9 | 10 | describe('repositories actions', () => { 11 | beforeEach(() => { 12 | nock.disableNetConnect(); 13 | nock('http://0.0.0.0:8000') 14 | .get('/api/repos') 15 | .query(true) 16 | .reply(200, [{ id: 1 }, { id: 2 }, { id: 3 }]) 17 | ; 18 | }); 19 | afterEach(() => nock.cleanAll()); 20 | 21 | it('creates FETCH_REPOSITORIES_SUCCESS when fetching todos has been done', () => { 22 | const expectedActions = [ 23 | { type: ActionTypes.FETCH_REPOSITORIES_REQUEST }, 24 | { type: ActionTypes.FETCH_REPOSITORIES_SUCCESS, items: [{ id: 1 }, { id: 2 }, { id: 3 }] } 25 | ]; 26 | const store = mockStore({ repositories: {} }); 27 | return store.dispatch(fetchRepositoriesIfNeeded()) 28 | .then(() => { 29 | expect(store.getActions()).toEqual(expectedActions); 30 | }); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /assets/src/actions/repositories.js: -------------------------------------------------------------------------------- 1 | import ActionTypes from '../constants/ActionTypes'; 2 | import apiBase from '../constants/apiBase'; 3 | import fetch from 'isomorphic-fetch'; 4 | 5 | function fetchRepositoriesRequest() { 6 | return { 7 | type: ActionTypes.FETCH_REPOSITORIES_REQUEST 8 | }; 9 | } 10 | 11 | function fetchRepositoriesSuccess(items) { 12 | return { 13 | type: ActionTypes.FETCH_REPOSITORIES_SUCCESS, 14 | items 15 | }; 16 | } 17 | 18 | function fetchRepositoriesFailure(error) { 19 | return { 20 | type: ActionTypes.FETCH_REPOSITORIES_FAILURE, 21 | error 22 | }; 23 | } 24 | 25 | const fetchRepositories = () => dispatch => { 26 | dispatch(fetchRepositoriesRequest()); 27 | return fetch(`${apiBase}/repos`, { credentials: 'include' }) 28 | .then(res => res.json()) 29 | .then(json => dispatch(fetchRepositoriesSuccess(json))) 30 | .catch(error => { 31 | return dispatch(fetchRepositoriesFailure(error)); 32 | }) 33 | ; 34 | }; 35 | 36 | const shouldFetchRepositories = (state) => { // eslint-disable-line complexity 37 | const { repositories } = state; 38 | if (!repositories || !repositories.items || !repositories.items.length) { 39 | return true; 40 | } 41 | if (repositories.isFetching) { 42 | return false; 43 | } 44 | return repositories.didInvalidate; 45 | }; 46 | 47 | export const fetchRepositoriesIfNeeded = () => (dispatch, getState) => { 48 | if (shouldFetchRepositories(getState())) { 49 | return dispatch(fetchRepositories()); 50 | } 51 | }; 52 | -------------------------------------------------------------------------------- /assets/src/actions/setRepositoryLock.js: -------------------------------------------------------------------------------- 1 | import ActionTypes from '../constants/ActionTypes'; 2 | import apiBase from '../constants/apiBase'; 3 | import fetch from 'isomorphic-fetch'; 4 | 5 | const lockRepositoryRequest = (id) => { 6 | return { 7 | type: ActionTypes.LOCK_REPOSITORY_REQUEST, 8 | id 9 | }; 10 | }; 11 | 12 | const unlockRepositoryRequest = (id) => { 13 | return { 14 | type: ActionTypes.UNLOCK_REPOSITORY_REQUEST, 15 | id 16 | }; 17 | }; 18 | 19 | const lockRepositorySuccess = (id) => { 20 | return { 21 | type: ActionTypes.LOCK_REPOSITORY_SUCCESS, 22 | id 23 | }; 24 | }; 25 | 26 | const unlockRepositorySuccess = (id) => { 27 | return { 28 | type: ActionTypes.UNLOCK_REPOSITORY_SUCCESS, 29 | id 30 | }; 31 | }; 32 | 33 | const lockRepositoryFailure = (id, error) => { 34 | return { 35 | type: ActionTypes.LOCK_REPOSITORY_FAILURE, 36 | id, 37 | error 38 | }; 39 | }; 40 | 41 | const unlockRepositoryFailure = (id, error) => { 42 | return { 43 | type: ActionTypes.UNLOCK_REPOSITORY_FAILURE, 44 | id, 45 | error 46 | }; 47 | }; 48 | 49 | const requestRepositoryLock = (repo, locked) => dispatch => { 50 | const { id, owner: { login }, name } = repo; 51 | const slug = `${login}/${name}`; 52 | const url = `${apiBase}/${slug}/lock`; 53 | const request = (method, start, success, fail) => { 54 | dispatch(start(id)); 55 | fetch(url, { method, credentials: 'include' }) 56 | .then(res => { 57 | if (!res.ok) { 58 | throw new Error(res.statusText); 59 | } 60 | }) 61 | .then(() => dispatch(success(id))) 62 | .catch(error => dispatch(fail(id, error))); 63 | }; 64 | if (locked) { 65 | request('PUT', 66 | lockRepositoryRequest, 67 | lockRepositorySuccess, 68 | lockRepositoryFailure); 69 | } else { 70 | request('DELETE', 71 | unlockRepositoryRequest, 72 | unlockRepositorySuccess, 73 | unlockRepositoryFailure); 74 | } 75 | }; 76 | 77 | export const setRepositoryLock = (id, locked) => (dispatch, getState) => { 78 | const { repositories: { items } } = getState(); 79 | const repo = items.filter(repo => repo.id === id)[0]; 80 | if (repo) { 81 | return dispatch(requestRepositoryLock(repo, locked)); 82 | } 83 | }; 84 | -------------------------------------------------------------------------------- /assets/src/components/App/components/GlobalNav/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Navbar, Nav, NavItem } from 'react-bootstrap'; 3 | 4 | import './index.styl'; 5 | 6 | export default class GlobalNav extends Component { 7 | render() { 8 | return ( 9 | 10 | 11 | 12 | Wiplock 13 | 14 | 15 | 16 | 17 | 22 | 23 | 24 | ); 25 | } 26 | } 27 | 28 | GlobalNav.displayName = 'GlobalNav'; 29 | 30 | -------------------------------------------------------------------------------- /assets/src/components/App/components/GlobalNav/index.styl: -------------------------------------------------------------------------------- 1 | @import 'bootstrap/variables' 2 | 3 | #global-nav 4 | a 5 | color: $text-color 6 | &:hover 7 | color: lighten($text-color, 30) 8 | .navbar-toggle 9 | &:hover 10 | background-color: darken($body-bg, 10) 11 | .icon-bar 12 | background-color: $text-color 13 | -------------------------------------------------------------------------------- /assets/src/components/App/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import GlobalNav from './components/GlobalNav'; 3 | import './index.styl'; 4 | 5 | export default class App extends Component { 6 | render() { 7 | return ( 8 |
9 | 10 |
11 | {this.props.children} 12 |
13 |
14 | ); 15 | } 16 | } 17 | 18 | App.displayName = 'App'; 19 | -------------------------------------------------------------------------------- /assets/src/components/App/index.styl: -------------------------------------------------------------------------------- 1 | $font-family-sans-serif = Raleway, 'Helvetica Neue', Helvetica, Arial, sans-serif 2 | $brand-primary = #abc47e 3 | $breadcrumb-bg = #fff 4 | $body-bg = #f3f3f3 5 | $icon-font-path = '../../../../node_modules/bootstrap-styl/fonts/' 6 | @import bootstrap 7 | -------------------------------------------------------------------------------- /assets/src/components/Repositories/components/ListItem/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component, PropTypes } from 'react'; 2 | import { ListGroupItem, Image, Media } from 'react-bootstrap'; 3 | import Switch from 'react-bootstrap-switch'; 4 | import Icon from 'react-fa'; 5 | import { connect } from 'react-redux'; 6 | import { setRepositoryLock } from '../../../../actions/setRepositoryLock'; 7 | import './index.styl'; 8 | import '../../../../../../node_modules/react-bootstrap-switch/dist/css/bootstrap3/react-bootstrap-switch.css'; 9 | 10 | class ListItem extends Component { 11 | 12 | render() { // eslint-disable-line complexity 13 | const { item, filterText, dispatch } = this.props; 14 | let { login } = item.owner; 15 | let { name } = item; 16 | const { html_url, private: isPrivate, locked, isUpdatingLock, id } = item; 17 | if (filterText) { 18 | login = login.replace(filterText, '$1'); 19 | name = name.replace(filterText, '$1'); 20 | } 21 | return ( 22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | dispatch(setRepositoryLock(id, locked))} /> 32 |
33 | 34 | 35 | 36 | {isPrivate ? : null} 37 | 38 |
39 |
40 |
41 | ); 42 | } 43 | } 44 | 45 | ListItem.displayName = 'Organizations.ListItem'; 46 | 47 | ListItem.propTypes = { 48 | filterText: PropTypes.instanceOf(RegExp), 49 | dispatch: PropTypes.func.isRequired, 50 | repoId: PropTypes.number.isRequired, 51 | item: PropTypes.shape({ 52 | id: PropTypes.number.isRequired, 53 | name: PropTypes.string.isRequired, 54 | private: PropTypes.bool.isRequired, 55 | locked: PropTypes.bool, 56 | isUpdatingLock: PropTypes.lock, 57 | lockError: PropTypes.instanceOf(Error), 58 | owner: PropTypes.shape({ 59 | login: PropTypes.string.isRequired, 60 | avatar_url: PropTypes.string.isRequired 61 | }).isRequired 62 | }) 63 | }; 64 | 65 | const mapStateToProps = (state, ownProps) => { // eslint-disable-line complexity 66 | const { repoId } = ownProps; 67 | const { repositories: currentItems } = state; 68 | const { items } = currentItems || { 69 | isFetching: true, 70 | items: [] 71 | }; 72 | const item = items.filter(item => item.id === repoId)[0]; 73 | return { item }; 74 | }; 75 | 76 | export default connect(mapStateToProps)(ListItem); 77 | -------------------------------------------------------------------------------- /assets/src/components/Repositories/components/ListItem/index.styl: -------------------------------------------------------------------------------- 1 | @import 'bootstrap/variables' 2 | 3 | $size = 32px 4 | 5 | .repository-list-item 6 | .media-left img 7 | width: $size 8 | height: $size 9 | .media-body 10 | .title 11 | height: $size 12 | display: flex 13 | align-items: center 14 | &, &:hover, &:focus 15 | text-decoration: none 16 | color: $text-color 17 | .owner 18 | color: lighten($text-color, 60) 19 | .name 20 | font-size: 1.2em 21 | .match 22 | background: #ffff99 23 | .fa-lock 24 | margin-left: .5em 25 | opacity: .3 26 | .bootstrap-switch.bootstrap-switch-normal .bootstrap-switch-handle-on 27 | font-family: 'FontAwesome' 28 | 29 | -------------------------------------------------------------------------------- /assets/src/components/Repositories/index.styl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngs/wiplock/977da3d11d07c6e4226499d7afca98b7b116b1b6/assets/src/components/Repositories/index.styl -------------------------------------------------------------------------------- /assets/src/components/Signin/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import Icon from 'react-fa'; 3 | import './index.styl'; 4 | import { Button } from 'react-bootstrap'; 5 | 6 | export default class Siginin extends Component { 7 | render() { 8 | return ( 9 |
10 |
11 |

Wiplock

12 |

13 | 18 |

19 |

20 | What's this? 21 |

22 |
23 |
24 | ); 25 | } 26 | } 27 | 28 | Siginin.displayName = 'Siginin'; 29 | -------------------------------------------------------------------------------- /assets/src/components/Signin/index.styl: -------------------------------------------------------------------------------- 1 | @import 'bootstrap/mixins' 2 | 3 | #signin 4 | 5 | min-height: 80% 6 | min-height: 80vh 7 | display: flex 8 | align-items: center 9 | 10 | h1 11 | font-size: 4em 12 | margin-bottom: .7em 13 | 14 | .btn-default 15 | button-variant(#fff, #333, #ccc) 16 | .fa-github 17 | font-size: 1.6em 18 | display: inline-block 19 | position: relative 20 | top: .1em 21 | 22 | html .btn-default 23 | &:hover, &:focus 24 | color: #eee 25 | 26 | -------------------------------------------------------------------------------- /assets/src/components/Spinner/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import Icon from 'react-fa'; 3 | import './index.styl'; 4 | 5 | export default class Spinner extends Component { 6 | 7 | render() { 8 | return ( 9 |
10 | 11 |
12 | ); 13 | } 14 | } 15 | 16 | Spinner.displayName = 'Spinner'; 17 | 18 | -------------------------------------------------------------------------------- /assets/src/components/Spinner/index.styl: -------------------------------------------------------------------------------- 1 | @import 'bootstrap/variables' 2 | 3 | .spinner 4 | width: 100% 5 | min-height: 50% 6 | min-height: 50vh 7 | display: flex 8 | align-items: center 9 | text-align: center 10 | .fa 11 | margin: 0 auto 12 | color: lighten($text-color, 60) 13 | font-size: 45px 14 | -------------------------------------------------------------------------------- /assets/src/constants/ActionTypes.js: -------------------------------------------------------------------------------- 1 | import keyMirror from 'keymirror'; 2 | 3 | const ActionTypes = keyMirror({ 4 | SELECT_ORGANIZATION: null, 5 | FETCH_REPOSITORIES_REQUEST: null, 6 | FETCH_REPOSITORIES_SUCCESS: null, 7 | FETCH_REPOSITORIES_FAILURE: null, 8 | LOCK_REPOSITORY_REQUEST: null, 9 | LOCK_REPOSITORY_SUCCESS: null, 10 | LOCK_REPOSITORY_FAILURE: null, 11 | UNLOCK_REPOSITORY_REQUEST: null, 12 | UNLOCK_REPOSITORY_SUCCESS: null, 13 | UNLOCK_REPOSITORY_FAILURE: null 14 | }); 15 | 16 | export default ActionTypes; 17 | -------------------------------------------------------------------------------- /assets/src/constants/apiBase.js: -------------------------------------------------------------------------------- 1 | const { protocol } = document.location; 2 | let apiBase = ''; 3 | 4 | if (!/^http/.test(protocol)) { 5 | apiBase = 'http://0.0.0.0:8000/api'; 6 | } else { 7 | apiBase = '/api'; 8 | } 9 | 10 | export default apiBase; 11 | -------------------------------------------------------------------------------- /assets/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngs/wiplock/977da3d11d07c6e4226499d7afca98b7b116b1b6/assets/src/favicon.ico -------------------------------------------------------------------------------- /assets/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from 'react-dom'; 3 | import { Provider } from 'react-redux'; 4 | import reducers from './reducers'; 5 | import createLogger from 'redux-logger'; 6 | import thunk from 'redux-thunk'; 7 | import { createStore, applyMiddleware } from 'redux'; 8 | 9 | import App from './components/App'; 10 | import Repositories from './components/Repositories'; 11 | import Signin from './components/Signin'; 12 | 13 | const element = document.getElementById('app-root'); 14 | const accessToken = element.getAttribute('data-access-token'); 15 | 16 | const middleware = [thunk]; 17 | if (process.env.NODE_ENV !== 'production') { // eslint-disable-line no-process-env 18 | middleware.push(createLogger()); 19 | } 20 | const store = createStore(reducers, applyMiddleware(...middleware)); 21 | 22 | if (!accessToken) { 23 | render(, element); 24 | } else { 25 | render( 26 | 27 | 28 | 29 | 30 | 31 | , element); 32 | } 33 | -------------------------------------------------------------------------------- /assets/src/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import repositories from './repositories'; 3 | 4 | export default combineReducers({ 5 | repositories 6 | }); 7 | -------------------------------------------------------------------------------- /assets/src/reducers/repositories.js: -------------------------------------------------------------------------------- 1 | import ActionTypes from '../constants/ActionTypes'; 2 | 3 | const getInitialState = () => ({ 4 | isFetching: false, 5 | items: [], 6 | didInvalidate: false, 7 | error: null 8 | }); 9 | 10 | export default function repositories(state = getInitialState(), action) { // eslint-disable-line complexity 11 | switch (action.type) { 12 | case ActionTypes.FETCH_REPOSITORIES_REQUEST: 13 | return { 14 | ...state, 15 | error: null, 16 | isFetching: true 17 | }; 18 | case ActionTypes.FETCH_REPOSITORIES_SUCCESS: 19 | return { 20 | ...state, 21 | items: action.items, 22 | isFetching: false 23 | }; 24 | case ActionTypes.FETCH_REPOSITORIES_FAILURE: 25 | const { error } = action; 26 | return { 27 | ...state, 28 | error 29 | }; 30 | case ActionTypes.LOCK_REPOSITORY_REQUEST: 31 | case ActionTypes.UNLOCK_REPOSITORY_REQUEST: 32 | return { 33 | ...state, 34 | items: state.items.map(item => { 35 | if (item.id === action.id) { 36 | return { 37 | ...item, 38 | isUpdatingLock: true, 39 | locked: /^LOCK/.test(action.type), 40 | lockError: null 41 | }; 42 | } 43 | return item; 44 | }) 45 | }; 46 | case ActionTypes.LOCK_REPOSITORY_FAILURE: 47 | case ActionTypes.UNLOCK_REPOSITORY_FAILURE: 48 | return { 49 | ...state, 50 | items: state.items.map(item => { 51 | if (item.id === action.id) { 52 | return { 53 | ...item, 54 | isUpdatingLock: false, 55 | locked: !/^LOCK/.test(action.type), 56 | lockError: action.error 57 | }; 58 | } 59 | return item; 60 | }) 61 | }; 62 | case ActionTypes.LOCK_REPOSITORY_SUCCESS: 63 | case ActionTypes.UNLOCK_REPOSITORY_SUCCESS: 64 | return { 65 | ...state, 66 | items: state.items.map(item => { 67 | if (item.id === action.id) { 68 | return { 69 | ...item, 70 | isUpdatingLock: false, 71 | locked: /^LOCK/.test(action.type), 72 | lockError: null 73 | }; 74 | } 75 | return item; 76 | }) 77 | }; 78 | default: 79 | return state; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | machine: 2 | timezone: UTC 3 | node: 4 | version: 6.1.0 5 | general: 6 | artifacts: 7 | - wiplock 8 | deployment: 9 | staging: 10 | branch: master 11 | heroku: 12 | appname: wiplock 13 | 14 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/ngs/wiplock/app" 5 | ) 6 | 7 | func main() { 8 | if _, err := app.Run(); err != nil { 9 | panic(err) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wiplock", 3 | "private": true, 4 | "version": "0.0.1", 5 | "description": "Wiplock protects mistakenly merging pull requests in progress", 6 | "main": "assets/src/index.js", 7 | "scripts": { 8 | "webpack": "webpack", 9 | "cp:favicon": "mkdir -p assets/build && cat assets/src/favicon.ico > assets/build/favicon.ico", 10 | "build": "NODE_ENV=production npm run webpack && npm run cp:favicon && npm run go:bindata && npm run go:build", 11 | "eslint": "eslint .", 12 | "go:bindata": "go-bindata -pkg app -o ./app/bindata.go assets/build", 13 | "go:build": "go build -v", 14 | "go:deps": "go get -u github.com/jteeuwen/go-bindata/... && go get github.com/tools/godep && godep restore -v", 15 | "go:deps:save": "godep save ./...", 16 | "go:test": "go test -v ./... | sed '/PASS/s//$$(printf \"\\033[32mPASS\\033[0m\")/' | sed '/FAIL/s//$$(printf \"\\033[31mFAIL\\033[0m\")/'", 17 | "lint": "npm run eslint && npm run stylint", 18 | "postinstall": "npm run chest:open && npm run go:deps", 19 | "chest:open": "/bin/bash -c '[[ -f ./node_modules/.bin/chest ]] && ./node_modules/.bin/chest open' || :", 20 | "chest:close": "/bin/bash -c '[[ -f ./node_modules/.bin/chest ]] && ./node_modules/.bin/chest close' || :", 21 | "start": "webpack-dev-server", 22 | "go:start": "npm run go:build && ./wiplock", 23 | "stylint": "stylint .", 24 | "test": "jest", 25 | "test:watch": "jest --watch" 26 | }, 27 | "repository": { 28 | "type": "git", 29 | "url": "git+https://github.com/ngs/wiplock.git" 30 | }, 31 | "keywords": [ 32 | "github", 33 | "wip", 34 | "pull", 35 | "request", 36 | "workflow" 37 | ], 38 | "author": "Atsushi Nagase", 39 | "license": "MIT", 40 | "bugs": { 41 | "url": "https://github.com/ngs/wiplock/issues" 42 | }, 43 | "homepage": "https://github.com/ngs/wiplock#readme", 44 | "devDependencies": { 45 | "autoprefixer": "^6.4.1", 46 | "babel-cli": "^6.14.0", 47 | "babel-core": "^6.14.0", 48 | "babel-eslint": "^6.1.2", 49 | "babel-jest": "^15.0.0", 50 | "babel-loader": "^6.2.5", 51 | "babel-polyfill": "^6.13.0", 52 | "babel-preset-es2015": "^6.14.0", 53 | "babel-preset-es2016": "^6.11.3", 54 | "babel-preset-react": "^6.11.1", 55 | "babel-preset-stage-2": "^6.13.0", 56 | "bootstrap-styl": "^5.0.7", 57 | "chest": "^1.2.3", 58 | "classnames": "^2.2.5", 59 | "css-loader": "^0.25.0", 60 | "css-mqpacker": "^5.0.1", 61 | "escape-string-regexp": "^1.0.5", 62 | "eslint": "^3.5.0", 63 | "eslint-loader": "^1.5.0", 64 | "eslint-plugin-react": "^6.2.2", 65 | "event-emitter": "^0.3.4", 66 | "file-loader": "^0.9.0", 67 | "history": "^4.2.0", 68 | "isomorphic-fetch": "^2.2.1", 69 | "jest-cli": "^15.1.1", 70 | "keymirror": "^0.1.1", 71 | "nib": "^1.1.2", 72 | "nock": "^8.0.0", 73 | "postcss-flexboxfixer": "0.0.5", 74 | "postcss-loader": "^0.13.0", 75 | "react": "^15.3.1", 76 | "react-bootstrap": "^0.30.3", 77 | "react-bootstrap-switch": "^15.0.0", 78 | "react-dom": "^15.3.1", 79 | "react-fa": "^4.1.2", 80 | "react-redux": "^4.4.5", 81 | "redux-devtools": "^3.3.1", 82 | "redux-logger": "^2.6.1", 83 | "redux-mock-store": "^1.2.0", 84 | "redux-thunk": "^2.1.0", 85 | "style-loader": "^0.13.1", 86 | "stylint": "^1.5.6", 87 | "stylint-loader": "^1.0.0", 88 | "stylint-stylish": "^1.3.2", 89 | "stylus-loader": "^2.3.1", 90 | "url-loader": "^0.5.7", 91 | "webpack": "^1.13.2", 92 | "webpack-dev-server": "^1.15.2" 93 | }, 94 | "jest": { 95 | "testPathDirs": [ 96 | "/assets/src" 97 | ], 98 | "cacheDirectory": "/cache/haste", 99 | "moduleNameMapper": { 100 | "^.+\\.(css|less|styl|sass|svg|png|mp3)$": null 101 | }, 102 | "testRegex": "/__tests__/.+-test\\.js$", 103 | "verbose": true 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /vendor/github.com/garyburd/redigo/internal/commandinfo.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Gary Burd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package internal 16 | 17 | import ( 18 | "strings" 19 | ) 20 | 21 | const ( 22 | WatchState = 1 << iota 23 | MultiState 24 | SubscribeState 25 | MonitorState 26 | ) 27 | 28 | type CommandInfo struct { 29 | Set, Clear int 30 | } 31 | 32 | var commandInfos = map[string]CommandInfo{ 33 | "WATCH": {Set: WatchState}, 34 | "UNWATCH": {Clear: WatchState}, 35 | "MULTI": {Set: MultiState}, 36 | "EXEC": {Clear: WatchState | MultiState}, 37 | "DISCARD": {Clear: WatchState | MultiState}, 38 | "PSUBSCRIBE": {Set: SubscribeState}, 39 | "SUBSCRIBE": {Set: SubscribeState}, 40 | "MONITOR": {Set: MonitorState}, 41 | } 42 | 43 | func init() { 44 | for n, ci := range commandInfos { 45 | commandInfos[strings.ToLower(n)] = ci 46 | } 47 | } 48 | 49 | func LookupCommandInfo(commandName string) CommandInfo { 50 | if ci, ok := commandInfos[commandName]; ok { 51 | return ci 52 | } 53 | return commandInfos[strings.ToUpper(commandName)] 54 | } 55 | -------------------------------------------------------------------------------- /vendor/github.com/garyburd/redigo/redis/log.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Gary Burd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package redis 16 | 17 | import ( 18 | "bytes" 19 | "fmt" 20 | "log" 21 | ) 22 | 23 | // NewLoggingConn returns a logging wrapper around a connection. 24 | func NewLoggingConn(conn Conn, logger *log.Logger, prefix string) Conn { 25 | if prefix != "" { 26 | prefix = prefix + "." 27 | } 28 | return &loggingConn{conn, logger, prefix} 29 | } 30 | 31 | type loggingConn struct { 32 | Conn 33 | logger *log.Logger 34 | prefix string 35 | } 36 | 37 | func (c *loggingConn) Close() error { 38 | err := c.Conn.Close() 39 | var buf bytes.Buffer 40 | fmt.Fprintf(&buf, "%sClose() -> (%v)", c.prefix, err) 41 | c.logger.Output(2, buf.String()) 42 | return err 43 | } 44 | 45 | func (c *loggingConn) printValue(buf *bytes.Buffer, v interface{}) { 46 | const chop = 32 47 | switch v := v.(type) { 48 | case []byte: 49 | if len(v) > chop { 50 | fmt.Fprintf(buf, "%q...", v[:chop]) 51 | } else { 52 | fmt.Fprintf(buf, "%q", v) 53 | } 54 | case string: 55 | if len(v) > chop { 56 | fmt.Fprintf(buf, "%q...", v[:chop]) 57 | } else { 58 | fmt.Fprintf(buf, "%q", v) 59 | } 60 | case []interface{}: 61 | if len(v) == 0 { 62 | buf.WriteString("[]") 63 | } else { 64 | sep := "[" 65 | fin := "]" 66 | if len(v) > chop { 67 | v = v[:chop] 68 | fin = "...]" 69 | } 70 | for _, vv := range v { 71 | buf.WriteString(sep) 72 | c.printValue(buf, vv) 73 | sep = ", " 74 | } 75 | buf.WriteString(fin) 76 | } 77 | default: 78 | fmt.Fprint(buf, v) 79 | } 80 | } 81 | 82 | func (c *loggingConn) print(method, commandName string, args []interface{}, reply interface{}, err error) { 83 | var buf bytes.Buffer 84 | fmt.Fprintf(&buf, "%s%s(", c.prefix, method) 85 | if method != "Receive" { 86 | buf.WriteString(commandName) 87 | for _, arg := range args { 88 | buf.WriteString(", ") 89 | c.printValue(&buf, arg) 90 | } 91 | } 92 | buf.WriteString(") -> (") 93 | if method != "Send" { 94 | c.printValue(&buf, reply) 95 | buf.WriteString(", ") 96 | } 97 | fmt.Fprintf(&buf, "%v)", err) 98 | c.logger.Output(3, buf.String()) 99 | } 100 | 101 | func (c *loggingConn) Do(commandName string, args ...interface{}) (interface{}, error) { 102 | reply, err := c.Conn.Do(commandName, args...) 103 | c.print("Do", commandName, args, reply, err) 104 | return reply, err 105 | } 106 | 107 | func (c *loggingConn) Send(commandName string, args ...interface{}) error { 108 | err := c.Conn.Send(commandName, args...) 109 | c.print("Send", commandName, args, nil, err) 110 | return err 111 | } 112 | 113 | func (c *loggingConn) Receive() (interface{}, error) { 114 | reply, err := c.Conn.Receive() 115 | c.print("Receive", "", nil, reply, err) 116 | return reply, err 117 | } 118 | -------------------------------------------------------------------------------- /vendor/github.com/garyburd/redigo/redis/pubsub.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Gary Burd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package redis 16 | 17 | import "errors" 18 | 19 | // Subscription represents a subscribe or unsubscribe notification. 20 | type Subscription struct { 21 | 22 | // Kind is "subscribe", "unsubscribe", "psubscribe" or "punsubscribe" 23 | Kind string 24 | 25 | // The channel that was changed. 26 | Channel string 27 | 28 | // The current number of subscriptions for connection. 29 | Count int 30 | } 31 | 32 | // Message represents a message notification. 33 | type Message struct { 34 | 35 | // The originating channel. 36 | Channel string 37 | 38 | // The message data. 39 | Data []byte 40 | } 41 | 42 | // PMessage represents a pmessage notification. 43 | type PMessage struct { 44 | 45 | // The matched pattern. 46 | Pattern string 47 | 48 | // The originating channel. 49 | Channel string 50 | 51 | // The message data. 52 | Data []byte 53 | } 54 | 55 | // Pong represents a pubsub pong notification. 56 | type Pong struct { 57 | Data string 58 | } 59 | 60 | // PubSubConn wraps a Conn with convenience methods for subscribers. 61 | type PubSubConn struct { 62 | Conn Conn 63 | } 64 | 65 | // Close closes the connection. 66 | func (c PubSubConn) Close() error { 67 | return c.Conn.Close() 68 | } 69 | 70 | // Subscribe subscribes the connection to the specified channels. 71 | func (c PubSubConn) Subscribe(channel ...interface{}) error { 72 | c.Conn.Send("SUBSCRIBE", channel...) 73 | return c.Conn.Flush() 74 | } 75 | 76 | // PSubscribe subscribes the connection to the given patterns. 77 | func (c PubSubConn) PSubscribe(channel ...interface{}) error { 78 | c.Conn.Send("PSUBSCRIBE", channel...) 79 | return c.Conn.Flush() 80 | } 81 | 82 | // Unsubscribe unsubscribes the connection from the given channels, or from all 83 | // of them if none is given. 84 | func (c PubSubConn) Unsubscribe(channel ...interface{}) error { 85 | c.Conn.Send("UNSUBSCRIBE", channel...) 86 | return c.Conn.Flush() 87 | } 88 | 89 | // PUnsubscribe unsubscribes the connection from the given patterns, or from all 90 | // of them if none is given. 91 | func (c PubSubConn) PUnsubscribe(channel ...interface{}) error { 92 | c.Conn.Send("PUNSUBSCRIBE", channel...) 93 | return c.Conn.Flush() 94 | } 95 | 96 | // Ping sends a PING to the server with the specified data. 97 | func (c PubSubConn) Ping(data string) error { 98 | c.Conn.Send("PING", data) 99 | return c.Conn.Flush() 100 | } 101 | 102 | // Receive returns a pushed message as a Subscription, Message, PMessage, Pong 103 | // or error. The return value is intended to be used directly in a type switch 104 | // as illustrated in the PubSubConn example. 105 | func (c PubSubConn) Receive() interface{} { 106 | reply, err := Values(c.Conn.Receive()) 107 | if err != nil { 108 | return err 109 | } 110 | 111 | var kind string 112 | reply, err = Scan(reply, &kind) 113 | if err != nil { 114 | return err 115 | } 116 | 117 | switch kind { 118 | case "message": 119 | var m Message 120 | if _, err := Scan(reply, &m.Channel, &m.Data); err != nil { 121 | return err 122 | } 123 | return m 124 | case "pmessage": 125 | var pm PMessage 126 | if _, err := Scan(reply, &pm.Pattern, &pm.Channel, &pm.Data); err != nil { 127 | return err 128 | } 129 | return pm 130 | case "subscribe", "psubscribe", "unsubscribe", "punsubscribe": 131 | s := Subscription{Kind: kind} 132 | if _, err := Scan(reply, &s.Channel, &s.Count); err != nil { 133 | return err 134 | } 135 | return s 136 | case "pong": 137 | var p Pong 138 | if _, err := Scan(reply, &p.Data); err != nil { 139 | return err 140 | } 141 | return p 142 | } 143 | return errors.New("redigo: unknown pubsub notification") 144 | } 145 | -------------------------------------------------------------------------------- /vendor/github.com/garyburd/redigo/redis/redis.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Gary Burd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package redis 16 | 17 | // Error represents an error returned in a command reply. 18 | type Error string 19 | 20 | func (err Error) Error() string { return string(err) } 21 | 22 | // Conn represents a connection to a Redis server. 23 | type Conn interface { 24 | // Close closes the connection. 25 | Close() error 26 | 27 | // Err returns a non-nil value if the connection is broken. The returned 28 | // value is either the first non-nil value returned from the underlying 29 | // network connection or a protocol parsing error. Applications should 30 | // close broken connections. 31 | Err() error 32 | 33 | // Do sends a command to the server and returns the received reply. 34 | Do(commandName string, args ...interface{}) (reply interface{}, err error) 35 | 36 | // Send writes the command to the client's output buffer. 37 | Send(commandName string, args ...interface{}) error 38 | 39 | // Flush flushes the output buffer to the Redis server. 40 | Flush() error 41 | 42 | // Receive receives a single reply from the Redis server 43 | Receive() (reply interface{}, err error) 44 | } 45 | -------------------------------------------------------------------------------- /vendor/github.com/garyburd/redigo/redis/script.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Gary Burd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package redis 16 | 17 | import ( 18 | "crypto/sha1" 19 | "encoding/hex" 20 | "io" 21 | "strings" 22 | ) 23 | 24 | // Script encapsulates the source, hash and key count for a Lua script. See 25 | // http://redis.io/commands/eval for information on scripts in Redis. 26 | type Script struct { 27 | keyCount int 28 | src string 29 | hash string 30 | } 31 | 32 | // NewScript returns a new script object. If keyCount is greater than or equal 33 | // to zero, then the count is automatically inserted in the EVAL command 34 | // argument list. If keyCount is less than zero, then the application supplies 35 | // the count as the first value in the keysAndArgs argument to the Do, Send and 36 | // SendHash methods. 37 | func NewScript(keyCount int, src string) *Script { 38 | h := sha1.New() 39 | io.WriteString(h, src) 40 | return &Script{keyCount, src, hex.EncodeToString(h.Sum(nil))} 41 | } 42 | 43 | func (s *Script) args(spec string, keysAndArgs []interface{}) []interface{} { 44 | var args []interface{} 45 | if s.keyCount < 0 { 46 | args = make([]interface{}, 1+len(keysAndArgs)) 47 | args[0] = spec 48 | copy(args[1:], keysAndArgs) 49 | } else { 50 | args = make([]interface{}, 2+len(keysAndArgs)) 51 | args[0] = spec 52 | args[1] = s.keyCount 53 | copy(args[2:], keysAndArgs) 54 | } 55 | return args 56 | } 57 | 58 | // Do evaluates the script. Under the covers, Do optimistically evaluates the 59 | // script using the EVALSHA command. If the command fails because the script is 60 | // not loaded, then Do evaluates the script using the EVAL command (thus 61 | // causing the script to load). 62 | func (s *Script) Do(c Conn, keysAndArgs ...interface{}) (interface{}, error) { 63 | v, err := c.Do("EVALSHA", s.args(s.hash, keysAndArgs)...) 64 | if e, ok := err.(Error); ok && strings.HasPrefix(string(e), "NOSCRIPT ") { 65 | v, err = c.Do("EVAL", s.args(s.src, keysAndArgs)...) 66 | } 67 | return v, err 68 | } 69 | 70 | // SendHash evaluates the script without waiting for the reply. The script is 71 | // evaluated with the EVALSHA command. The application must ensure that the 72 | // script is loaded by a previous call to Send, Do or Load methods. 73 | func (s *Script) SendHash(c Conn, keysAndArgs ...interface{}) error { 74 | return c.Send("EVALSHA", s.args(s.hash, keysAndArgs)...) 75 | } 76 | 77 | // Send evaluates the script without waiting for the reply. 78 | func (s *Script) Send(c Conn, keysAndArgs ...interface{}) error { 79 | return c.Send("EVAL", s.args(s.src, keysAndArgs)...) 80 | } 81 | 82 | // Load loads the script without evaluating it. 83 | func (s *Script) Load(c Conn) error { 84 | _, err := c.Do("SCRIPT", "LOAD", s.src) 85 | return err 86 | } 87 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/activity.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package github 7 | 8 | // ActivityService handles communication with the activity related 9 | // methods of the GitHub API. 10 | // 11 | // GitHub API docs: http://developer.github.com/v3/activity/ 12 | type ActivityService service 13 | 14 | // FeedLink represents a link to a related resource. 15 | type FeedLink struct { 16 | HRef *string `json:"href,omitempty"` 17 | Type *string `json:"type,omitempty"` 18 | } 19 | 20 | // Feeds represents timeline resources in Atom format. 21 | type Feeds struct { 22 | TimelineURL *string `json:"timeline_url,omitempty"` 23 | UserURL *string `json:"user_url,omitempty"` 24 | CurrentUserPublicURL *string `json:"current_user_public_url,omitempty"` 25 | CurrentUserURL *string `json:"current_user_url,omitempty"` 26 | CurrentUserActorURL *string `json:"current_user_actor_url,omitempty"` 27 | CurrentUserOrganizationURL *string `json:"current_user_organization_url,omitempty"` 28 | CurrentUserOrganizationURLs []string `json:"current_user_organization_urls,omitempty"` 29 | Links *struct { 30 | Timeline *FeedLink `json:"timeline,omitempty"` 31 | User *FeedLink `json:"user,omitempty"` 32 | CurrentUserPublic *FeedLink `json:"current_user_public,omitempty"` 33 | CurrentUser *FeedLink `json:"current_user,omitempty"` 34 | CurrentUserActor *FeedLink `json:"current_user_actor,omitempty"` 35 | CurrentUserOrganization *FeedLink `json:"current_user_organization,omitempty"` 36 | CurrentUserOrganizations []FeedLink `json:"current_user_organizations,omitempty"` 37 | } `json:"_links,omitempty"` 38 | } 39 | 40 | // ListFeeds lists all the feeds available to the authenticated user. 41 | // 42 | // GitHub provides several timeline resources in Atom format: 43 | // Timeline: The GitHub global public timeline 44 | // User: The public timeline for any user, using URI template 45 | // Current user public: The public timeline for the authenticated user 46 | // Current user: The private timeline for the authenticated user 47 | // Current user actor: The private timeline for activity created by the 48 | // authenticated user 49 | // Current user organizations: The private timeline for the organizations 50 | // the authenticated user is a member of. 51 | // 52 | // Note: Private feeds are only returned when authenticating via Basic Auth 53 | // since current feed URIs use the older, non revocable auth tokens. 54 | func (s *ActivityService) ListFeeds() (*Feeds, *Response, error) { 55 | req, err := s.client.NewRequest("GET", "feeds", nil) 56 | if err != nil { 57 | return nil, nil, err 58 | } 59 | 60 | f := &Feeds{} 61 | resp, err := s.client.Do(req, f) 62 | if err != nil { 63 | return nil, resp, err 64 | } 65 | 66 | return f, resp, nil 67 | } 68 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/activity_star.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package github 7 | 8 | import "fmt" 9 | 10 | // StarredRepository is returned by ListStarred. 11 | type StarredRepository struct { 12 | StarredAt *Timestamp `json:"starred_at,omitempty"` 13 | Repository *Repository `json:"repo,omitempty"` 14 | } 15 | 16 | // Stargazer represents a user that has starred a repository. 17 | type Stargazer struct { 18 | StarredAt *Timestamp `json:"starred_at,omitempty"` 19 | User *User `json:"user,omitempty"` 20 | } 21 | 22 | // ListStargazers lists people who have starred the specified repo. 23 | // 24 | // GitHub API Docs: https://developer.github.com/v3/activity/starring/#list-stargazers 25 | func (s *ActivityService) ListStargazers(owner, repo string, opt *ListOptions) ([]*Stargazer, *Response, error) { 26 | u := fmt.Sprintf("repos/%s/%s/stargazers", owner, repo) 27 | u, err := addOptions(u, opt) 28 | if err != nil { 29 | return nil, nil, err 30 | } 31 | 32 | req, err := s.client.NewRequest("GET", u, nil) 33 | if err != nil { 34 | return nil, nil, err 35 | } 36 | 37 | // TODO: remove custom Accept header when this API fully launches 38 | req.Header.Set("Accept", mediaTypeStarringPreview) 39 | 40 | stargazers := new([]*Stargazer) 41 | resp, err := s.client.Do(req, stargazers) 42 | if err != nil { 43 | return nil, resp, err 44 | } 45 | 46 | return *stargazers, resp, err 47 | } 48 | 49 | // ActivityListStarredOptions specifies the optional parameters to the 50 | // ActivityService.ListStarred method. 51 | type ActivityListStarredOptions struct { 52 | // How to sort the repository list. Possible values are: created, updated, 53 | // pushed, full_name. Default is "full_name". 54 | Sort string `url:"sort,omitempty"` 55 | 56 | // Direction in which to sort repositories. Possible values are: asc, desc. 57 | // Default is "asc" when sort is "full_name", otherwise default is "desc". 58 | Direction string `url:"direction,omitempty"` 59 | 60 | ListOptions 61 | } 62 | 63 | // ListStarred lists all the repos starred by a user. Passing the empty string 64 | // will list the starred repositories for the authenticated user. 65 | // 66 | // GitHub API docs: http://developer.github.com/v3/activity/starring/#list-repositories-being-starred 67 | func (s *ActivityService) ListStarred(user string, opt *ActivityListStarredOptions) ([]*StarredRepository, *Response, error) { 68 | var u string 69 | if user != "" { 70 | u = fmt.Sprintf("users/%v/starred", user) 71 | } else { 72 | u = "user/starred" 73 | } 74 | u, err := addOptions(u, opt) 75 | if err != nil { 76 | return nil, nil, err 77 | } 78 | 79 | req, err := s.client.NewRequest("GET", u, nil) 80 | if err != nil { 81 | return nil, nil, err 82 | } 83 | 84 | // TODO: remove custom Accept header when this API fully launches 85 | req.Header.Set("Accept", mediaTypeStarringPreview) 86 | 87 | repos := new([]*StarredRepository) 88 | resp, err := s.client.Do(req, repos) 89 | if err != nil { 90 | return nil, resp, err 91 | } 92 | 93 | return *repos, resp, err 94 | } 95 | 96 | // IsStarred checks if a repository is starred by authenticated user. 97 | // 98 | // GitHub API docs: https://developer.github.com/v3/activity/starring/#check-if-you-are-starring-a-repository 99 | func (s *ActivityService) IsStarred(owner, repo string) (bool, *Response, error) { 100 | u := fmt.Sprintf("user/starred/%v/%v", owner, repo) 101 | req, err := s.client.NewRequest("GET", u, nil) 102 | if err != nil { 103 | return false, nil, err 104 | } 105 | resp, err := s.client.Do(req, nil) 106 | starred, err := parseBoolResponse(err) 107 | return starred, resp, err 108 | } 109 | 110 | // Star a repository as the authenticated user. 111 | // 112 | // GitHub API docs: https://developer.github.com/v3/activity/starring/#star-a-repository 113 | func (s *ActivityService) Star(owner, repo string) (*Response, error) { 114 | u := fmt.Sprintf("user/starred/%v/%v", owner, repo) 115 | req, err := s.client.NewRequest("PUT", u, nil) 116 | if err != nil { 117 | return nil, err 118 | } 119 | return s.client.Do(req, nil) 120 | } 121 | 122 | // Unstar a repository as the authenticated user. 123 | // 124 | // GitHub API docs: https://developer.github.com/v3/activity/starring/#unstar-a-repository 125 | func (s *ActivityService) Unstar(owner, repo string) (*Response, error) { 126 | u := fmt.Sprintf("user/starred/%v/%v", owner, repo) 127 | req, err := s.client.NewRequest("DELETE", u, nil) 128 | if err != nil { 129 | return nil, err 130 | } 131 | return s.client.Do(req, nil) 132 | } 133 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/activity_watching.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package github 7 | 8 | import "fmt" 9 | 10 | // Subscription identifies a repository or thread subscription. 11 | type Subscription struct { 12 | Subscribed *bool `json:"subscribed,omitempty"` 13 | Ignored *bool `json:"ignored,omitempty"` 14 | Reason *string `json:"reason,omitempty"` 15 | CreatedAt *Timestamp `json:"created_at,omitempty"` 16 | URL *string `json:"url,omitempty"` 17 | 18 | // only populated for repository subscriptions 19 | RepositoryURL *string `json:"repository_url,omitempty"` 20 | 21 | // only populated for thread subscriptions 22 | ThreadURL *string `json:"thread_url,omitempty"` 23 | } 24 | 25 | // ListWatchers lists watchers of a particular repo. 26 | // 27 | // GitHub API Docs: http://developer.github.com/v3/activity/watching/#list-watchers 28 | func (s *ActivityService) ListWatchers(owner, repo string, opt *ListOptions) ([]*User, *Response, error) { 29 | u := fmt.Sprintf("repos/%s/%s/subscribers", owner, repo) 30 | u, err := addOptions(u, opt) 31 | if err != nil { 32 | return nil, nil, err 33 | } 34 | 35 | req, err := s.client.NewRequest("GET", u, nil) 36 | if err != nil { 37 | return nil, nil, err 38 | } 39 | 40 | watchers := new([]*User) 41 | resp, err := s.client.Do(req, watchers) 42 | if err != nil { 43 | return nil, resp, err 44 | } 45 | 46 | return *watchers, resp, err 47 | } 48 | 49 | // ListWatched lists the repositories the specified user is watching. Passing 50 | // the empty string will fetch watched repos for the authenticated user. 51 | // 52 | // GitHub API Docs: https://developer.github.com/v3/activity/watching/#list-repositories-being-watched 53 | func (s *ActivityService) ListWatched(user string, opt *ListOptions) ([]*Repository, *Response, error) { 54 | var u string 55 | if user != "" { 56 | u = fmt.Sprintf("users/%v/subscriptions", user) 57 | } else { 58 | u = "user/subscriptions" 59 | } 60 | u, err := addOptions(u, opt) 61 | if err != nil { 62 | return nil, nil, err 63 | } 64 | 65 | req, err := s.client.NewRequest("GET", u, nil) 66 | if err != nil { 67 | return nil, nil, err 68 | } 69 | 70 | watched := new([]*Repository) 71 | resp, err := s.client.Do(req, watched) 72 | if err != nil { 73 | return nil, resp, err 74 | } 75 | 76 | return *watched, resp, err 77 | } 78 | 79 | // GetRepositorySubscription returns the subscription for the specified 80 | // repository for the authenticated user. If the authenticated user is not 81 | // watching the repository, a nil Subscription is returned. 82 | // 83 | // GitHub API Docs: https://developer.github.com/v3/activity/watching/#get-a-repository-subscription 84 | func (s *ActivityService) GetRepositorySubscription(owner, repo string) (*Subscription, *Response, error) { 85 | u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo) 86 | 87 | req, err := s.client.NewRequest("GET", u, nil) 88 | if err != nil { 89 | return nil, nil, err 90 | } 91 | 92 | sub := new(Subscription) 93 | resp, err := s.client.Do(req, sub) 94 | if err != nil { 95 | // if it's just a 404, don't return that as an error 96 | _, err = parseBoolResponse(err) 97 | return nil, resp, err 98 | } 99 | 100 | return sub, resp, err 101 | } 102 | 103 | // SetRepositorySubscription sets the subscription for the specified repository 104 | // for the authenticated user. 105 | // 106 | // GitHub API Docs: https://developer.github.com/v3/activity/watching/#set-a-repository-subscription 107 | func (s *ActivityService) SetRepositorySubscription(owner, repo string, subscription *Subscription) (*Subscription, *Response, error) { 108 | u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo) 109 | 110 | req, err := s.client.NewRequest("PUT", u, subscription) 111 | if err != nil { 112 | return nil, nil, err 113 | } 114 | 115 | sub := new(Subscription) 116 | resp, err := s.client.Do(req, sub) 117 | if err != nil { 118 | return nil, resp, err 119 | } 120 | 121 | return sub, resp, err 122 | } 123 | 124 | // DeleteRepositorySubscription deletes the subscription for the specified 125 | // repository for the authenticated user. 126 | // 127 | // GitHub API Docs: https://developer.github.com/v3/activity/watching/#delete-a-repository-subscription 128 | func (s *ActivityService) DeleteRepositorySubscription(owner, repo string) (*Response, error) { 129 | u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo) 130 | req, err := s.client.NewRequest("DELETE", u, nil) 131 | if err != nil { 132 | return nil, err 133 | } 134 | 135 | return s.client.Do(req, nil) 136 | } 137 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/gists_comments.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package github 7 | 8 | import ( 9 | "fmt" 10 | "time" 11 | ) 12 | 13 | // GistComment represents a Gist comment. 14 | type GistComment struct { 15 | ID *int `json:"id,omitempty"` 16 | URL *string `json:"url,omitempty"` 17 | Body *string `json:"body,omitempty"` 18 | User *User `json:"user,omitempty"` 19 | CreatedAt *time.Time `json:"created_at,omitempty"` 20 | } 21 | 22 | func (g GistComment) String() string { 23 | return Stringify(g) 24 | } 25 | 26 | // ListComments lists all comments for a gist. 27 | // 28 | // GitHub API docs: http://developer.github.com/v3/gists/comments/#list-comments-on-a-gist 29 | func (s *GistsService) ListComments(gistID string, opt *ListOptions) ([]*GistComment, *Response, error) { 30 | u := fmt.Sprintf("gists/%v/comments", gistID) 31 | u, err := addOptions(u, opt) 32 | if err != nil { 33 | return nil, nil, err 34 | } 35 | 36 | req, err := s.client.NewRequest("GET", u, nil) 37 | if err != nil { 38 | return nil, nil, err 39 | } 40 | 41 | comments := new([]*GistComment) 42 | resp, err := s.client.Do(req, comments) 43 | if err != nil { 44 | return nil, resp, err 45 | } 46 | 47 | return *comments, resp, err 48 | } 49 | 50 | // GetComment retrieves a single comment from a gist. 51 | // 52 | // GitHub API docs: http://developer.github.com/v3/gists/comments/#get-a-single-comment 53 | func (s *GistsService) GetComment(gistID string, commentID int) (*GistComment, *Response, error) { 54 | u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID) 55 | req, err := s.client.NewRequest("GET", u, nil) 56 | if err != nil { 57 | return nil, nil, err 58 | } 59 | 60 | c := new(GistComment) 61 | resp, err := s.client.Do(req, c) 62 | if err != nil { 63 | return nil, resp, err 64 | } 65 | 66 | return c, resp, err 67 | } 68 | 69 | // CreateComment creates a comment for a gist. 70 | // 71 | // GitHub API docs: http://developer.github.com/v3/gists/comments/#create-a-comment 72 | func (s *GistsService) CreateComment(gistID string, comment *GistComment) (*GistComment, *Response, error) { 73 | u := fmt.Sprintf("gists/%v/comments", gistID) 74 | req, err := s.client.NewRequest("POST", u, comment) 75 | if err != nil { 76 | return nil, nil, err 77 | } 78 | 79 | c := new(GistComment) 80 | resp, err := s.client.Do(req, c) 81 | if err != nil { 82 | return nil, resp, err 83 | } 84 | 85 | return c, resp, err 86 | } 87 | 88 | // EditComment edits an existing gist comment. 89 | // 90 | // GitHub API docs: http://developer.github.com/v3/gists/comments/#edit-a-comment 91 | func (s *GistsService) EditComment(gistID string, commentID int, comment *GistComment) (*GistComment, *Response, error) { 92 | u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID) 93 | req, err := s.client.NewRequest("PATCH", u, comment) 94 | if err != nil { 95 | return nil, nil, err 96 | } 97 | 98 | c := new(GistComment) 99 | resp, err := s.client.Do(req, c) 100 | if err != nil { 101 | return nil, resp, err 102 | } 103 | 104 | return c, resp, err 105 | } 106 | 107 | // DeleteComment deletes a gist comment. 108 | // 109 | // GitHub API docs: http://developer.github.com/v3/gists/comments/#delete-a-comment 110 | func (s *GistsService) DeleteComment(gistID string, commentID int) (*Response, error) { 111 | u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID) 112 | req, err := s.client.NewRequest("DELETE", u, nil) 113 | if err != nil { 114 | return nil, err 115 | } 116 | 117 | return s.client.Do(req, nil) 118 | } 119 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/git.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package github 7 | 8 | // GitService handles communication with the git data related 9 | // methods of the GitHub API. 10 | // 11 | // GitHub API docs: http://developer.github.com/v3/git/ 12 | type GitService service 13 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/git_blobs.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package github 7 | 8 | import "fmt" 9 | 10 | // Blob represents a blob object. 11 | type Blob struct { 12 | Content *string `json:"content,omitempty"` 13 | Encoding *string `json:"encoding,omitempty"` 14 | SHA *string `json:"sha,omitempty"` 15 | Size *int `json:"size,omitempty"` 16 | URL *string `json:"url,omitempty"` 17 | } 18 | 19 | // GetBlob fetchs a blob from a repo given a SHA. 20 | // 21 | // GitHub API docs: http://developer.github.com/v3/git/blobs/#get-a-blob 22 | func (s *GitService) GetBlob(owner string, repo string, sha string) (*Blob, *Response, error) { 23 | u := fmt.Sprintf("repos/%v/%v/git/blobs/%v", owner, repo, sha) 24 | req, err := s.client.NewRequest("GET", u, nil) 25 | if err != nil { 26 | return nil, nil, err 27 | } 28 | 29 | blob := new(Blob) 30 | resp, err := s.client.Do(req, blob) 31 | return blob, resp, err 32 | } 33 | 34 | // CreateBlob creates a blob object. 35 | // 36 | // GitHub API docs: https://developer.github.com/v3/git/blobs/#create-a-blob 37 | func (s *GitService) CreateBlob(owner string, repo string, blob *Blob) (*Blob, *Response, error) { 38 | u := fmt.Sprintf("repos/%v/%v/git/blobs", owner, repo) 39 | req, err := s.client.NewRequest("POST", u, blob) 40 | if err != nil { 41 | return nil, nil, err 42 | } 43 | 44 | t := new(Blob) 45 | resp, err := s.client.Do(req, t) 46 | return t, resp, err 47 | } 48 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/git_commits.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package github 7 | 8 | import ( 9 | "fmt" 10 | "time" 11 | ) 12 | 13 | // SignatureVerification represents GPG signature verification. 14 | type SignatureVerification struct { 15 | Verified *bool `json:"verified,omitempty"` 16 | Reason *string `json:"reason,omitempty"` 17 | Signature *string `json:"signature,omitempty"` 18 | Payload *string `json:"payload,omitempty"` 19 | } 20 | 21 | // Commit represents a GitHub commit. 22 | type Commit struct { 23 | SHA *string `json:"sha,omitempty"` 24 | Author *CommitAuthor `json:"author,omitempty"` 25 | Committer *CommitAuthor `json:"committer,omitempty"` 26 | Message *string `json:"message,omitempty"` 27 | Tree *Tree `json:"tree,omitempty"` 28 | Parents []Commit `json:"parents,omitempty"` 29 | Stats *CommitStats `json:"stats,omitempty"` 30 | URL *string `json:"url,omitempty"` 31 | Verification *SignatureVerification `json:"verification,omitempty"` 32 | 33 | // CommentCount is the number of GitHub comments on the commit. This 34 | // is only populated for requests that fetch GitHub data like 35 | // Pulls.ListCommits, Repositories.ListCommits, etc. 36 | CommentCount *int `json:"comment_count,omitempty"` 37 | } 38 | 39 | func (c Commit) String() string { 40 | return Stringify(c) 41 | } 42 | 43 | // CommitAuthor represents the author or committer of a commit. The commit 44 | // author may not correspond to a GitHub User. 45 | type CommitAuthor struct { 46 | Date *time.Time `json:"date,omitempty"` 47 | Name *string `json:"name,omitempty"` 48 | Email *string `json:"email,omitempty"` 49 | 50 | // The following fields are only populated by Webhook events. 51 | Login *string `json:"username,omitempty"` // Renamed for go-github consistency. 52 | } 53 | 54 | func (c CommitAuthor) String() string { 55 | return Stringify(c) 56 | } 57 | 58 | // GetCommit fetchs the Commit object for a given SHA. 59 | // 60 | // GitHub API docs: http://developer.github.com/v3/git/commits/#get-a-commit 61 | func (s *GitService) GetCommit(owner string, repo string, sha string) (*Commit, *Response, error) { 62 | u := fmt.Sprintf("repos/%v/%v/git/commits/%v", owner, repo, sha) 63 | req, err := s.client.NewRequest("GET", u, nil) 64 | if err != nil { 65 | return nil, nil, err 66 | } 67 | 68 | // TODO: remove custom Accept header when this API fully launches. 69 | req.Header.Set("Accept", mediaTypeGitSigningPreview) 70 | 71 | c := new(Commit) 72 | resp, err := s.client.Do(req, c) 73 | if err != nil { 74 | return nil, resp, err 75 | } 76 | 77 | return c, resp, err 78 | } 79 | 80 | // createCommit represents the body of a CreateCommit request. 81 | type createCommit struct { 82 | Author *CommitAuthor `json:"author,omitempty"` 83 | Committer *CommitAuthor `json:"committer,omitempty"` 84 | Message *string `json:"message,omitempty"` 85 | Tree *string `json:"tree,omitempty"` 86 | Parents []string `json:"parents,omitempty"` 87 | } 88 | 89 | // CreateCommit creates a new commit in a repository. 90 | // 91 | // The commit.Committer is optional and will be filled with the commit.Author 92 | // data if omitted. If the commit.Author is omitted, it will be filled in with 93 | // the authenticated user’s information and the current date. 94 | // 95 | // GitHub API docs: http://developer.github.com/v3/git/commits/#create-a-commit 96 | func (s *GitService) CreateCommit(owner string, repo string, commit *Commit) (*Commit, *Response, error) { 97 | u := fmt.Sprintf("repos/%v/%v/git/commits", owner, repo) 98 | 99 | body := &createCommit{} 100 | if commit != nil { 101 | parents := make([]string, len(commit.Parents)) 102 | for i, parent := range commit.Parents { 103 | parents[i] = *parent.SHA 104 | } 105 | 106 | body = &createCommit{ 107 | Author: commit.Author, 108 | Committer: commit.Committer, 109 | Message: commit.Message, 110 | Tree: commit.Tree.SHA, 111 | Parents: parents, 112 | } 113 | } 114 | 115 | req, err := s.client.NewRequest("POST", u, body) 116 | if err != nil { 117 | return nil, nil, err 118 | } 119 | 120 | c := new(Commit) 121 | resp, err := s.client.Do(req, c) 122 | if err != nil { 123 | return nil, resp, err 124 | } 125 | 126 | return c, resp, err 127 | } 128 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/git_tags.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package github 7 | 8 | import ( 9 | "fmt" 10 | ) 11 | 12 | // Tag represents a tag object. 13 | type Tag struct { 14 | Tag *string `json:"tag,omitempty"` 15 | SHA *string `json:"sha,omitempty"` 16 | URL *string `json:"url,omitempty"` 17 | Message *string `json:"message,omitempty"` 18 | Tagger *CommitAuthor `json:"tagger,omitempty"` 19 | Object *GitObject `json:"object,omitempty"` 20 | Verification *SignatureVerification `json:"verification,omitempty"` 21 | } 22 | 23 | // createTagRequest represents the body of a CreateTag request. This is mostly 24 | // identical to Tag with the exception that the object SHA and Type are 25 | // top-level fields, rather than being nested inside a JSON object. 26 | type createTagRequest struct { 27 | Tag *string `json:"tag,omitempty"` 28 | Message *string `json:"message,omitempty"` 29 | Object *string `json:"object,omitempty"` 30 | Type *string `json:"type,omitempty"` 31 | Tagger *CommitAuthor `json:"tagger,omitempty"` 32 | } 33 | 34 | // GetTag fetchs a tag from a repo given a SHA. 35 | // 36 | // GitHub API docs: http://developer.github.com/v3/git/tags/#get-a-tag 37 | func (s *GitService) GetTag(owner string, repo string, sha string) (*Tag, *Response, error) { 38 | u := fmt.Sprintf("repos/%v/%v/git/tags/%v", owner, repo, sha) 39 | req, err := s.client.NewRequest("GET", u, nil) 40 | if err != nil { 41 | return nil, nil, err 42 | } 43 | 44 | // TODO: remove custom Accept header when this API fully launches. 45 | req.Header.Set("Accept", mediaTypeGitSigningPreview) 46 | 47 | tag := new(Tag) 48 | resp, err := s.client.Do(req, tag) 49 | return tag, resp, err 50 | } 51 | 52 | // CreateTag creates a tag object. 53 | // 54 | // GitHub API docs: http://developer.github.com/v3/git/tags/#create-a-tag-object 55 | func (s *GitService) CreateTag(owner string, repo string, tag *Tag) (*Tag, *Response, error) { 56 | u := fmt.Sprintf("repos/%v/%v/git/tags", owner, repo) 57 | 58 | // convert Tag into a createTagRequest 59 | tagRequest := &createTagRequest{ 60 | Tag: tag.Tag, 61 | Message: tag.Message, 62 | Tagger: tag.Tagger, 63 | } 64 | if tag.Object != nil { 65 | tagRequest.Object = tag.Object.SHA 66 | tagRequest.Type = tag.Object.Type 67 | } 68 | 69 | req, err := s.client.NewRequest("POST", u, tagRequest) 70 | if err != nil { 71 | return nil, nil, err 72 | } 73 | 74 | t := new(Tag) 75 | resp, err := s.client.Do(req, t) 76 | return t, resp, err 77 | } 78 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/git_trees.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package github 7 | 8 | import "fmt" 9 | 10 | // Tree represents a GitHub tree. 11 | type Tree struct { 12 | SHA *string `json:"sha,omitempty"` 13 | Entries []TreeEntry `json:"tree,omitempty"` 14 | } 15 | 16 | func (t Tree) String() string { 17 | return Stringify(t) 18 | } 19 | 20 | // TreeEntry represents the contents of a tree structure. TreeEntry can 21 | // represent either a blob, a commit (in the case of a submodule), or another 22 | // tree. 23 | type TreeEntry struct { 24 | SHA *string `json:"sha,omitempty"` 25 | Path *string `json:"path,omitempty"` 26 | Mode *string `json:"mode,omitempty"` 27 | Type *string `json:"type,omitempty"` 28 | Size *int `json:"size,omitempty"` 29 | Content *string `json:"content,omitempty"` 30 | } 31 | 32 | func (t TreeEntry) String() string { 33 | return Stringify(t) 34 | } 35 | 36 | // GetTree fetches the Tree object for a given sha hash from a repository. 37 | // 38 | // GitHub API docs: http://developer.github.com/v3/git/trees/#get-a-tree 39 | func (s *GitService) GetTree(owner string, repo string, sha string, recursive bool) (*Tree, *Response, error) { 40 | u := fmt.Sprintf("repos/%v/%v/git/trees/%v", owner, repo, sha) 41 | if recursive { 42 | u += "?recursive=1" 43 | } 44 | 45 | req, err := s.client.NewRequest("GET", u, nil) 46 | if err != nil { 47 | return nil, nil, err 48 | } 49 | 50 | t := new(Tree) 51 | resp, err := s.client.Do(req, t) 52 | if err != nil { 53 | return nil, resp, err 54 | } 55 | 56 | return t, resp, err 57 | } 58 | 59 | // createTree represents the body of a CreateTree request. 60 | type createTree struct { 61 | BaseTree string `json:"base_tree,omitempty"` 62 | Entries []TreeEntry `json:"tree"` 63 | } 64 | 65 | // CreateTree creates a new tree in a repository. If both a tree and a nested 66 | // path modifying that tree are specified, it will overwrite the contents of 67 | // that tree with the new path contents and write a new tree out. 68 | // 69 | // GitHub API docs: http://developer.github.com/v3/git/trees/#create-a-tree 70 | func (s *GitService) CreateTree(owner string, repo string, baseTree string, entries []TreeEntry) (*Tree, *Response, error) { 71 | u := fmt.Sprintf("repos/%v/%v/git/trees", owner, repo) 72 | 73 | body := &createTree{ 74 | BaseTree: baseTree, 75 | Entries: entries, 76 | } 77 | req, err := s.client.NewRequest("POST", u, body) 78 | if err != nil { 79 | return nil, nil, err 80 | } 81 | 82 | t := new(Tree) 83 | resp, err := s.client.Do(req, t) 84 | if err != nil { 85 | return nil, resp, err 86 | } 87 | 88 | return t, resp, err 89 | } 90 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/gitignore.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package github 7 | 8 | import "fmt" 9 | 10 | // GitignoresService provides access to the gitignore related functions in the 11 | // GitHub API. 12 | // 13 | // GitHub API docs: http://developer.github.com/v3/gitignore/ 14 | type GitignoresService service 15 | 16 | // Gitignore represents a .gitignore file as returned by the GitHub API. 17 | type Gitignore struct { 18 | Name *string `json:"name,omitempty"` 19 | Source *string `json:"source,omitempty"` 20 | } 21 | 22 | func (g Gitignore) String() string { 23 | return Stringify(g) 24 | } 25 | 26 | // List all available Gitignore templates. 27 | // 28 | // http://developer.github.com/v3/gitignore/#listing-available-templates 29 | func (s GitignoresService) List() ([]string, *Response, error) { 30 | req, err := s.client.NewRequest("GET", "gitignore/templates", nil) 31 | if err != nil { 32 | return nil, nil, err 33 | } 34 | 35 | availableTemplates := new([]string) 36 | resp, err := s.client.Do(req, availableTemplates) 37 | if err != nil { 38 | return nil, resp, err 39 | } 40 | 41 | return *availableTemplates, resp, err 42 | } 43 | 44 | // Get a Gitignore by name. 45 | // 46 | // http://developer.github.com/v3/gitignore/#get-a-single-template 47 | func (s GitignoresService) Get(name string) (*Gitignore, *Response, error) { 48 | u := fmt.Sprintf("gitignore/templates/%v", name) 49 | req, err := s.client.NewRequest("GET", u, nil) 50 | if err != nil { 51 | return nil, nil, err 52 | } 53 | 54 | gitignore := new(Gitignore) 55 | resp, err := s.client.Do(req, gitignore) 56 | if err != nil { 57 | return nil, resp, err 58 | } 59 | 60 | return gitignore, resp, err 61 | } 62 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/issues_assignees.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package github 7 | 8 | import "fmt" 9 | 10 | // ListAssignees fetches all available assignees (owners and collaborators) to 11 | // which issues may be assigned. 12 | // 13 | // GitHub API docs: http://developer.github.com/v3/issues/assignees/#list-assignees 14 | func (s *IssuesService) ListAssignees(owner, repo string, opt *ListOptions) ([]*User, *Response, error) { 15 | u := fmt.Sprintf("repos/%v/%v/assignees", owner, repo) 16 | u, err := addOptions(u, opt) 17 | if err != nil { 18 | return nil, nil, err 19 | } 20 | 21 | req, err := s.client.NewRequest("GET", u, nil) 22 | if err != nil { 23 | return nil, nil, err 24 | } 25 | assignees := new([]*User) 26 | resp, err := s.client.Do(req, assignees) 27 | if err != nil { 28 | return nil, resp, err 29 | } 30 | 31 | return *assignees, resp, err 32 | } 33 | 34 | // IsAssignee checks if a user is an assignee for the specified repository. 35 | // 36 | // GitHub API docs: http://developer.github.com/v3/issues/assignees/#check-assignee 37 | func (s *IssuesService) IsAssignee(owner, repo, user string) (bool, *Response, error) { 38 | u := fmt.Sprintf("repos/%v/%v/assignees/%v", owner, repo, user) 39 | req, err := s.client.NewRequest("GET", u, nil) 40 | if err != nil { 41 | return false, nil, err 42 | } 43 | resp, err := s.client.Do(req, nil) 44 | assignee, err := parseBoolResponse(err) 45 | return assignee, resp, err 46 | } 47 | 48 | // AddAssignees adds the provided GitHub users as assignees to the issue. 49 | // 50 | // GitHub API docs: https://developer.github.com/v3/issues/assignees/#add-assignees-to-an-issue 51 | func (s *IssuesService) AddAssignees(owner, repo string, number int, assignees []string) (*Issue, *Response, error) { 52 | users := &struct { 53 | Assignees []string `json:"assignees,omitempty"` 54 | }{Assignees: assignees} 55 | u := fmt.Sprintf("repos/%v/%v/issues/%v/assignees", owner, repo, number) 56 | req, err := s.client.NewRequest("POST", u, users) 57 | if err != nil { 58 | return nil, nil, err 59 | } 60 | 61 | issue := &Issue{} 62 | resp, err := s.client.Do(req, issue) 63 | return issue, resp, err 64 | } 65 | 66 | // RemoveAssignees removes the provided GitHub users as assignees from the issue. 67 | // 68 | // GitHub API docs: https://developer.github.com/v3/issues/assignees/#remove-assignees-from-an-issue 69 | func (s *IssuesService) RemoveAssignees(owner, repo string, number int, assignees []string) (*Issue, *Response, error) { 70 | users := &struct { 71 | Assignees []string `json:"assignees,omitempty"` 72 | }{Assignees: assignees} 73 | u := fmt.Sprintf("repos/%v/%v/issues/%v/assignees", owner, repo, number) 74 | req, err := s.client.NewRequest("DELETE", u, users) 75 | if err != nil { 76 | return nil, nil, err 77 | } 78 | 79 | issue := &Issue{} 80 | resp, err := s.client.Do(req, issue) 81 | return issue, resp, err 82 | } 83 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/licenses.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package github 7 | 8 | import "fmt" 9 | 10 | // LicensesService handles communication with the license related 11 | // methods of the GitHub API. 12 | // 13 | // GitHub API docs: http://developer.github.com/v3/pulls/ 14 | type LicensesService service 15 | 16 | // License represents an open source license. 17 | type License struct { 18 | Key *string `json:"key,omitempty"` 19 | Name *string `json:"name,omitempty"` 20 | URL *string `json:"url,omitempty"` 21 | 22 | HTMLURL *string `json:"html_url,omitempty"` 23 | Featured *bool `json:"featured,omitempty"` 24 | Description *string `json:"description,omitempty"` 25 | Category *string `json:"category,omitempty"` 26 | Implementation *string `json:"implementation,omitempty"` 27 | Required *[]string `json:"required,omitempty"` 28 | Permitted *[]string `json:"permitted,omitempty"` 29 | Forbidden *[]string `json:"forbidden,omitempty"` 30 | Body *string `json:"body,omitempty"` 31 | } 32 | 33 | func (l License) String() string { 34 | return Stringify(l) 35 | } 36 | 37 | // List popular open source licenses. 38 | // 39 | // GitHub API docs: https://developer.github.com/v3/licenses/#list-all-licenses 40 | func (s *LicensesService) List() ([]*License, *Response, error) { 41 | req, err := s.client.NewRequest("GET", "licenses", nil) 42 | if err != nil { 43 | return nil, nil, err 44 | } 45 | 46 | // TODO: remove custom Accept header when this API fully launches 47 | req.Header.Set("Accept", mediaTypeLicensesPreview) 48 | 49 | licenses := new([]*License) 50 | resp, err := s.client.Do(req, licenses) 51 | if err != nil { 52 | return nil, resp, err 53 | } 54 | 55 | return *licenses, resp, err 56 | } 57 | 58 | // Get extended metadata for one license. 59 | // 60 | // GitHub API docs: https://developer.github.com/v3/licenses/#get-an-individual-license 61 | func (s *LicensesService) Get(licenseName string) (*License, *Response, error) { 62 | u := fmt.Sprintf("licenses/%s", licenseName) 63 | 64 | req, err := s.client.NewRequest("GET", u, nil) 65 | if err != nil { 66 | return nil, nil, err 67 | } 68 | 69 | // TODO: remove custom Accept header when this API fully launches 70 | req.Header.Set("Accept", mediaTypeLicensesPreview) 71 | 72 | license := new(License) 73 | resp, err := s.client.Do(req, license) 74 | if err != nil { 75 | return nil, resp, err 76 | } 77 | 78 | return license, resp, err 79 | } 80 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/messages.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // This file provides functions for validating payloads from GitHub Webhooks. 7 | // GitHub docs: https://developer.github.com/webhooks/securing/#validating-payloads-from-github 8 | 9 | package github 10 | 11 | import ( 12 | "crypto/hmac" 13 | "crypto/sha1" 14 | "crypto/sha256" 15 | "crypto/sha512" 16 | "encoding/hex" 17 | "errors" 18 | "fmt" 19 | "hash" 20 | "io/ioutil" 21 | "net/http" 22 | "strings" 23 | ) 24 | 25 | const ( 26 | // sha1Prefix is the prefix used by GitHub before the HMAC hexdigest. 27 | sha1Prefix = "sha1" 28 | // sha256Prefix and sha512Prefix are provided for future compatibility. 29 | sha256Prefix = "sha256" 30 | sha512Prefix = "sha512" 31 | // signatureHeader is the GitHub header key used to pass the HMAC hexdigest. 32 | signatureHeader = "X-Hub-Signature" 33 | ) 34 | 35 | // genMAC generates the HMAC signature for a message provided the secret key 36 | // and hashFunc. 37 | func genMAC(message, key []byte, hashFunc func() hash.Hash) []byte { 38 | mac := hmac.New(hashFunc, key) 39 | mac.Write(message) 40 | return mac.Sum(nil) 41 | } 42 | 43 | // checkMAC reports whether messageMAC is a valid HMAC tag for message. 44 | func checkMAC(message, messageMAC, key []byte, hashFunc func() hash.Hash) bool { 45 | expectedMAC := genMAC(message, key, hashFunc) 46 | return hmac.Equal(messageMAC, expectedMAC) 47 | } 48 | 49 | // messageMAC returns the hex-decoded HMAC tag from the signature and its 50 | // corresponding hash function. 51 | func messageMAC(signature string) ([]byte, func() hash.Hash, error) { 52 | if signature == "" { 53 | return nil, nil, errors.New("missing signature") 54 | } 55 | sigParts := strings.SplitN(signature, "=", 2) 56 | if len(sigParts) != 2 { 57 | return nil, nil, fmt.Errorf("error parsing signature %q", signature) 58 | } 59 | 60 | var hashFunc func() hash.Hash 61 | switch sigParts[0] { 62 | case sha1Prefix: 63 | hashFunc = sha1.New 64 | case sha256Prefix: 65 | hashFunc = sha256.New 66 | case sha512Prefix: 67 | hashFunc = sha512.New 68 | default: 69 | return nil, nil, fmt.Errorf("unknown hash type prefix: %q", sigParts[0]) 70 | } 71 | 72 | buf, err := hex.DecodeString(sigParts[1]) 73 | if err != nil { 74 | return nil, nil, fmt.Errorf("error decoding signature %q: %v", signature, err) 75 | } 76 | return buf, hashFunc, nil 77 | } 78 | 79 | // ValidatePayload validates an incoming GitHub Webhook event request 80 | // and returns the (JSON) payload. 81 | // secretKey is the GitHub Webhook secret message. 82 | // 83 | // Example usage: 84 | // 85 | // func (s *GitHubEventMonitor) ServeHTTP(w http.ResponseWriter, r *http.Request) { 86 | // payload, err := github.ValidatePayload(r, s.webhookSecretKey) 87 | // if err != nil { ... } 88 | // // Process payload... 89 | // } 90 | // 91 | func ValidatePayload(r *http.Request, secretKey []byte) (payload []byte, err error) { 92 | payload, err = ioutil.ReadAll(r.Body) 93 | if err != nil { 94 | return nil, err 95 | } 96 | 97 | sig := r.Header.Get(signatureHeader) 98 | if err := validateSignature(sig, payload, secretKey); err != nil { 99 | return nil, err 100 | } 101 | return payload, nil 102 | } 103 | 104 | // validateSignature validates the signature for the given payload. 105 | // signature is the GitHub hash signature delivered in the X-Hub-Signature header. 106 | // payload is the JSON payload sent by GitHub Webhooks. 107 | // secretKey is the GitHub Webhook secret message. 108 | // 109 | // GitHub docs: https://developer.github.com/webhooks/securing/#validating-payloads-from-github 110 | func validateSignature(signature string, payload, secretKey []byte) error { 111 | messageMAC, hashFunc, err := messageMAC(signature) 112 | if err != nil { 113 | return err 114 | } 115 | if !checkMAC(payload, messageMAC, secretKey, hashFunc) { 116 | return errors.New("payload signature check failed") 117 | } 118 | return nil 119 | } 120 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/orgs_hooks.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package github 7 | 8 | import "fmt" 9 | 10 | // ListHooks lists all Hooks for the specified organization. 11 | // 12 | // GitHub API docs: https://developer.github.com/v3/orgs/hooks/#list-hooks 13 | func (s *OrganizationsService) ListHooks(org string, opt *ListOptions) ([]*Hook, *Response, error) { 14 | u := fmt.Sprintf("orgs/%v/hooks", org) 15 | u, err := addOptions(u, opt) 16 | if err != nil { 17 | return nil, nil, err 18 | } 19 | 20 | req, err := s.client.NewRequest("GET", u, nil) 21 | if err != nil { 22 | return nil, nil, err 23 | } 24 | 25 | hooks := new([]*Hook) 26 | resp, err := s.client.Do(req, hooks) 27 | if err != nil { 28 | return nil, resp, err 29 | } 30 | 31 | return *hooks, resp, err 32 | } 33 | 34 | // GetHook returns a single specified Hook. 35 | // 36 | // GitHub API docs: https://developer.github.com/v3/orgs/hooks/#get-single-hook 37 | func (s *OrganizationsService) GetHook(org string, id int) (*Hook, *Response, error) { 38 | u := fmt.Sprintf("orgs/%v/hooks/%d", org, id) 39 | req, err := s.client.NewRequest("GET", u, nil) 40 | if err != nil { 41 | return nil, nil, err 42 | } 43 | hook := new(Hook) 44 | resp, err := s.client.Do(req, hook) 45 | return hook, resp, err 46 | } 47 | 48 | // CreateHook creates a Hook for the specified org. 49 | // Name and Config are required fields. 50 | // 51 | // GitHub API docs: https://developer.github.com/v3/orgs/hooks/#create-a-hook 52 | func (s *OrganizationsService) CreateHook(org string, hook *Hook) (*Hook, *Response, error) { 53 | u := fmt.Sprintf("orgs/%v/hooks", org) 54 | req, err := s.client.NewRequest("POST", u, hook) 55 | if err != nil { 56 | return nil, nil, err 57 | } 58 | 59 | h := new(Hook) 60 | resp, err := s.client.Do(req, h) 61 | if err != nil { 62 | return nil, resp, err 63 | } 64 | 65 | return h, resp, err 66 | } 67 | 68 | // EditHook updates a specified Hook. 69 | // 70 | // GitHub API docs: https://developer.github.com/v3/orgs/hooks/#edit-a-hook 71 | func (s *OrganizationsService) EditHook(org string, id int, hook *Hook) (*Hook, *Response, error) { 72 | u := fmt.Sprintf("orgs/%v/hooks/%d", org, id) 73 | req, err := s.client.NewRequest("PATCH", u, hook) 74 | if err != nil { 75 | return nil, nil, err 76 | } 77 | h := new(Hook) 78 | resp, err := s.client.Do(req, h) 79 | return h, resp, err 80 | } 81 | 82 | // PingHook triggers a 'ping' event to be sent to the Hook. 83 | // 84 | // GitHub API docs: https://developer.github.com/v3/orgs/hooks/#ping-a-hook 85 | func (s *OrganizationsService) PingHook(org string, id int) (*Response, error) { 86 | u := fmt.Sprintf("orgs/%v/hooks/%d/pings", org, id) 87 | req, err := s.client.NewRequest("POST", u, nil) 88 | if err != nil { 89 | return nil, err 90 | } 91 | return s.client.Do(req, nil) 92 | } 93 | 94 | // DeleteHook deletes a specified Hook. 95 | // 96 | // GitHub API docs: https://developer.github.com/v3/orgs/hooks/#delete-a-hook 97 | func (s *OrganizationsService) DeleteHook(org string, id int) (*Response, error) { 98 | u := fmt.Sprintf("orgs/%v/hooks/%d", org, id) 99 | req, err := s.client.NewRequest("DELETE", u, nil) 100 | if err != nil { 101 | return nil, err 102 | } 103 | return s.client.Do(req, nil) 104 | } 105 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/repos_collaborators.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package github 7 | 8 | import "fmt" 9 | 10 | // ListCollaborators lists the Github users that have access to the repository. 11 | // 12 | // GitHub API docs: http://developer.github.com/v3/repos/collaborators/#list 13 | func (s *RepositoriesService) ListCollaborators(owner, repo string, opt *ListOptions) ([]*User, *Response, error) { 14 | u := fmt.Sprintf("repos/%v/%v/collaborators", owner, repo) 15 | u, err := addOptions(u, opt) 16 | if err != nil { 17 | return nil, nil, err 18 | } 19 | 20 | req, err := s.client.NewRequest("GET", u, nil) 21 | if err != nil { 22 | return nil, nil, err 23 | } 24 | 25 | users := new([]*User) 26 | resp, err := s.client.Do(req, users) 27 | if err != nil { 28 | return nil, resp, err 29 | } 30 | 31 | return *users, resp, err 32 | } 33 | 34 | // IsCollaborator checks whether the specified Github user has collaborator 35 | // access to the given repo. 36 | // Note: This will return false if the user is not a collaborator OR the user 37 | // is not a GitHub user. 38 | // 39 | // GitHub API docs: http://developer.github.com/v3/repos/collaborators/#get 40 | func (s *RepositoriesService) IsCollaborator(owner, repo, user string) (bool, *Response, error) { 41 | u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user) 42 | req, err := s.client.NewRequest("GET", u, nil) 43 | if err != nil { 44 | return false, nil, err 45 | } 46 | 47 | resp, err := s.client.Do(req, nil) 48 | isCollab, err := parseBoolResponse(err) 49 | return isCollab, resp, err 50 | } 51 | 52 | // RepositoryAddCollaboratorOptions specifies the optional parameters to the 53 | // RepositoriesService.AddCollaborator method. 54 | type RepositoryAddCollaboratorOptions struct { 55 | // Permission specifies the permission to grant the user on this repository. 56 | // Possible values are: 57 | // pull - team members can pull, but not push to or administer this repository 58 | // push - team members can pull and push, but not administer this repository 59 | // admin - team members can pull, push and administer this repository 60 | // 61 | // Default value is "push". This option is only valid for organization-owned repositories. 62 | Permission string `json:"permission,omitempty"` 63 | } 64 | 65 | // AddCollaborator adds the specified Github user as collaborator to the given repo. 66 | // 67 | // GitHub API docs: https://developer.github.com/v3/repos/collaborators/#add-user-as-a-collaborator 68 | func (s *RepositoriesService) AddCollaborator(owner, repo, user string, opt *RepositoryAddCollaboratorOptions) (*Response, error) { 69 | u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user) 70 | req, err := s.client.NewRequest("PUT", u, opt) 71 | if err != nil { 72 | return nil, err 73 | } 74 | 75 | // TODO: remove custom Accept header when this API fully launches. 76 | req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview) 77 | 78 | return s.client.Do(req, nil) 79 | } 80 | 81 | // RemoveCollaborator removes the specified Github user as collaborator from the given repo. 82 | // Note: Does not return error if a valid user that is not a collaborator is removed. 83 | // 84 | // GitHub API docs: http://developer.github.com/v3/repos/collaborators/#remove-collaborator 85 | func (s *RepositoriesService) RemoveCollaborator(owner, repo, user string) (*Response, error) { 86 | u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user) 87 | req, err := s.client.NewRequest("DELETE", u, nil) 88 | if err != nil { 89 | return nil, err 90 | } 91 | return s.client.Do(req, nil) 92 | } 93 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/repos_forks.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package github 7 | 8 | import "fmt" 9 | 10 | // RepositoryListForksOptions specifies the optional parameters to the 11 | // RepositoriesService.ListForks method. 12 | type RepositoryListForksOptions struct { 13 | // How to sort the forks list. Possible values are: newest, oldest, 14 | // watchers. Default is "newest". 15 | Sort string `url:"sort,omitempty"` 16 | 17 | ListOptions 18 | } 19 | 20 | // ListForks lists the forks of the specified repository. 21 | // 22 | // GitHub API docs: http://developer.github.com/v3/repos/forks/#list-forks 23 | func (s *RepositoriesService) ListForks(owner, repo string, opt *RepositoryListForksOptions) ([]*Repository, *Response, error) { 24 | u := fmt.Sprintf("repos/%v/%v/forks", owner, repo) 25 | u, err := addOptions(u, opt) 26 | if err != nil { 27 | return nil, nil, err 28 | } 29 | 30 | req, err := s.client.NewRequest("GET", u, nil) 31 | if err != nil { 32 | return nil, nil, err 33 | } 34 | 35 | repos := new([]*Repository) 36 | resp, err := s.client.Do(req, repos) 37 | if err != nil { 38 | return nil, resp, err 39 | } 40 | 41 | return *repos, resp, err 42 | } 43 | 44 | // RepositoryCreateForkOptions specifies the optional parameters to the 45 | // RepositoriesService.CreateFork method. 46 | type RepositoryCreateForkOptions struct { 47 | // The organization to fork the repository into. 48 | Organization string `url:"organization,omitempty"` 49 | } 50 | 51 | // CreateFork creates a fork of the specified repository. 52 | // 53 | // GitHub API docs: http://developer.github.com/v3/repos/forks/#list-forks 54 | func (s *RepositoriesService) CreateFork(owner, repo string, opt *RepositoryCreateForkOptions) (*Repository, *Response, error) { 55 | u := fmt.Sprintf("repos/%v/%v/forks", owner, repo) 56 | u, err := addOptions(u, opt) 57 | if err != nil { 58 | return nil, nil, err 59 | } 60 | 61 | req, err := s.client.NewRequest("POST", u, nil) 62 | if err != nil { 63 | return nil, nil, err 64 | } 65 | 66 | fork := new(Repository) 67 | resp, err := s.client.Do(req, fork) 68 | if err != nil { 69 | return nil, resp, err 70 | } 71 | 72 | return fork, resp, err 73 | } 74 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/repos_invitations.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package github 7 | 8 | import "fmt" 9 | 10 | // RepositoryInvitation represents an invitation to collaborate on a repo. 11 | type RepositoryInvitation struct { 12 | ID *int `json:"id,omitempty"` 13 | Repo *Repository `json:"repository,omitempty"` 14 | Invitee *User `json:"invitee,omitempty"` 15 | Inviter *User `json:"inviter,omitempty"` 16 | 17 | // Permissions represents the permissions that the associated user will have 18 | // on the repository. Possible values are: "read", "write", "admin". 19 | Permissions *string `json:"permissions,omitempty"` 20 | CreatedAt *Timestamp `json:"created_at,omitempty"` 21 | URL *string `json:"url,omitempty"` 22 | HTMLURL *string `json:"html_url,omitempty"` 23 | } 24 | 25 | // ListInvitations lists all currently-open repository invitations. 26 | // 27 | // GitHub API docs: https://developer.github.com/v3/repos/invitations/#list-invitations-for-a-repository 28 | func (s *RepositoriesService) ListInvitations(repoID int, opt *ListOptions) ([]*RepositoryInvitation, *Response, error) { 29 | u := fmt.Sprintf("repositories/%v/invitations", repoID) 30 | u, err := addOptions(u, opt) 31 | if err != nil { 32 | return nil, nil, err 33 | } 34 | 35 | req, err := s.client.NewRequest("GET", u, nil) 36 | if err != nil { 37 | return nil, nil, err 38 | } 39 | 40 | // TODO: remove custom Accept header when this API fully launches. 41 | req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview) 42 | 43 | invites := []*RepositoryInvitation{} 44 | resp, err := s.client.Do(req, &invites) 45 | if err != nil { 46 | return nil, resp, err 47 | } 48 | 49 | return invites, resp, err 50 | } 51 | 52 | // DeleteInvitation deletes a repository invitation. 53 | // 54 | // GitHub API docs: https://developer.github.com/v3/repos/invitations/#delete-a-repository-invitation 55 | func (s *RepositoriesService) DeleteInvitation(repoID, invitationID int) (*Response, error) { 56 | u := fmt.Sprintf("repositories/%v/invitations/%v", repoID, invitationID) 57 | req, err := s.client.NewRequest("DELETE", u, nil) 58 | if err != nil { 59 | return nil, err 60 | } 61 | 62 | // TODO: remove custom Accept header when this API fully launches. 63 | req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview) 64 | 65 | return s.client.Do(req, nil) 66 | } 67 | 68 | // UpdateInvitation updates the permissions associated with a repository 69 | // invitation. 70 | // 71 | // permissions represents the permissions that the associated user will have 72 | // on the repository. Possible values are: "read", "write", "admin". 73 | // 74 | // GitHub API docs: https://developer.github.com/v3/repos/invitations/#update-a-repository-invitation 75 | func (s *RepositoriesService) UpdateInvitation(repoID, invitationID int, permissions string) (*RepositoryInvitation, *Response, error) { 76 | opts := &struct { 77 | Permissions string `json:"permissions"` 78 | }{Permissions: permissions} 79 | u := fmt.Sprintf("repositories/%v/invitations/%v", repoID, invitationID) 80 | req, err := s.client.NewRequest("PATCH", u, opts) 81 | if err != nil { 82 | return nil, nil, err 83 | } 84 | 85 | // TODO: remove custom Accept header when this API fully launches. 86 | req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview) 87 | 88 | invite := &RepositoryInvitation{} 89 | resp, err := s.client.Do(req, invite) 90 | return invite, resp, err 91 | } 92 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/repos_keys.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package github 7 | 8 | import "fmt" 9 | 10 | // The Key type is defined in users_keys.go 11 | 12 | // ListKeys lists the deploy keys for a repository. 13 | // 14 | // GitHub API docs: http://developer.github.com/v3/repos/keys/#list 15 | func (s *RepositoriesService) ListKeys(owner string, repo string, opt *ListOptions) ([]*Key, *Response, error) { 16 | u := fmt.Sprintf("repos/%v/%v/keys", owner, repo) 17 | u, err := addOptions(u, opt) 18 | if err != nil { 19 | return nil, nil, err 20 | } 21 | 22 | req, err := s.client.NewRequest("GET", u, nil) 23 | if err != nil { 24 | return nil, nil, err 25 | } 26 | 27 | keys := new([]*Key) 28 | resp, err := s.client.Do(req, keys) 29 | if err != nil { 30 | return nil, resp, err 31 | } 32 | 33 | return *keys, resp, err 34 | } 35 | 36 | // GetKey fetches a single deploy key. 37 | // 38 | // GitHub API docs: http://developer.github.com/v3/repos/keys/#get 39 | func (s *RepositoriesService) GetKey(owner string, repo string, id int) (*Key, *Response, error) { 40 | u := fmt.Sprintf("repos/%v/%v/keys/%v", owner, repo, id) 41 | 42 | req, err := s.client.NewRequest("GET", u, nil) 43 | if err != nil { 44 | return nil, nil, err 45 | } 46 | 47 | key := new(Key) 48 | resp, err := s.client.Do(req, key) 49 | if err != nil { 50 | return nil, resp, err 51 | } 52 | 53 | return key, resp, err 54 | } 55 | 56 | // CreateKey adds a deploy key for a repository. 57 | // 58 | // GitHub API docs: http://developer.github.com/v3/repos/keys/#create 59 | func (s *RepositoriesService) CreateKey(owner string, repo string, key *Key) (*Key, *Response, error) { 60 | u := fmt.Sprintf("repos/%v/%v/keys", owner, repo) 61 | 62 | req, err := s.client.NewRequest("POST", u, key) 63 | if err != nil { 64 | return nil, nil, err 65 | } 66 | 67 | k := new(Key) 68 | resp, err := s.client.Do(req, k) 69 | if err != nil { 70 | return nil, resp, err 71 | } 72 | 73 | return k, resp, err 74 | } 75 | 76 | // EditKey edits a deploy key. 77 | // 78 | // GitHub API docs: http://developer.github.com/v3/repos/keys/#edit 79 | func (s *RepositoriesService) EditKey(owner string, repo string, id int, key *Key) (*Key, *Response, error) { 80 | u := fmt.Sprintf("repos/%v/%v/keys/%v", owner, repo, id) 81 | 82 | req, err := s.client.NewRequest("PATCH", u, key) 83 | if err != nil { 84 | return nil, nil, err 85 | } 86 | 87 | k := new(Key) 88 | resp, err := s.client.Do(req, k) 89 | if err != nil { 90 | return nil, resp, err 91 | } 92 | 93 | return k, resp, err 94 | } 95 | 96 | // DeleteKey deletes a deploy key. 97 | // 98 | // GitHub API docs: http://developer.github.com/v3/repos/keys/#delete 99 | func (s *RepositoriesService) DeleteKey(owner string, repo string, id int) (*Response, error) { 100 | u := fmt.Sprintf("repos/%v/%v/keys/%v", owner, repo, id) 101 | 102 | req, err := s.client.NewRequest("DELETE", u, nil) 103 | if err != nil { 104 | return nil, err 105 | } 106 | 107 | return s.client.Do(req, nil) 108 | } 109 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/repos_merging.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package github 7 | 8 | import ( 9 | "fmt" 10 | ) 11 | 12 | // RepositoryMergeRequest represents a request to merge a branch in a 13 | // repository. 14 | type RepositoryMergeRequest struct { 15 | Base *string `json:"base,omitempty"` 16 | Head *string `json:"head,omitempty"` 17 | CommitMessage *string `json:"commit_message,omitempty"` 18 | } 19 | 20 | // Merge a branch in the specified repository. 21 | // 22 | // GitHub API docs: https://developer.github.com/v3/repos/merging/#perform-a-merge 23 | func (s *RepositoriesService) Merge(owner, repo string, request *RepositoryMergeRequest) (*RepositoryCommit, *Response, error) { 24 | u := fmt.Sprintf("repos/%v/%v/merges", owner, repo) 25 | req, err := s.client.NewRequest("POST", u, request) 26 | if err != nil { 27 | return nil, nil, err 28 | } 29 | 30 | commit := new(RepositoryCommit) 31 | resp, err := s.client.Do(req, commit) 32 | if err != nil { 33 | return nil, resp, err 34 | } 35 | 36 | return commit, resp, err 37 | } 38 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/repos_pages.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package github 7 | 8 | import "fmt" 9 | 10 | // Pages represents a GitHub Pages site configuration. 11 | type Pages struct { 12 | URL *string `json:"url,omitempty"` 13 | Status *string `json:"status,omitempty"` 14 | CNAME *string `json:"cname,omitempty"` 15 | Custom404 *bool `json:"custom_404,omitempty"` 16 | HTMLURL *string `json:"html_url,omitempty"` 17 | } 18 | 19 | // PagesError represents a build error for a GitHub Pages site. 20 | type PagesError struct { 21 | Message *string `json:"message,omitempty"` 22 | } 23 | 24 | // PagesBuild represents the build information for a GitHub Pages site. 25 | type PagesBuild struct { 26 | URL *string `json:"url,omitempty"` 27 | Status *string `json:"status,omitempty"` 28 | Error *PagesError `json:"error,omitempty"` 29 | Pusher *User `json:"pusher,omitempty"` 30 | Commit *string `json:"commit,omitempty"` 31 | Duration *int `json:"duration,omitempty"` 32 | CreatedAt *Timestamp `json:"created_at,omitempty"` 33 | UpdatedAt *Timestamp `json:"created_at,omitempty"` 34 | } 35 | 36 | // GetPagesInfo fetches information about a GitHub Pages site. 37 | // 38 | // GitHub API docs: https://developer.github.com/v3/repos/pages/#get-information-about-a-pages-site 39 | func (s *RepositoriesService) GetPagesInfo(owner string, repo string) (*Pages, *Response, error) { 40 | u := fmt.Sprintf("repos/%v/%v/pages", owner, repo) 41 | req, err := s.client.NewRequest("GET", u, nil) 42 | if err != nil { 43 | return nil, nil, err 44 | } 45 | 46 | // TODO: remove custom Accept header when this API fully launches. 47 | req.Header.Set("Accept", mediaTypePagesPreview) 48 | 49 | site := new(Pages) 50 | resp, err := s.client.Do(req, site) 51 | if err != nil { 52 | return nil, resp, err 53 | } 54 | 55 | return site, resp, err 56 | } 57 | 58 | // ListPagesBuilds lists the builds for a GitHub Pages site. 59 | // 60 | // GitHub API docs: https://developer.github.com/v3/repos/pages/#list-pages-builds 61 | func (s *RepositoriesService) ListPagesBuilds(owner string, repo string) ([]*PagesBuild, *Response, error) { 62 | u := fmt.Sprintf("repos/%v/%v/pages/builds", owner, repo) 63 | req, err := s.client.NewRequest("GET", u, nil) 64 | if err != nil { 65 | return nil, nil, err 66 | } 67 | 68 | var pages []*PagesBuild 69 | resp, err := s.client.Do(req, &pages) 70 | if err != nil { 71 | return nil, resp, err 72 | } 73 | 74 | return pages, resp, err 75 | } 76 | 77 | // GetLatestPagesBuild fetches the latest build information for a GitHub pages site. 78 | // 79 | // GitHub API docs: https://developer.github.com/v3/repos/pages/#list-latest-pages-build 80 | func (s *RepositoriesService) GetLatestPagesBuild(owner string, repo string) (*PagesBuild, *Response, error) { 81 | u := fmt.Sprintf("repos/%v/%v/pages/builds/latest", owner, repo) 82 | req, err := s.client.NewRequest("GET", u, nil) 83 | if err != nil { 84 | return nil, nil, err 85 | } 86 | 87 | build := new(PagesBuild) 88 | resp, err := s.client.Do(req, build) 89 | if err != nil { 90 | return nil, resp, err 91 | } 92 | 93 | return build, resp, err 94 | } 95 | 96 | // RequestPageBuild requests a build of a GitHub Pages site without needing to push new commit. 97 | // 98 | // GitHub API docs: https://developer.github.com/v3/repos/pages/#request-a-page-build 99 | func (s *RepositoriesService) RequestPageBuild(owner string, repo string) (*PagesBuild, *Response, error) { 100 | u := fmt.Sprintf("repos/%v/%v/pages/builds", owner, repo) 101 | req, err := s.client.NewRequest("POST", u, nil) 102 | if err != nil { 103 | return nil, nil, err 104 | } 105 | 106 | // TODO: remove custom Accept header when this API fully launches. 107 | req.Header.Set("Accept", mediaTypePagesPreview) 108 | 109 | build := new(PagesBuild) 110 | resp, err := s.client.Do(req, build) 111 | if err != nil { 112 | return nil, resp, err 113 | } 114 | 115 | return build, resp, err 116 | } 117 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/repos_statuses.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package github 7 | 8 | import ( 9 | "fmt" 10 | "time" 11 | ) 12 | 13 | // RepoStatus represents the status of a repository at a particular reference. 14 | type RepoStatus struct { 15 | ID *int `json:"id,omitempty"` 16 | URL *string `json:"url,omitempty"` 17 | 18 | // State is the current state of the repository. Possible values are: 19 | // pending, success, error, or failure. 20 | State *string `json:"state,omitempty"` 21 | 22 | // TargetURL is the URL of the page representing this status. It will be 23 | // linked from the GitHub UI to allow users to see the source of the status. 24 | TargetURL *string `json:"target_url,omitempty"` 25 | 26 | // Description is a short high level summary of the status. 27 | Description *string `json:"description,omitempty"` 28 | 29 | // A string label to differentiate this status from the statuses of other systems. 30 | Context *string `json:"context,omitempty"` 31 | 32 | Creator *User `json:"creator,omitempty"` 33 | CreatedAt *time.Time `json:"created_at,omitempty"` 34 | UpdatedAt *time.Time `json:"updated_at,omitempty"` 35 | } 36 | 37 | func (r RepoStatus) String() string { 38 | return Stringify(r) 39 | } 40 | 41 | // ListStatuses lists the statuses of a repository at the specified 42 | // reference. ref can be a SHA, a branch name, or a tag name. 43 | // 44 | // GitHub API docs: http://developer.github.com/v3/repos/statuses/#list-statuses-for-a-specific-ref 45 | func (s *RepositoriesService) ListStatuses(owner, repo, ref string, opt *ListOptions) ([]*RepoStatus, *Response, error) { 46 | u := fmt.Sprintf("repos/%v/%v/commits/%v/statuses", owner, repo, ref) 47 | u, err := addOptions(u, opt) 48 | if err != nil { 49 | return nil, nil, err 50 | } 51 | 52 | req, err := s.client.NewRequest("GET", u, nil) 53 | if err != nil { 54 | return nil, nil, err 55 | } 56 | 57 | statuses := new([]*RepoStatus) 58 | resp, err := s.client.Do(req, statuses) 59 | if err != nil { 60 | return nil, resp, err 61 | } 62 | 63 | return *statuses, resp, err 64 | } 65 | 66 | // CreateStatus creates a new status for a repository at the specified 67 | // reference. Ref can be a SHA, a branch name, or a tag name. 68 | // 69 | // GitHub API docs: http://developer.github.com/v3/repos/statuses/#create-a-status 70 | func (s *RepositoriesService) CreateStatus(owner, repo, ref string, status *RepoStatus) (*RepoStatus, *Response, error) { 71 | u := fmt.Sprintf("repos/%v/%v/statuses/%v", owner, repo, ref) 72 | req, err := s.client.NewRequest("POST", u, status) 73 | if err != nil { 74 | return nil, nil, err 75 | } 76 | 77 | repoStatus := new(RepoStatus) 78 | resp, err := s.client.Do(req, repoStatus) 79 | if err != nil { 80 | return nil, resp, err 81 | } 82 | 83 | return repoStatus, resp, err 84 | } 85 | 86 | // CombinedStatus represents the combined status of a repository at a particular reference. 87 | type CombinedStatus struct { 88 | // State is the combined state of the repository. Possible values are: 89 | // failure, pending, or success. 90 | State *string `json:"state,omitempty"` 91 | 92 | Name *string `json:"name,omitempty"` 93 | SHA *string `json:"sha,omitempty"` 94 | TotalCount *int `json:"total_count,omitempty"` 95 | Statuses []RepoStatus `json:"statuses,omitempty"` 96 | 97 | CommitURL *string `json:"commit_url,omitempty"` 98 | RepositoryURL *string `json:"repository_url,omitempty"` 99 | } 100 | 101 | func (s CombinedStatus) String() string { 102 | return Stringify(s) 103 | } 104 | 105 | // GetCombinedStatus returns the combined status of a repository at the specified 106 | // reference. ref can be a SHA, a branch name, or a tag name. 107 | // 108 | // GitHub API docs: https://developer.github.com/v3/repos/statuses/#get-the-combined-status-for-a-specific-ref 109 | func (s *RepositoriesService) GetCombinedStatus(owner, repo, ref string, opt *ListOptions) (*CombinedStatus, *Response, error) { 110 | u := fmt.Sprintf("repos/%v/%v/commits/%v/status", owner, repo, ref) 111 | u, err := addOptions(u, opt) 112 | if err != nil { 113 | return nil, nil, err 114 | } 115 | 116 | req, err := s.client.NewRequest("GET", u, nil) 117 | if err != nil { 118 | return nil, nil, err 119 | } 120 | 121 | status := new(CombinedStatus) 122 | resp, err := s.client.Do(req, status) 123 | if err != nil { 124 | return nil, resp, err 125 | } 126 | 127 | return status, resp, err 128 | } 129 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/strings.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package github 7 | 8 | import ( 9 | "bytes" 10 | "fmt" 11 | "io" 12 | 13 | "reflect" 14 | ) 15 | 16 | var timestampType = reflect.TypeOf(Timestamp{}) 17 | 18 | // Stringify attempts to create a reasonable string representation of types in 19 | // the GitHub library. It does things like resolve pointers to their values 20 | // and omits struct fields with nil values. 21 | func Stringify(message interface{}) string { 22 | var buf bytes.Buffer 23 | v := reflect.ValueOf(message) 24 | stringifyValue(&buf, v) 25 | return buf.String() 26 | } 27 | 28 | // stringifyValue was heavily inspired by the goprotobuf library. 29 | 30 | func stringifyValue(w io.Writer, val reflect.Value) { 31 | if val.Kind() == reflect.Ptr && val.IsNil() { 32 | w.Write([]byte("")) 33 | return 34 | } 35 | 36 | v := reflect.Indirect(val) 37 | 38 | switch v.Kind() { 39 | case reflect.String: 40 | fmt.Fprintf(w, `"%s"`, v) 41 | case reflect.Slice: 42 | w.Write([]byte{'['}) 43 | for i := 0; i < v.Len(); i++ { 44 | if i > 0 { 45 | w.Write([]byte{' '}) 46 | } 47 | 48 | stringifyValue(w, v.Index(i)) 49 | } 50 | 51 | w.Write([]byte{']'}) 52 | return 53 | case reflect.Struct: 54 | if v.Type().Name() != "" { 55 | w.Write([]byte(v.Type().String())) 56 | } 57 | 58 | // special handling of Timestamp values 59 | if v.Type() == timestampType { 60 | fmt.Fprintf(w, "{%s}", v.Interface()) 61 | return 62 | } 63 | 64 | w.Write([]byte{'{'}) 65 | 66 | var sep bool 67 | for i := 0; i < v.NumField(); i++ { 68 | fv := v.Field(i) 69 | if fv.Kind() == reflect.Ptr && fv.IsNil() { 70 | continue 71 | } 72 | if fv.Kind() == reflect.Slice && fv.IsNil() { 73 | continue 74 | } 75 | 76 | if sep { 77 | w.Write([]byte(", ")) 78 | } else { 79 | sep = true 80 | } 81 | 82 | w.Write([]byte(v.Type().Field(i).Name)) 83 | w.Write([]byte{':'}) 84 | stringifyValue(w, fv) 85 | } 86 | 87 | w.Write([]byte{'}'}) 88 | default: 89 | if v.CanInterface() { 90 | fmt.Fprint(w, v.Interface()) 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/timestamp.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package github 7 | 8 | import ( 9 | "strconv" 10 | "time" 11 | ) 12 | 13 | // Timestamp represents a time that can be unmarshalled from a JSON string 14 | // formatted as either an RFC3339 or Unix timestamp. This is necessary for some 15 | // fields since the GitHub API is inconsistent in how it represents times. All 16 | // exported methods of time.Time can be called on Timestamp. 17 | type Timestamp struct { 18 | time.Time 19 | } 20 | 21 | func (t Timestamp) String() string { 22 | return t.Time.String() 23 | } 24 | 25 | // UnmarshalJSON implements the json.Unmarshaler interface. 26 | // Time is expected in RFC3339 or Unix format. 27 | func (t *Timestamp) UnmarshalJSON(data []byte) (err error) { 28 | str := string(data) 29 | i, err := strconv.ParseInt(str, 10, 64) 30 | if err == nil { 31 | (*t).Time = time.Unix(i, 0) 32 | } else { 33 | (*t).Time, err = time.Parse(`"`+time.RFC3339+`"`, str) 34 | } 35 | return 36 | } 37 | 38 | // Equal reports whether t and u are equal based on time.Equal 39 | func (t Timestamp) Equal(u Timestamp) bool { 40 | return t.Time.Equal(u.Time) 41 | } 42 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/users_administration.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package github 7 | 8 | import "fmt" 9 | 10 | // PromoteSiteAdmin promotes a user to a site administrator of a GitHub Enterprise instance. 11 | // 12 | // GitHub API docs: https://developer.github.com/v3/users/administration/#promote-an-ordinary-user-to-a-site-administrator 13 | func (s *UsersService) PromoteSiteAdmin(user string) (*Response, error) { 14 | u := fmt.Sprintf("users/%v/site_admin", user) 15 | 16 | req, err := s.client.NewRequest("PUT", u, nil) 17 | if err != nil { 18 | return nil, err 19 | } 20 | 21 | return s.client.Do(req, nil) 22 | } 23 | 24 | // DemoteSiteAdmin demotes a user from site administrator of a GitHub Enterprise instance. 25 | // 26 | // GitHub API docs: https://developer.github.com/v3/users/administration/#demote-a-site-administrator-to-an-ordinary-user 27 | func (s *UsersService) DemoteSiteAdmin(user string) (*Response, error) { 28 | u := fmt.Sprintf("users/%v/site_admin", user) 29 | 30 | req, err := s.client.NewRequest("DELETE", u, nil) 31 | if err != nil { 32 | return nil, err 33 | } 34 | 35 | return s.client.Do(req, nil) 36 | } 37 | 38 | // Suspend a user on a GitHub Enterprise instance. 39 | // 40 | // GitHub API docs: https://developer.github.com/v3/users/administration/#suspend-a-user 41 | func (s *UsersService) Suspend(user string) (*Response, error) { 42 | u := fmt.Sprintf("users/%v/suspended", user) 43 | 44 | req, err := s.client.NewRequest("PUT", u, nil) 45 | if err != nil { 46 | return nil, err 47 | } 48 | 49 | return s.client.Do(req, nil) 50 | } 51 | 52 | // Unsuspend a user on a GitHub Enterprise instance. 53 | // 54 | // GitHub API docs: https://developer.github.com/v3/users/administration/#unsuspend-a-user 55 | func (s *UsersService) Unsuspend(user string) (*Response, error) { 56 | u := fmt.Sprintf("users/%v/suspended", user) 57 | 58 | req, err := s.client.NewRequest("DELETE", u, nil) 59 | if err != nil { 60 | return nil, err 61 | } 62 | 63 | return s.client.Do(req, nil) 64 | } 65 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/users_emails.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package github 7 | 8 | // UserEmail represents user's email address 9 | type UserEmail struct { 10 | Email *string `json:"email,omitempty"` 11 | Primary *bool `json:"primary,omitempty"` 12 | Verified *bool `json:"verified,omitempty"` 13 | } 14 | 15 | // ListEmails lists all email addresses for the authenticated user. 16 | // 17 | // GitHub API docs: http://developer.github.com/v3/users/emails/#list-email-addresses-for-a-user 18 | func (s *UsersService) ListEmails(opt *ListOptions) ([]*UserEmail, *Response, error) { 19 | u := "user/emails" 20 | u, err := addOptions(u, opt) 21 | if err != nil { 22 | return nil, nil, err 23 | } 24 | 25 | req, err := s.client.NewRequest("GET", u, nil) 26 | if err != nil { 27 | return nil, nil, err 28 | } 29 | 30 | emails := new([]*UserEmail) 31 | resp, err := s.client.Do(req, emails) 32 | if err != nil { 33 | return nil, resp, err 34 | } 35 | 36 | return *emails, resp, err 37 | } 38 | 39 | // AddEmails adds email addresses of the authenticated user. 40 | // 41 | // GitHub API docs: http://developer.github.com/v3/users/emails/#add-email-addresses 42 | func (s *UsersService) AddEmails(emails []string) ([]*UserEmail, *Response, error) { 43 | u := "user/emails" 44 | req, err := s.client.NewRequest("POST", u, emails) 45 | if err != nil { 46 | return nil, nil, err 47 | } 48 | 49 | e := new([]*UserEmail) 50 | resp, err := s.client.Do(req, e) 51 | if err != nil { 52 | return nil, resp, err 53 | } 54 | 55 | return *e, resp, err 56 | } 57 | 58 | // DeleteEmails deletes email addresses from authenticated user. 59 | // 60 | // GitHub API docs: http://developer.github.com/v3/users/emails/#delete-email-addresses 61 | func (s *UsersService) DeleteEmails(emails []string) (*Response, error) { 62 | u := "user/emails" 63 | req, err := s.client.NewRequest("DELETE", u, emails) 64 | if err != nil { 65 | return nil, err 66 | } 67 | 68 | return s.client.Do(req, nil) 69 | } 70 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/users_followers.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package github 7 | 8 | import "fmt" 9 | 10 | // ListFollowers lists the followers for a user. Passing the empty string will 11 | // fetch followers for the authenticated user. 12 | // 13 | // GitHub API docs: http://developer.github.com/v3/users/followers/#list-followers-of-a-user 14 | func (s *UsersService) ListFollowers(user string, opt *ListOptions) ([]*User, *Response, error) { 15 | var u string 16 | if user != "" { 17 | u = fmt.Sprintf("users/%v/followers", user) 18 | } else { 19 | u = "user/followers" 20 | } 21 | u, err := addOptions(u, opt) 22 | if err != nil { 23 | return nil, nil, err 24 | } 25 | 26 | req, err := s.client.NewRequest("GET", u, nil) 27 | if err != nil { 28 | return nil, nil, err 29 | } 30 | 31 | users := new([]*User) 32 | resp, err := s.client.Do(req, users) 33 | if err != nil { 34 | return nil, resp, err 35 | } 36 | 37 | return *users, resp, err 38 | } 39 | 40 | // ListFollowing lists the people that a user is following. Passing the empty 41 | // string will list people the authenticated user is following. 42 | // 43 | // GitHub API docs: http://developer.github.com/v3/users/followers/#list-users-followed-by-another-user 44 | func (s *UsersService) ListFollowing(user string, opt *ListOptions) ([]*User, *Response, error) { 45 | var u string 46 | if user != "" { 47 | u = fmt.Sprintf("users/%v/following", user) 48 | } else { 49 | u = "user/following" 50 | } 51 | u, err := addOptions(u, opt) 52 | if err != nil { 53 | return nil, nil, err 54 | } 55 | 56 | req, err := s.client.NewRequest("GET", u, nil) 57 | if err != nil { 58 | return nil, nil, err 59 | } 60 | 61 | users := new([]*User) 62 | resp, err := s.client.Do(req, users) 63 | if err != nil { 64 | return nil, resp, err 65 | } 66 | 67 | return *users, resp, err 68 | } 69 | 70 | // IsFollowing checks if "user" is following "target". Passing the empty 71 | // string for "user" will check if the authenticated user is following "target". 72 | // 73 | // GitHub API docs: http://developer.github.com/v3/users/followers/#check-if-you-are-following-a-user 74 | func (s *UsersService) IsFollowing(user, target string) (bool, *Response, error) { 75 | var u string 76 | if user != "" { 77 | u = fmt.Sprintf("users/%v/following/%v", user, target) 78 | } else { 79 | u = fmt.Sprintf("user/following/%v", target) 80 | } 81 | 82 | req, err := s.client.NewRequest("GET", u, nil) 83 | if err != nil { 84 | return false, nil, err 85 | } 86 | 87 | resp, err := s.client.Do(req, nil) 88 | following, err := parseBoolResponse(err) 89 | return following, resp, err 90 | } 91 | 92 | // Follow will cause the authenticated user to follow the specified user. 93 | // 94 | // GitHub API docs: http://developer.github.com/v3/users/followers/#follow-a-user 95 | func (s *UsersService) Follow(user string) (*Response, error) { 96 | u := fmt.Sprintf("user/following/%v", user) 97 | req, err := s.client.NewRequest("PUT", u, nil) 98 | if err != nil { 99 | return nil, err 100 | } 101 | 102 | return s.client.Do(req, nil) 103 | } 104 | 105 | // Unfollow will cause the authenticated user to unfollow the specified user. 106 | // 107 | // GitHub API docs: http://developer.github.com/v3/users/followers/#unfollow-a-user 108 | func (s *UsersService) Unfollow(user string) (*Response, error) { 109 | u := fmt.Sprintf("user/following/%v", user) 110 | req, err := s.client.NewRequest("DELETE", u, nil) 111 | if err != nil { 112 | return nil, err 113 | } 114 | 115 | return s.client.Do(req, nil) 116 | } 117 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/users_gpg_keys.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package github 7 | 8 | import ( 9 | "fmt" 10 | "time" 11 | ) 12 | 13 | // GPGKey represents a GitHub user's public GPG key used to verify GPG signed commits and tags. 14 | // 15 | // https://developer.github.com/changes/2016-04-04-git-signing-api-preview/ 16 | type GPGKey struct { 17 | ID *int `json:"id,omitempty"` 18 | PrimaryKeyID *int `json:"primary_key_id,omitempty"` 19 | KeyID *string `json:"key_id,omitempty"` 20 | PublicKey *string `json:"public_key,omitempty"` 21 | Emails []GPGEmail `json:"emails,omitempty"` 22 | Subkeys []GPGKey `json:"subkeys,omitempty"` 23 | CanSign *bool `json:"can_sign,omitempty"` 24 | CanEncryptComms *bool `json:"can_encrypt_comms,omitempty"` 25 | CanEncryptStorage *bool `json:"can_encrypt_storage,omitempty"` 26 | CanCertify *bool `json:"can_certify,omitempty"` 27 | CreatedAt *time.Time `json:"created_at,omitempty"` 28 | ExpiresAt *time.Time `json:"expires_at,omitempty"` 29 | } 30 | 31 | // String stringifies a GPGKey. 32 | func (k GPGKey) String() string { 33 | return Stringify(k) 34 | } 35 | 36 | // GPGEmail represents an email address associated to a GPG key. 37 | type GPGEmail struct { 38 | Email *string `json:"email,omitempty"` 39 | Verified *bool `json:"verified,omitempty"` 40 | } 41 | 42 | // ListGPGKeys lists the current user's GPG keys. It requires authentication 43 | // via Basic Auth or via OAuth with at least read:gpg_key scope. 44 | // 45 | // GitHub API docs: https://developer.github.com/v3/users/gpg_keys/#list-your-gpg-keys 46 | func (s *UsersService) ListGPGKeys() ([]*GPGKey, *Response, error) { 47 | req, err := s.client.NewRequest("GET", "user/gpg_keys", nil) 48 | if err != nil { 49 | return nil, nil, err 50 | } 51 | 52 | // TODO: remove custom Accept header when this API fully launches. 53 | req.Header.Set("Accept", mediaTypeGitSigningPreview) 54 | 55 | var keys []*GPGKey 56 | resp, err := s.client.Do(req, &keys) 57 | if err != nil { 58 | return nil, resp, err 59 | } 60 | 61 | return keys, resp, err 62 | } 63 | 64 | // GetGPGKey gets extended details for a single GPG key. It requires authentication 65 | // via Basic Auth or via OAuth with at least read:gpg_key scope. 66 | // 67 | // GitHub API docs: https://developer.github.com/v3/users/gpg_keys/#get-a-single-gpg-key 68 | func (s *UsersService) GetGPGKey(id int) (*GPGKey, *Response, error) { 69 | u := fmt.Sprintf("user/gpg_keys/%v", id) 70 | req, err := s.client.NewRequest("GET", u, nil) 71 | if err != nil { 72 | return nil, nil, err 73 | } 74 | 75 | // TODO: remove custom Accept header when this API fully launches. 76 | req.Header.Set("Accept", mediaTypeGitSigningPreview) 77 | 78 | key := &GPGKey{} 79 | resp, err := s.client.Do(req, key) 80 | if err != nil { 81 | return nil, resp, err 82 | } 83 | 84 | return key, resp, err 85 | } 86 | 87 | // CreateGPGKey creates a GPG key. It requires authenticatation via Basic Auth 88 | // or OAuth with at least write:gpg_key scope. 89 | // 90 | // GitHub API docs: https://developer.github.com/v3/users/gpg_keys/#create-a-gpg-key 91 | func (s *UsersService) CreateGPGKey(armoredPublicKey string) (*GPGKey, *Response, error) { 92 | gpgKey := &struct { 93 | ArmoredPublicKey string `json:"armored_public_key"` 94 | }{ArmoredPublicKey: armoredPublicKey} 95 | req, err := s.client.NewRequest("POST", "user/gpg_keys", gpgKey) 96 | if err != nil { 97 | return nil, nil, err 98 | } 99 | 100 | // TODO: remove custom Accept header when this API fully launches. 101 | req.Header.Set("Accept", mediaTypeGitSigningPreview) 102 | 103 | key := &GPGKey{} 104 | resp, err := s.client.Do(req, key) 105 | if err != nil { 106 | return nil, resp, err 107 | } 108 | 109 | return key, resp, err 110 | } 111 | 112 | // DeleteGPGKey deletes a GPG key. It requires authentication via Basic Auth or 113 | // via OAuth with at least admin:gpg_key scope. 114 | // 115 | // GitHub API docs: https://developer.github.com/v3/users/gpg_keys/#delete-a-gpg-key 116 | func (s *UsersService) DeleteGPGKey(id int) (*Response, error) { 117 | u := fmt.Sprintf("user/gpg_keys/%v", id) 118 | req, err := s.client.NewRequest("DELETE", u, nil) 119 | if err != nil { 120 | return nil, err 121 | } 122 | 123 | // TODO: remove custom Accept header when this API fully launches. 124 | req.Header.Set("Accept", mediaTypeGitSigningPreview) 125 | 126 | return s.client.Do(req, nil) 127 | } 128 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-github/github/users_keys.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The go-github AUTHORS. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package github 7 | 8 | import "fmt" 9 | 10 | // Key represents a public SSH key used to authenticate a user or deploy script. 11 | type Key struct { 12 | ID *int `json:"id,omitempty"` 13 | Key *string `json:"key,omitempty"` 14 | URL *string `json:"url,omitempty"` 15 | Title *string `json:"title,omitempty"` 16 | ReadOnly *bool `json:"read_only,omitempty"` 17 | } 18 | 19 | func (k Key) String() string { 20 | return Stringify(k) 21 | } 22 | 23 | // ListKeys lists the verified public keys for a user. Passing the empty 24 | // string will fetch keys for the authenticated user. 25 | // 26 | // GitHub API docs: http://developer.github.com/v3/users/keys/#list-public-keys-for-a-user 27 | func (s *UsersService) ListKeys(user string, opt *ListOptions) ([]*Key, *Response, error) { 28 | var u string 29 | if user != "" { 30 | u = fmt.Sprintf("users/%v/keys", user) 31 | } else { 32 | u = "user/keys" 33 | } 34 | u, err := addOptions(u, opt) 35 | if err != nil { 36 | return nil, nil, err 37 | } 38 | 39 | req, err := s.client.NewRequest("GET", u, nil) 40 | if err != nil { 41 | return nil, nil, err 42 | } 43 | 44 | keys := new([]*Key) 45 | resp, err := s.client.Do(req, keys) 46 | if err != nil { 47 | return nil, resp, err 48 | } 49 | 50 | return *keys, resp, err 51 | } 52 | 53 | // GetKey fetches a single public key. 54 | // 55 | // GitHub API docs: http://developer.github.com/v3/users/keys/#get-a-single-public-key 56 | func (s *UsersService) GetKey(id int) (*Key, *Response, error) { 57 | u := fmt.Sprintf("user/keys/%v", id) 58 | 59 | req, err := s.client.NewRequest("GET", u, nil) 60 | if err != nil { 61 | return nil, nil, err 62 | } 63 | 64 | key := new(Key) 65 | resp, err := s.client.Do(req, key) 66 | if err != nil { 67 | return nil, resp, err 68 | } 69 | 70 | return key, resp, err 71 | } 72 | 73 | // CreateKey adds a public key for the authenticated user. 74 | // 75 | // GitHub API docs: http://developer.github.com/v3/users/keys/#create-a-public-key 76 | func (s *UsersService) CreateKey(key *Key) (*Key, *Response, error) { 77 | u := "user/keys" 78 | 79 | req, err := s.client.NewRequest("POST", u, key) 80 | if err != nil { 81 | return nil, nil, err 82 | } 83 | 84 | k := new(Key) 85 | resp, err := s.client.Do(req, k) 86 | if err != nil { 87 | return nil, resp, err 88 | } 89 | 90 | return k, resp, err 91 | } 92 | 93 | // DeleteKey deletes a public key. 94 | // 95 | // GitHub API docs: http://developer.github.com/v3/users/keys/#delete-a-public-key 96 | func (s *UsersService) DeleteKey(id int) (*Response, error) { 97 | u := fmt.Sprintf("user/keys/%v", id) 98 | 99 | req, err := s.client.NewRequest("DELETE", u, nil) 100 | if err != nil { 101 | return nil, err 102 | } 103 | 104 | return s.client.Do(req, nil) 105 | } 106 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-querystring/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Google. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/context/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | 4 | matrix: 5 | include: 6 | - go: 1.3 7 | - go: 1.4 8 | - go: 1.5 9 | - go: 1.6 10 | - go: 1.7 11 | - go: tip 12 | allow_failures: 13 | - go: tip 14 | 15 | script: 16 | - go get -t -v ./... 17 | - diff -u <(echo -n) <(gofmt -d .) 18 | - go vet $(go list ./... | grep -v /vendor/) 19 | - go test -v -race ./... 20 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/context/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Rodrigo Moraes. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/context/README.md: -------------------------------------------------------------------------------- 1 | context 2 | ======= 3 | [![Build Status](https://travis-ci.org/gorilla/context.png?branch=master)](https://travis-ci.org/gorilla/context) 4 | 5 | gorilla/context is a general purpose registry for global request variables. 6 | 7 | > Note: gorilla/context, having been born well before `context.Context` existed, does not play well 8 | > with the shallow copying of the request that [`http.Request.WithContext`](https://golang.org/pkg/net/http/#Request.WithContext) (added to net/http Go 1.7 onwards) performs. You should either use *just* gorilla/context, or moving forward, the new `http.Request.Context()`. 9 | 10 | Read the full documentation here: http://www.gorillatoolkit.org/pkg/context 11 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/context/context.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Gorilla Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package context 6 | 7 | import ( 8 | "net/http" 9 | "sync" 10 | "time" 11 | ) 12 | 13 | var ( 14 | mutex sync.RWMutex 15 | data = make(map[*http.Request]map[interface{}]interface{}) 16 | datat = make(map[*http.Request]int64) 17 | ) 18 | 19 | // Set stores a value for a given key in a given request. 20 | func Set(r *http.Request, key, val interface{}) { 21 | mutex.Lock() 22 | if data[r] == nil { 23 | data[r] = make(map[interface{}]interface{}) 24 | datat[r] = time.Now().Unix() 25 | } 26 | data[r][key] = val 27 | mutex.Unlock() 28 | } 29 | 30 | // Get returns a value stored for a given key in a given request. 31 | func Get(r *http.Request, key interface{}) interface{} { 32 | mutex.RLock() 33 | if ctx := data[r]; ctx != nil { 34 | value := ctx[key] 35 | mutex.RUnlock() 36 | return value 37 | } 38 | mutex.RUnlock() 39 | return nil 40 | } 41 | 42 | // GetOk returns stored value and presence state like multi-value return of map access. 43 | func GetOk(r *http.Request, key interface{}) (interface{}, bool) { 44 | mutex.RLock() 45 | if _, ok := data[r]; ok { 46 | value, ok := data[r][key] 47 | mutex.RUnlock() 48 | return value, ok 49 | } 50 | mutex.RUnlock() 51 | return nil, false 52 | } 53 | 54 | // GetAll returns all stored values for the request as a map. Nil is returned for invalid requests. 55 | func GetAll(r *http.Request) map[interface{}]interface{} { 56 | mutex.RLock() 57 | if context, ok := data[r]; ok { 58 | result := make(map[interface{}]interface{}, len(context)) 59 | for k, v := range context { 60 | result[k] = v 61 | } 62 | mutex.RUnlock() 63 | return result 64 | } 65 | mutex.RUnlock() 66 | return nil 67 | } 68 | 69 | // GetAllOk returns all stored values for the request as a map and a boolean value that indicates if 70 | // the request was registered. 71 | func GetAllOk(r *http.Request) (map[interface{}]interface{}, bool) { 72 | mutex.RLock() 73 | context, ok := data[r] 74 | result := make(map[interface{}]interface{}, len(context)) 75 | for k, v := range context { 76 | result[k] = v 77 | } 78 | mutex.RUnlock() 79 | return result, ok 80 | } 81 | 82 | // Delete removes a value stored for a given key in a given request. 83 | func Delete(r *http.Request, key interface{}) { 84 | mutex.Lock() 85 | if data[r] != nil { 86 | delete(data[r], key) 87 | } 88 | mutex.Unlock() 89 | } 90 | 91 | // Clear removes all values stored for a given request. 92 | // 93 | // This is usually called by a handler wrapper to clean up request 94 | // variables at the end of a request lifetime. See ClearHandler(). 95 | func Clear(r *http.Request) { 96 | mutex.Lock() 97 | clear(r) 98 | mutex.Unlock() 99 | } 100 | 101 | // clear is Clear without the lock. 102 | func clear(r *http.Request) { 103 | delete(data, r) 104 | delete(datat, r) 105 | } 106 | 107 | // Purge removes request data stored for longer than maxAge, in seconds. 108 | // It returns the amount of requests removed. 109 | // 110 | // If maxAge <= 0, all request data is removed. 111 | // 112 | // This is only used for sanity check: in case context cleaning was not 113 | // properly set some request data can be kept forever, consuming an increasing 114 | // amount of memory. In case this is detected, Purge() must be called 115 | // periodically until the problem is fixed. 116 | func Purge(maxAge int) int { 117 | mutex.Lock() 118 | count := 0 119 | if maxAge <= 0 { 120 | count = len(data) 121 | data = make(map[*http.Request]map[interface{}]interface{}) 122 | datat = make(map[*http.Request]int64) 123 | } else { 124 | min := time.Now().Unix() - int64(maxAge) 125 | for r := range data { 126 | if datat[r] < min { 127 | clear(r) 128 | count++ 129 | } 130 | } 131 | } 132 | mutex.Unlock() 133 | return count 134 | } 135 | 136 | // ClearHandler wraps an http.Handler and clears request values at the end 137 | // of a request lifetime. 138 | func ClearHandler(h http.Handler) http.Handler { 139 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 140 | defer Clear(r) 141 | h.ServeHTTP(w, r) 142 | }) 143 | } 144 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/context/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Gorilla Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | /* 6 | Package context stores values shared during a request lifetime. 7 | 8 | Note: gorilla/context, having been born well before `context.Context` existed, 9 | does not play well > with the shallow copying of the request that 10 | [`http.Request.WithContext`](https://golang.org/pkg/net/http/#Request.WithContext) 11 | (added to net/http Go 1.7 onwards) performs. You should either use *just* 12 | gorilla/context, or moving forward, the new `http.Request.Context()`. 13 | 14 | For example, a router can set variables extracted from the URL and later 15 | application handlers can access those values, or it can be used to store 16 | sessions values to be saved at the end of a request. There are several 17 | others common uses. 18 | 19 | The idea was posted by Brad Fitzpatrick to the go-nuts mailing list: 20 | 21 | http://groups.google.com/group/golang-nuts/msg/e2d679d303aa5d53 22 | 23 | Here's the basic usage: first define the keys that you will need. The key 24 | type is interface{} so a key can be of any type that supports equality. 25 | Here we define a key using a custom int type to avoid name collisions: 26 | 27 | package foo 28 | 29 | import ( 30 | "github.com/gorilla/context" 31 | ) 32 | 33 | type key int 34 | 35 | const MyKey key = 0 36 | 37 | Then set a variable. Variables are bound to an http.Request object, so you 38 | need a request instance to set a value: 39 | 40 | context.Set(r, MyKey, "bar") 41 | 42 | The application can later access the variable using the same key you provided: 43 | 44 | func MyHandler(w http.ResponseWriter, r *http.Request) { 45 | // val is "bar". 46 | val := context.Get(r, foo.MyKey) 47 | 48 | // returns ("bar", true) 49 | val, ok := context.GetOk(r, foo.MyKey) 50 | // ... 51 | } 52 | 53 | And that's all about the basic usage. We discuss some other ideas below. 54 | 55 | Any type can be stored in the context. To enforce a given type, make the key 56 | private and wrap Get() and Set() to accept and return values of a specific 57 | type: 58 | 59 | type key int 60 | 61 | const mykey key = 0 62 | 63 | // GetMyKey returns a value for this package from the request values. 64 | func GetMyKey(r *http.Request) SomeType { 65 | if rv := context.Get(r, mykey); rv != nil { 66 | return rv.(SomeType) 67 | } 68 | return nil 69 | } 70 | 71 | // SetMyKey sets a value for this package in the request values. 72 | func SetMyKey(r *http.Request, val SomeType) { 73 | context.Set(r, mykey, val) 74 | } 75 | 76 | Variables must be cleared at the end of a request, to remove all values 77 | that were stored. This can be done in an http.Handler, after a request was 78 | served. Just call Clear() passing the request: 79 | 80 | context.Clear(r) 81 | 82 | ...or use ClearHandler(), which conveniently wraps an http.Handler to clear 83 | variables at the end of a request lifetime. 84 | 85 | The Routers from the packages gorilla/mux and gorilla/pat call Clear() 86 | so if you are using either of them you don't need to clear the context manually. 87 | */ 88 | package context 89 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | 4 | matrix: 5 | include: 6 | - go: 1.2 7 | - go: 1.3 8 | - go: 1.4 9 | - go: 1.5 10 | - go: 1.6 11 | - go: 1.7 12 | - go: tip 13 | 14 | install: 15 | - # Skip 16 | 17 | script: 18 | - go get -t -v ./... 19 | - diff -u <(echo -n) <(gofmt -d .) 20 | - go tool vet . 21 | - go test -v -race ./... 22 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Rodrigo Moraes. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/context_gorilla.go: -------------------------------------------------------------------------------- 1 | // +build !go1.7 2 | 3 | package mux 4 | 5 | import ( 6 | "net/http" 7 | 8 | "github.com/gorilla/context" 9 | ) 10 | 11 | func contextGet(r *http.Request, key interface{}) interface{} { 12 | return context.Get(r, key) 13 | } 14 | 15 | func contextSet(r *http.Request, key, val interface{}) *http.Request { 16 | if val == nil { 17 | return r 18 | } 19 | 20 | context.Set(r, key, val) 21 | return r 22 | } 23 | 24 | func contextClear(r *http.Request) { 25 | context.Clear(r) 26 | } 27 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/context_native.go: -------------------------------------------------------------------------------- 1 | // +build go1.7 2 | 3 | package mux 4 | 5 | import ( 6 | "context" 7 | "net/http" 8 | ) 9 | 10 | func contextGet(r *http.Request, key interface{}) interface{} { 11 | return r.Context().Value(key) 12 | } 13 | 14 | func contextSet(r *http.Request, key, val interface{}) *http.Request { 15 | if val == nil { 16 | return r 17 | } 18 | 19 | return r.WithContext(context.WithValue(r.Context(), key, val)) 20 | } 21 | 22 | func contextClear(r *http.Request) { 23 | return 24 | } 25 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/securecookie/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | 4 | matrix: 5 | include: 6 | - go: 1.3 7 | - go: 1.4 8 | - go: 1.5 9 | - go: 1.6 10 | - go: 1.7 11 | - go: tip 12 | allow_failures: 13 | - go: tip 14 | 15 | script: 16 | - go get -t -v ./... 17 | - diff -u <(echo -n) <(gofmt -d .) 18 | - go vet $(go list ./... | grep -v /vendor/) 19 | - go test -v -race ./... 20 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/securecookie/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Rodrigo Moraes. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/securecookie/README.md: -------------------------------------------------------------------------------- 1 | securecookie 2 | ============ 3 | [![GoDoc](https://godoc.org/github.com/gorilla/securecookie?status.svg)](https://godoc.org/github.com/gorilla/securecookie) [![Build Status](https://travis-ci.org/gorilla/securecookie.png?branch=master)](https://travis-ci.org/gorilla/securecookie) 4 | 5 | securecookie encodes and decodes authenticated and optionally encrypted 6 | cookie values. 7 | 8 | Secure cookies can't be forged, because their values are validated using HMAC. 9 | When encrypted, the content is also inaccessible to malicious eyes. It is still 10 | recommended that sensitive data not be stored in cookies, and that HTTPS be used 11 | to prevent cookie [replay attacks](https://en.wikipedia.org/wiki/Replay_attack). 12 | 13 | ## Examples 14 | 15 | To use it, first create a new SecureCookie instance: 16 | 17 | ```go 18 | // Hash keys should be at least 32 bytes long 19 | var hashKey = []byte("very-secret") 20 | // Block keys should be 16 bytes (AES-128) or 32 bytes (AES-256) long. 21 | // Shorter keys may weaken the encryption used. 22 | var blockKey = []byte("a-lot-secret") 23 | var s = securecookie.New(hashKey, blockKey) 24 | ``` 25 | 26 | The hashKey is required, used to authenticate the cookie value using HMAC. 27 | It is recommended to use a key with 32 or 64 bytes. 28 | 29 | The blockKey is optional, used to encrypt the cookie value -- set it to nil 30 | to not use encryption. If set, the length must correspond to the block size 31 | of the encryption algorithm. For AES, used by default, valid lengths are 32 | 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256. 33 | 34 | Strong keys can be created using the convenience function GenerateRandomKey(). 35 | 36 | Once a SecureCookie instance is set, use it to encode a cookie value: 37 | 38 | ```go 39 | func SetCookieHandler(w http.ResponseWriter, r *http.Request) { 40 | value := map[string]string{ 41 | "foo": "bar", 42 | } 43 | if encoded, err := s.Encode("cookie-name", value); err == nil { 44 | cookie := &http.Cookie{ 45 | Name: "cookie-name", 46 | Value: encoded, 47 | Path: "/", 48 | Secure: true, 49 | HttpOnly: true, 50 | } 51 | http.SetCookie(w, cookie) 52 | } 53 | } 54 | ``` 55 | 56 | Later, use the same SecureCookie instance to decode and validate a cookie 57 | value: 58 | 59 | ```go 60 | func ReadCookieHandler(w http.ResponseWriter, r *http.Request) { 61 | if cookie, err := r.Cookie("cookie-name"); err == nil { 62 | value := make(map[string]string) 63 | if err = s2.Decode("cookie-name", cookie.Value, &value); err == nil { 64 | fmt.Fprintf(w, "The value of foo is %q", value["foo"]) 65 | } 66 | } 67 | } 68 | ``` 69 | 70 | We stored a map[string]string, but secure cookies can hold any value that 71 | can be encoded using `encoding/gob`. To store custom types, they must be 72 | registered first using gob.Register(). For basic types this is not needed; 73 | it works out of the box. An optional JSON encoder that uses `encoding/json` is 74 | available for types compatible with JSON. 75 | 76 | ## License 77 | 78 | BSD licensed. See the LICENSE file for details. 79 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/securecookie/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Gorilla Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | /* 6 | Package securecookie encodes and decodes authenticated and optionally 7 | encrypted cookie values. 8 | 9 | Secure cookies can't be forged, because their values are validated using HMAC. 10 | When encrypted, the content is also inaccessible to malicious eyes. 11 | 12 | To use it, first create a new SecureCookie instance: 13 | 14 | var hashKey = []byte("very-secret") 15 | var blockKey = []byte("a-lot-secret") 16 | var s = securecookie.New(hashKey, blockKey) 17 | 18 | The hashKey is required, used to authenticate the cookie value using HMAC. 19 | It is recommended to use a key with 32 or 64 bytes. 20 | 21 | The blockKey is optional, used to encrypt the cookie value -- set it to nil 22 | to not use encryption. If set, the length must correspond to the block size 23 | of the encryption algorithm. For AES, used by default, valid lengths are 24 | 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256. 25 | 26 | Strong keys can be created using the convenience function GenerateRandomKey(). 27 | 28 | Once a SecureCookie instance is set, use it to encode a cookie value: 29 | 30 | func SetCookieHandler(w http.ResponseWriter, r *http.Request) { 31 | value := map[string]string{ 32 | "foo": "bar", 33 | } 34 | if encoded, err := s.Encode("cookie-name", value); err == nil { 35 | cookie := &http.Cookie{ 36 | Name: "cookie-name", 37 | Value: encoded, 38 | Path: "/", 39 | } 40 | http.SetCookie(w, cookie) 41 | } 42 | } 43 | 44 | Later, use the same SecureCookie instance to decode and validate a cookie 45 | value: 46 | 47 | func ReadCookieHandler(w http.ResponseWriter, r *http.Request) { 48 | if cookie, err := r.Cookie("cookie-name"); err == nil { 49 | value := make(map[string]string) 50 | if err = s2.Decode("cookie-name", cookie.Value, &value); err == nil { 51 | fmt.Fprintf(w, "The value of foo is %q", value["foo"]) 52 | } 53 | } 54 | } 55 | 56 | We stored a map[string]string, but secure cookies can hold any value that 57 | can be encoded using encoding/gob. To store custom types, they must be 58 | registered first using gob.Register(). For basic types this is not needed; 59 | it works out of the box. 60 | */ 61 | package securecookie 62 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/securecookie/fuzz.go: -------------------------------------------------------------------------------- 1 | // +build gofuzz 2 | 3 | package securecookie 4 | 5 | var hashKey = []byte("very-secret12345") 6 | var blockKey = []byte("a-lot-secret1234") 7 | var s = New(hashKey, blockKey) 8 | 9 | type Cookie struct { 10 | B bool 11 | I int 12 | S string 13 | } 14 | 15 | func Fuzz(data []byte) int { 16 | datas := string(data) 17 | var c Cookie 18 | if err := s.Decode("fuzz", datas, &c); err != nil { 19 | return 0 20 | } 21 | if _, err := s.Encode("fuzz", c); err != nil { 22 | panic(err) 23 | } 24 | return 1 25 | } 26 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/sessions/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | 4 | matrix: 5 | include: 6 | - go: 1.3 7 | - go: 1.4 8 | - go: 1.5 9 | - go: 1.6 10 | - go: 1.7 11 | - go: tip 12 | allow_failures: 13 | - go: tip 14 | 15 | install: 16 | - # skip 17 | 18 | script: 19 | - go get -t -v ./... 20 | - diff -u <(echo -n) <(gofmt -d .) 21 | - go vet $(go list ./... | grep -v /vendor/) 22 | - go test -v -race ./... 23 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/sessions/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Rodrigo Moraes. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/sessions/README.md: -------------------------------------------------------------------------------- 1 | sessions 2 | ======== 3 | [![GoDoc](https://godoc.org/github.com/gorilla/sessions?status.svg)](https://godoc.org/github.com/gorilla/sessions) [![Build Status](https://travis-ci.org/gorilla/sessions.png?branch=master)](https://travis-ci.org/gorilla/sessions) 4 | 5 | gorilla/sessions provides cookie and filesystem sessions and infrastructure for 6 | custom session backends. 7 | 8 | The key features are: 9 | 10 | * Simple API: use it as an easy way to set signed (and optionally 11 | encrypted) cookies. 12 | * Built-in backends to store sessions in cookies or the filesystem. 13 | * Flash messages: session values that last until read. 14 | * Convenient way to switch session persistency (aka "remember me") and set 15 | other attributes. 16 | * Mechanism to rotate authentication and encryption keys. 17 | * Multiple sessions per request, even using different backends. 18 | * Interfaces and infrastructure for custom session backends: sessions from 19 | different stores can be retrieved and batch-saved using a common API. 20 | 21 | Let's start with an example that shows the sessions API in a nutshell: 22 | 23 | ```go 24 | import ( 25 | "net/http" 26 | "github.com/gorilla/sessions" 27 | ) 28 | 29 | var store = sessions.NewCookieStore([]byte("something-very-secret")) 30 | 31 | func MyHandler(w http.ResponseWriter, r *http.Request) { 32 | // Get a session. We're ignoring the error resulted from decoding an 33 | // existing session: Get() always returns a session, even if empty. 34 | session, _ := store.Get(r, "session-name") 35 | // Set some session values. 36 | session.Values["foo"] = "bar" 37 | session.Values[42] = 43 38 | // Save it before we write to the response/return from the handler. 39 | session.Save(r, w) 40 | } 41 | ``` 42 | 43 | First we initialize a session store calling `NewCookieStore()` and passing a 44 | secret key used to authenticate the session. Inside the handler, we call 45 | `store.Get()` to retrieve an existing session or a new one. Then we set some 46 | session values in session.Values, which is a `map[interface{}]interface{}`. 47 | And finally we call `session.Save()` to save the session in the response. 48 | 49 | Important Note: If you aren't using gorilla/mux, you need to wrap your handlers 50 | with 51 | [`context.ClearHandler`](http://www.gorillatoolkit.org/pkg/context#ClearHandler) 52 | as or else you will leak memory! An easy way to do this is to wrap the top-level 53 | mux when calling http.ListenAndServe: 54 | 55 | More examples are available [on the Gorilla 56 | website](http://www.gorillatoolkit.org/pkg/sessions). 57 | 58 | ## Store Implementations 59 | 60 | Other implementations of the `sessions.Store` interface: 61 | 62 | * [github.com/starJammer/gorilla-sessions-arangodb](https://github.com/starJammer/gorilla-sessions-arangodb) - ArangoDB 63 | * [github.com/yosssi/boltstore](https://github.com/yosssi/boltstore) - Bolt 64 | * [github.com/srinathgs/couchbasestore](https://github.com/srinathgs/couchbasestore) - Couchbase 65 | * [github.com/denizeren/dynamostore](https://github.com/denizeren/dynamostore) - Dynamodb on AWS 66 | * [github.com/bradleypeabody/gorilla-sessions-memcache](https://github.com/bradleypeabody/gorilla-sessions-memcache) - Memcache 67 | * [github.com/dsoprea/goappenginesessioncascade](https://github.com/dsoprea/goappenginesessioncascade) - Memcache/Datastore/Context in AppEngine 68 | * [github.com/kidstuff/mongostore](https://github.com/kidstuff/mongostore) - MongoDB 69 | * [github.com/srinathgs/mysqlstore](https://github.com/srinathgs/mysqlstore) - MySQL 70 | * [github.com/antonlindstrom/pgstore](https://github.com/antonlindstrom/pgstore) - PostgreSQL 71 | * [github.com/boj/redistore](https://github.com/boj/redistore) - Redis 72 | * [github.com/boj/rethinkstore](https://github.com/boj/rethinkstore) - RethinkDB 73 | * [github.com/boj/riakstore](https://github.com/boj/riakstore) - Riak 74 | * [github.com/michaeljs1990/sqlitestore](https://github.com/michaeljs1990/sqlitestore) - SQLite 75 | * [github.com/wader/gormstore](https://github.com/wader/gormstore) - GORM (MySQL, PostgreSQL, SQLite) 76 | 77 | ## License 78 | 79 | BSD licensed. See the LICENSE file for details. 80 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/sessions/lex.go: -------------------------------------------------------------------------------- 1 | // This file contains code adapted from the Go standard library 2 | // https://github.com/golang/go/blob/39ad0fd0789872f9469167be7fe9578625ff246e/src/net/http/lex.go 3 | 4 | package sessions 5 | 6 | import "strings" 7 | 8 | var isTokenTable = [127]bool{ 9 | '!': true, 10 | '#': true, 11 | '$': true, 12 | '%': true, 13 | '&': true, 14 | '\'': true, 15 | '*': true, 16 | '+': true, 17 | '-': true, 18 | '.': true, 19 | '0': true, 20 | '1': true, 21 | '2': true, 22 | '3': true, 23 | '4': true, 24 | '5': true, 25 | '6': true, 26 | '7': true, 27 | '8': true, 28 | '9': true, 29 | 'A': true, 30 | 'B': true, 31 | 'C': true, 32 | 'D': true, 33 | 'E': true, 34 | 'F': true, 35 | 'G': true, 36 | 'H': true, 37 | 'I': true, 38 | 'J': true, 39 | 'K': true, 40 | 'L': true, 41 | 'M': true, 42 | 'N': true, 43 | 'O': true, 44 | 'P': true, 45 | 'Q': true, 46 | 'R': true, 47 | 'S': true, 48 | 'T': true, 49 | 'U': true, 50 | 'W': true, 51 | 'V': true, 52 | 'X': true, 53 | 'Y': true, 54 | 'Z': true, 55 | '^': true, 56 | '_': true, 57 | '`': true, 58 | 'a': true, 59 | 'b': true, 60 | 'c': true, 61 | 'd': true, 62 | 'e': true, 63 | 'f': true, 64 | 'g': true, 65 | 'h': true, 66 | 'i': true, 67 | 'j': true, 68 | 'k': true, 69 | 'l': true, 70 | 'm': true, 71 | 'n': true, 72 | 'o': true, 73 | 'p': true, 74 | 'q': true, 75 | 'r': true, 76 | 's': true, 77 | 't': true, 78 | 'u': true, 79 | 'v': true, 80 | 'w': true, 81 | 'x': true, 82 | 'y': true, 83 | 'z': true, 84 | '|': true, 85 | '~': true, 86 | } 87 | 88 | func isToken(r rune) bool { 89 | i := int(r) 90 | return i < len(isTokenTable) && isTokenTable[i] 91 | } 92 | 93 | func isNotToken(r rune) bool { 94 | return !isToken(r) 95 | } 96 | 97 | func isCookieNameValid(raw string) bool { 98 | if raw == "" { 99 | return false 100 | } 101 | return strings.IndexFunc(raw, isNotToken) < 0 102 | } 103 | -------------------------------------------------------------------------------- /vendor/github.com/lestrrat/go-apache-logformat/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | -------------------------------------------------------------------------------- /vendor/github.com/lestrrat/go-apache-logformat/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | go: 4 | - 1.7 5 | - tip 6 | -------------------------------------------------------------------------------- /vendor/github.com/lestrrat/go-apache-logformat/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 lestrrat 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /vendor/github.com/lestrrat/go-apache-logformat/README.md: -------------------------------------------------------------------------------- 1 | go-apache-logformat 2 | =================== 3 | 4 | [![Build Status](https://travis-ci.org/lestrrat/go-apache-logformat.png?branch=master)](https://travis-ci.org/lestrrat/go-apache-logformat) 5 | 6 | [![Coverage Status](https://coveralls.io/repos/lestrrat/go-apache-logformat/badge.png?branch=topic%2Fgoveralls)](https://coveralls.io/r/lestrrat/go-apache-logformat?branch=topic%2Fgoveralls) 7 | 8 | # SYNOPSYS 9 | 10 | ```go 11 | import ( 12 | "net/http" 13 | "os" 14 | 15 | "github.com/lestrrat/go-apache-logformat" 16 | ) 17 | 18 | func main() { 19 | var s http.ServeMux 20 | s.HandleFunc("/", handleIndex) 21 | s.HandleFunc("/foo", handleFoo) 22 | 23 | http.ListenAndServe(":8080", apachelog.CombinedLog.Wrap(s, os.Stderr)) 24 | } 25 | ``` 26 | 27 | # DESCRIPTION 28 | 29 | This is a port of Perl5's [Apache::LogFormat::Compiler](https://metacpan.org/release/Apache-LogFormat-Compiler) to golang 30 | -------------------------------------------------------------------------------- /vendor/github.com/lestrrat/go-apache-logformat/interface.go: -------------------------------------------------------------------------------- 1 | package apachelog 2 | 3 | import ( 4 | "errors" 5 | "io" 6 | "net/http" 7 | "time" 8 | ) 9 | 10 | type ApacheLog struct { 11 | format *Format 12 | } 13 | 14 | // Combined is a pre-defined ApacheLog struct to log "common" log format 15 | var CommonLog, _ = New(`%h %l %u %t "%r" %>s %b`) 16 | 17 | // Combined is a pre-defined ApacheLog struct to log "combined" log format 18 | var CombinedLog, _ = New(`%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-agent}i"`) 19 | 20 | var ( 21 | ErrInvalidRuneSequence = errors.New("invalid rune sequence found in format") 22 | ErrUnimplemented = errors.New("pattern unimplemented") 23 | ) 24 | 25 | type LogCtx struct { 26 | Request *http.Request 27 | RequestTime time.Time 28 | ResponseStatus int 29 | ResponseHeader http.Header 30 | ElapsedTime time.Duration 31 | } 32 | 33 | // Format describes an Apache log format. Given a logging context, 34 | // it can create a log line. 35 | type Format struct { 36 | writers []FormatWriter 37 | } 38 | 39 | type FormatWriter interface { 40 | WriteTo(io.Writer, *LogCtx) error 41 | } 42 | 43 | type FormatWriteFunc func(io.Writer, *LogCtx) error 44 | -------------------------------------------------------------------------------- /vendor/github.com/lestrrat/go-apache-logformat/logformat.go: -------------------------------------------------------------------------------- 1 | package apachelog 2 | 3 | import ( 4 | "io" 5 | "net/http" 6 | "os" 7 | "time" 8 | 9 | "github.com/pkg/errors" 10 | ) 11 | 12 | // New creates a new ApacheLog instance from the given 13 | // format. It will return an error if the format fails to compile. 14 | func New(format string) (*ApacheLog, error) { 15 | var f Format 16 | if err := f.compile(format); err != nil { 17 | return nil, errors.Wrap(err, "failed to compile log format") 18 | } 19 | 20 | return &ApacheLog{format: &f}, nil 21 | } 22 | 23 | // WriteLog generates a log line using the format associated with the 24 | // ApacheLog instance, using the values from ctx. The result is written 25 | // to dst 26 | func (al *ApacheLog) WriteLog(dst io.Writer, ctx *LogCtx) error { 27 | buf := getLogBuffer() 28 | defer releaseLogBuffer(buf) 29 | 30 | if err := al.format.WriteTo(buf, ctx); err != nil { 31 | return errors.Wrap(err, "failed to format log line") 32 | } 33 | 34 | b := buf.Bytes() 35 | if b[len(b)-1] != '\n' { 36 | buf.Write([]byte{'\n'}) 37 | } 38 | 39 | if _, err := buf.WriteTo(dst); err != nil { 40 | return errors.Wrap(err, "failed to write formated line to destination") 41 | } 42 | return nil 43 | } 44 | 45 | type absorbingResponseWriter struct { 46 | w http.ResponseWriter 47 | ctx *LogCtx 48 | } 49 | 50 | func (w *absorbingResponseWriter) Write(buf []byte) (int, error) { 51 | return w.w.Write(buf) 52 | } 53 | 54 | func (w *absorbingResponseWriter) Header() http.Header { 55 | return w.w.Header() 56 | } 57 | 58 | func (w *absorbingResponseWriter) WriteHeader(status int) { 59 | w.ctx.ResponseStatus = status 60 | w.w.WriteHeader(status) 61 | } 62 | 63 | // Wrap creates a new http.Handler that logs a formatted log line 64 | // to dst. 65 | func (al *ApacheLog) Wrap(h http.Handler, dst io.Writer) http.Handler { 66 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 67 | ctx := getLogCtx() 68 | defer releaseLogCtx(ctx) 69 | 70 | ctx.Request = r 71 | ctx.RequestTime = time.Now() 72 | ctx.ResponseStatus = http.StatusOK 73 | 74 | w2 := getResponseWriter(w, ctx) 75 | defer releaseResponseWriter(w2) 76 | 77 | defer func() { 78 | ctx.ResponseHeader = w2.Header() 79 | ctx.ElapsedTime = time.Since(ctx.RequestTime) 80 | if err := al.WriteLog(dst, ctx); err != nil { 81 | // Hmmm... no where to log except for stderr 82 | os.Stderr.Write([]byte(err.Error())) 83 | return 84 | } 85 | }() 86 | 87 | h.ServeHTTP(w2, r) 88 | }) 89 | } 90 | -------------------------------------------------------------------------------- /vendor/github.com/lestrrat/go-apache-logformat/pool.go: -------------------------------------------------------------------------------- 1 | package apachelog 2 | 3 | import ( 4 | "bytes" 5 | "net/http" 6 | "sync" 7 | "time" 8 | ) 9 | 10 | var logBufferPool sync.Pool 11 | var logCtxPool sync.Pool 12 | var responseWriterPool sync.Pool 13 | 14 | func init() { 15 | logBufferPool.New = allocLogBuffer 16 | logCtxPool.New = allocLogCtx 17 | responseWriterPool.New = allocResponseWriter 18 | } 19 | 20 | func allocLogBuffer() interface{} { 21 | return &bytes.Buffer{} 22 | } 23 | 24 | func getLogBuffer() *bytes.Buffer { 25 | return logBufferPool.Get().(*bytes.Buffer) 26 | } 27 | 28 | func releaseLogBuffer(v *bytes.Buffer) { 29 | v.Reset() 30 | logBufferPool.Put(v) 31 | } 32 | 33 | func allocLogCtx() interface{} { 34 | return &LogCtx{} 35 | } 36 | 37 | func getLogCtx() *LogCtx { 38 | return logCtxPool.Get().(*LogCtx) 39 | } 40 | 41 | func releaseLogCtx(v *LogCtx) { 42 | v.Request = nil 43 | v.RequestTime = time.Time{} 44 | v.ResponseStatus = http.StatusOK 45 | v.ResponseHeader = nil 46 | v.ElapsedTime = 0 47 | logCtxPool.Put(v) 48 | } 49 | 50 | func allocResponseWriter() interface{} { 51 | return &absorbingResponseWriter{} 52 | } 53 | 54 | func getResponseWriter(w http.ResponseWriter, ctx *LogCtx) *absorbingResponseWriter { 55 | w2 := responseWriterPool.Get().(*absorbingResponseWriter) 56 | w2.w = w 57 | w2.ctx = ctx 58 | return w2 59 | } 60 | 61 | func releaseResponseWriter(v *absorbingResponseWriter) { 62 | v.w = nil 63 | v.ctx = nil 64 | responseWriterPool.Put(v) 65 | } 66 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go_import_path: github.com/pkg/errors 3 | go: 4 | - 1.4.3 5 | - 1.5.4 6 | - 1.6.2 7 | - tip 8 | 9 | script: 10 | - go test -v ./... 11 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Dave Cheney 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/README.md: -------------------------------------------------------------------------------- 1 | # errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) 2 | 3 | Package errors provides simple error handling primitives. 4 | 5 | `go get github.com/pkg/errors` 6 | 7 | The traditional error handling idiom in Go is roughly akin to 8 | ```go 9 | if err != nil { 10 | return err 11 | } 12 | ``` 13 | which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error. 14 | 15 | ## Adding context to an error 16 | 17 | The errors.Wrap function returns a new error that adds context to the original error. For example 18 | ```go 19 | _, err := ioutil.ReadAll(r) 20 | if err != nil { 21 | return errors.Wrap(err, "read failed") 22 | } 23 | ``` 24 | ## Retrieving the cause of an error 25 | 26 | Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`. 27 | ```go 28 | type causer interface { 29 | Cause() error 30 | } 31 | ``` 32 | `errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example: 33 | ```go 34 | switch err := errors.Cause(err).(type) { 35 | case *MyError: 36 | // handle specifically 37 | default: 38 | // unknown error 39 | } 40 | ``` 41 | 42 | [Read the package documentation for more information](https://godoc.org/github.com/pkg/errors). 43 | 44 | ## Contributing 45 | 46 | We welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high. 47 | 48 | Before proposing a change, please discuss your change by raising an issue. 49 | 50 | ## Licence 51 | 52 | BSD-2-Clause 53 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/appveyor.yml: -------------------------------------------------------------------------------- 1 | version: build-{build}.{branch} 2 | 3 | clone_folder: C:\gopath\src\github.com\pkg\errors 4 | shallow_clone: true # for startup speed 5 | 6 | environment: 7 | GOPATH: C:\gopath 8 | 9 | platform: 10 | - x64 11 | 12 | # http://www.appveyor.com/docs/installed-software 13 | install: 14 | # some helpful output for debugging builds 15 | - go version 16 | - go env 17 | # pre-installed MinGW at C:\MinGW is 32bit only 18 | # but MSYS2 at C:\msys64 has mingw64 19 | - set PATH=C:\msys64\mingw64\bin;%PATH% 20 | - gcc --version 21 | - g++ --version 22 | 23 | build_script: 24 | - go install -v ./... 25 | 26 | test_script: 27 | - set PATH=C:\gopath\bin;%PATH% 28 | - go test -v ./... 29 | 30 | #artifacts: 31 | # - path: '%GOPATH%\bin\*.exe' 32 | deploy: off 33 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/oauth2/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.3 5 | - 1.4 6 | 7 | install: 8 | - export GOPATH="$HOME/gopath" 9 | - mkdir -p "$GOPATH/src/golang.org/x" 10 | - mv "$TRAVIS_BUILD_DIR" "$GOPATH/src/golang.org/x/oauth2" 11 | - go get -v -t -d golang.org/x/oauth2/... 12 | 13 | script: 14 | - go test -v golang.org/x/oauth2/... 15 | -------------------------------------------------------------------------------- /vendor/golang.org/x/oauth2/AUTHORS: -------------------------------------------------------------------------------- 1 | # This source code refers to The Go Authors for copyright purposes. 2 | # The master list of authors is in the main Go distribution, 3 | # visible at http://tip.golang.org/AUTHORS. 4 | -------------------------------------------------------------------------------- /vendor/golang.org/x/oauth2/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Go 2 | 3 | Go is an open source project. 4 | 5 | It is the work of hundreds of contributors. We appreciate your help! 6 | 7 | 8 | ## Filing issues 9 | 10 | When [filing an issue](https://github.com/golang/oauth2/issues), make sure to answer these five questions: 11 | 12 | 1. What version of Go are you using (`go version`)? 13 | 2. What operating system and processor architecture are you using? 14 | 3. What did you do? 15 | 4. What did you expect to see? 16 | 5. What did you see instead? 17 | 18 | General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker. 19 | The gophers there will answer or ask you to file an issue if you've tripped over a bug. 20 | 21 | ## Contributing code 22 | 23 | Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html) 24 | before sending patches. 25 | 26 | **We do not accept GitHub pull requests** 27 | (we use [Gerrit](https://code.google.com/p/gerrit/) instead for code review). 28 | 29 | Unless otherwise noted, the Go source files are distributed under 30 | the BSD-style license found in the LICENSE file. 31 | 32 | -------------------------------------------------------------------------------- /vendor/golang.org/x/oauth2/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # This source code was written by the Go contributors. 2 | # The master list of contributors is in the main Go distribution, 3 | # visible at http://tip.golang.org/CONTRIBUTORS. 4 | -------------------------------------------------------------------------------- /vendor/golang.org/x/oauth2/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The oauth2 Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/golang.org/x/oauth2/README.md: -------------------------------------------------------------------------------- 1 | # OAuth2 for Go 2 | 3 | [![Build Status](https://travis-ci.org/golang/oauth2.svg?branch=master)](https://travis-ci.org/golang/oauth2) 4 | 5 | oauth2 package contains a client implementation for OAuth 2.0 spec. 6 | 7 | ## Installation 8 | 9 | ~~~~ 10 | go get golang.org/x/oauth2 11 | ~~~~ 12 | 13 | See godoc for further documentation and examples. 14 | 15 | * [godoc.org/golang.org/x/oauth2](http://godoc.org/golang.org/x/oauth2) 16 | * [godoc.org/golang.org/x/oauth2/google](http://godoc.org/golang.org/x/oauth2/google) 17 | 18 | 19 | ## App Engine 20 | 21 | In change 96e89be (March 2015) we removed the `oauth2.Context2` type in favor 22 | of the [`context.Context`](https://golang.org/x/net/context#Context) type from 23 | the `golang.org/x/net/context` package 24 | 25 | This means its no longer possible to use the "Classic App Engine" 26 | `appengine.Context` type with the `oauth2` package. (You're using 27 | Classic App Engine if you import the package `"appengine"`.) 28 | 29 | To work around this, you may use the new `"google.golang.org/appengine"` 30 | package. This package has almost the same API as the `"appengine"` package, 31 | but it can be fetched with `go get` and used on "Managed VMs" and well as 32 | Classic App Engine. 33 | 34 | See the [new `appengine` package's readme](https://github.com/golang/appengine#updating-a-go-app-engine-app) 35 | for information on updating your app. 36 | 37 | If you don't want to update your entire app to use the new App Engine packages, 38 | you may use both sets of packages in parallel, using only the new packages 39 | with the `oauth2` package. 40 | 41 | import ( 42 | "golang.org/x/net/context" 43 | "golang.org/x/oauth2" 44 | "golang.org/x/oauth2/google" 45 | newappengine "google.golang.org/appengine" 46 | newurlfetch "google.golang.org/appengine/urlfetch" 47 | 48 | "appengine" 49 | ) 50 | 51 | func handler(w http.ResponseWriter, r *http.Request) { 52 | var c appengine.Context = appengine.NewContext(r) 53 | c.Infof("Logging a message with the old package") 54 | 55 | var ctx context.Context = newappengine.NewContext(r) 56 | client := &http.Client{ 57 | Transport: &oauth2.Transport{ 58 | Source: google.AppEngineTokenSource(ctx, "scope"), 59 | Base: &newurlfetch.Transport{Context: ctx}, 60 | }, 61 | } 62 | client.Get("...") 63 | } 64 | 65 | -------------------------------------------------------------------------------- /vendor/golang.org/x/oauth2/client_appengine.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The oauth2 Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build appengine 6 | 7 | // App Engine hooks. 8 | 9 | package oauth2 10 | 11 | import ( 12 | "net/http" 13 | 14 | "golang.org/x/net/context" 15 | "golang.org/x/oauth2/internal" 16 | "google.golang.org/appengine/urlfetch" 17 | ) 18 | 19 | func init() { 20 | internal.RegisterContextClientFunc(contextClientAppEngine) 21 | } 22 | 23 | func contextClientAppEngine(ctx context.Context) (*http.Client, error) { 24 | return urlfetch.Client(ctx), nil 25 | } 26 | -------------------------------------------------------------------------------- /vendor/golang.org/x/oauth2/github/github.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The oauth2 Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package github provides constants for using OAuth2 to access Github. 6 | package github 7 | 8 | import ( 9 | "golang.org/x/oauth2" 10 | ) 11 | 12 | // Endpoint is Github's OAuth 2.0 endpoint. 13 | var Endpoint = oauth2.Endpoint{ 14 | AuthURL: "https://github.com/login/oauth/authorize", 15 | TokenURL: "https://github.com/login/oauth/access_token", 16 | } 17 | -------------------------------------------------------------------------------- /vendor/golang.org/x/oauth2/internal/oauth2.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The oauth2 Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package internal contains support packages for oauth2 package. 6 | package internal 7 | 8 | import ( 9 | "bufio" 10 | "crypto/rsa" 11 | "crypto/x509" 12 | "encoding/pem" 13 | "errors" 14 | "fmt" 15 | "io" 16 | "strings" 17 | ) 18 | 19 | // ParseKey converts the binary contents of a private key file 20 | // to an *rsa.PrivateKey. It detects whether the private key is in a 21 | // PEM container or not. If so, it extracts the the private key 22 | // from PEM container before conversion. It only supports PEM 23 | // containers with no passphrase. 24 | func ParseKey(key []byte) (*rsa.PrivateKey, error) { 25 | block, _ := pem.Decode(key) 26 | if block != nil { 27 | key = block.Bytes 28 | } 29 | parsedKey, err := x509.ParsePKCS8PrivateKey(key) 30 | if err != nil { 31 | parsedKey, err = x509.ParsePKCS1PrivateKey(key) 32 | if err != nil { 33 | return nil, fmt.Errorf("private key should be a PEM or plain PKSC1 or PKCS8; parse error: %v", err) 34 | } 35 | } 36 | parsed, ok := parsedKey.(*rsa.PrivateKey) 37 | if !ok { 38 | return nil, errors.New("private key is invalid") 39 | } 40 | return parsed, nil 41 | } 42 | 43 | func ParseINI(ini io.Reader) (map[string]map[string]string, error) { 44 | result := map[string]map[string]string{ 45 | "": map[string]string{}, // root section 46 | } 47 | scanner := bufio.NewScanner(ini) 48 | currentSection := "" 49 | for scanner.Scan() { 50 | line := strings.TrimSpace(scanner.Text()) 51 | if strings.HasPrefix(line, ";") { 52 | // comment. 53 | continue 54 | } 55 | if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") { 56 | currentSection = strings.TrimSpace(line[1 : len(line)-1]) 57 | result[currentSection] = map[string]string{} 58 | continue 59 | } 60 | parts := strings.SplitN(line, "=", 2) 61 | if len(parts) == 2 && parts[0] != "" { 62 | result[currentSection][strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1]) 63 | } 64 | } 65 | if err := scanner.Err(); err != nil { 66 | return nil, fmt.Errorf("error scanning ini: %v", err) 67 | } 68 | return result, nil 69 | } 70 | 71 | func CondVal(v string) []string { 72 | if v == "" { 73 | return nil 74 | } 75 | return []string{v} 76 | } 77 | -------------------------------------------------------------------------------- /vendor/golang.org/x/oauth2/internal/transport.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The oauth2 Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package internal contains support packages for oauth2 package. 6 | package internal 7 | 8 | import ( 9 | "net/http" 10 | 11 | "golang.org/x/net/context" 12 | ) 13 | 14 | // HTTPClient is the context key to use with golang.org/x/net/context's 15 | // WithValue function to associate an *http.Client value with a context. 16 | var HTTPClient ContextKey 17 | 18 | // ContextKey is just an empty struct. It exists so HTTPClient can be 19 | // an immutable public variable with a unique type. It's immutable 20 | // because nobody else can create a ContextKey, being unexported. 21 | type ContextKey struct{} 22 | 23 | // ContextClientFunc is a func which tries to return an *http.Client 24 | // given a Context value. If it returns an error, the search stops 25 | // with that error. If it returns (nil, nil), the search continues 26 | // down the list of registered funcs. 27 | type ContextClientFunc func(context.Context) (*http.Client, error) 28 | 29 | var contextClientFuncs []ContextClientFunc 30 | 31 | func RegisterContextClientFunc(fn ContextClientFunc) { 32 | contextClientFuncs = append(contextClientFuncs, fn) 33 | } 34 | 35 | func ContextClient(ctx context.Context) (*http.Client, error) { 36 | for _, fn := range contextClientFuncs { 37 | c, err := fn(ctx) 38 | if err != nil { 39 | return nil, err 40 | } 41 | if c != nil { 42 | return c, nil 43 | } 44 | } 45 | if hc, ok := ctx.Value(HTTPClient).(*http.Client); ok { 46 | return hc, nil 47 | } 48 | return http.DefaultClient, nil 49 | } 50 | 51 | func ContextTransport(ctx context.Context) http.RoundTripper { 52 | hc, err := ContextClient(ctx) 53 | // This is a rare error case (somebody using nil on App Engine). 54 | if err != nil { 55 | return ErrorTransport{err} 56 | } 57 | return hc.Transport 58 | } 59 | 60 | // ErrorTransport returns the specified error on RoundTrip. 61 | // This RoundTripper should be used in rare error cases where 62 | // error handling can be postponed to response handling time. 63 | type ErrorTransport struct{ Err error } 64 | 65 | func (t ErrorTransport) RoundTrip(*http.Request) (*http.Response, error) { 66 | return nil, t.Err 67 | } 68 | -------------------------------------------------------------------------------- /vendor/golang.org/x/oauth2/transport.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The oauth2 Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package oauth2 6 | 7 | import ( 8 | "errors" 9 | "io" 10 | "net/http" 11 | "sync" 12 | ) 13 | 14 | // Transport is an http.RoundTripper that makes OAuth 2.0 HTTP requests, 15 | // wrapping a base RoundTripper and adding an Authorization header 16 | // with a token from the supplied Sources. 17 | // 18 | // Transport is a low-level mechanism. Most code will use the 19 | // higher-level Config.Client method instead. 20 | type Transport struct { 21 | // Source supplies the token to add to outgoing requests' 22 | // Authorization headers. 23 | Source TokenSource 24 | 25 | // Base is the base RoundTripper used to make HTTP requests. 26 | // If nil, http.DefaultTransport is used. 27 | Base http.RoundTripper 28 | 29 | mu sync.Mutex // guards modReq 30 | modReq map[*http.Request]*http.Request // original -> modified 31 | } 32 | 33 | // RoundTrip authorizes and authenticates the request with an 34 | // access token. If no token exists or token is expired, 35 | // tries to refresh/fetch a new token. 36 | func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) { 37 | if t.Source == nil { 38 | return nil, errors.New("oauth2: Transport's Source is nil") 39 | } 40 | token, err := t.Source.Token() 41 | if err != nil { 42 | return nil, err 43 | } 44 | 45 | req2 := cloneRequest(req) // per RoundTripper contract 46 | token.SetAuthHeader(req2) 47 | t.setModReq(req, req2) 48 | res, err := t.base().RoundTrip(req2) 49 | if err != nil { 50 | t.setModReq(req, nil) 51 | return nil, err 52 | } 53 | res.Body = &onEOFReader{ 54 | rc: res.Body, 55 | fn: func() { t.setModReq(req, nil) }, 56 | } 57 | return res, nil 58 | } 59 | 60 | // CancelRequest cancels an in-flight request by closing its connection. 61 | func (t *Transport) CancelRequest(req *http.Request) { 62 | type canceler interface { 63 | CancelRequest(*http.Request) 64 | } 65 | if cr, ok := t.base().(canceler); ok { 66 | t.mu.Lock() 67 | modReq := t.modReq[req] 68 | delete(t.modReq, req) 69 | t.mu.Unlock() 70 | cr.CancelRequest(modReq) 71 | } 72 | } 73 | 74 | func (t *Transport) base() http.RoundTripper { 75 | if t.Base != nil { 76 | return t.Base 77 | } 78 | return http.DefaultTransport 79 | } 80 | 81 | func (t *Transport) setModReq(orig, mod *http.Request) { 82 | t.mu.Lock() 83 | defer t.mu.Unlock() 84 | if t.modReq == nil { 85 | t.modReq = make(map[*http.Request]*http.Request) 86 | } 87 | if mod == nil { 88 | delete(t.modReq, orig) 89 | } else { 90 | t.modReq[orig] = mod 91 | } 92 | } 93 | 94 | // cloneRequest returns a clone of the provided *http.Request. 95 | // The clone is a shallow copy of the struct and its Header map. 96 | func cloneRequest(r *http.Request) *http.Request { 97 | // shallow copy of the struct 98 | r2 := new(http.Request) 99 | *r2 = *r 100 | // deep copy of the Header 101 | r2.Header = make(http.Header, len(r.Header)) 102 | for k, s := range r.Header { 103 | r2.Header[k] = append([]string(nil), s...) 104 | } 105 | return r2 106 | } 107 | 108 | type onEOFReader struct { 109 | rc io.ReadCloser 110 | fn func() 111 | } 112 | 113 | func (r *onEOFReader) Read(p []byte) (n int, err error) { 114 | n, err = r.rc.Read(p) 115 | if err == io.EOF { 116 | r.runFunc() 117 | } 118 | return 119 | } 120 | 121 | func (r *onEOFReader) Close() error { 122 | err := r.rc.Close() 123 | r.runFunc() 124 | return err 125 | } 126 | 127 | func (r *onEOFReader) runFunc() { 128 | if fn := r.fn; fn != nil { 129 | fn() 130 | r.fn = nil 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /webpack.config.babel.js: -------------------------------------------------------------------------------- 1 | /*eslint-disable no-process-env */ 2 | import fs from 'fs'; 3 | import autoprefixer from 'autoprefixer'; 4 | import bootstrap from 'bootstrap-styl'; 5 | import cssMqpacker from 'css-mqpacker'; 6 | import flexboxfixer from 'postcss-flexboxfixer'; 7 | import nib from 'nib'; 8 | import packagejson from './package.json'; 9 | import path from 'path'; 10 | import webpack from 'webpack'; 11 | import { spawn } from 'child_process'; 12 | 13 | const version = packagejson.version; 14 | const devServer = /webpack\-dev\-server$/.test(process.env._); 15 | const buildDir = path.join(__dirname, 'assets', 'build'); 16 | const srcDir = path.join(__dirname, 'assets', 'src'); 17 | 18 | const entries = ['babel-polyfill', path.join(srcDir, 'index.js')]; 19 | const cssLoader = devServer ? 'css' : 'css?minimize'; 20 | const plugins = [ 21 | new webpack.DefinePlugin({ 22 | 'process.env': { 23 | NODE_ENV: JSON.stringify(process.env.NODE_ENV), 24 | VERSION: JSON.stringify(version) 25 | } 26 | }) 27 | ]; 28 | 29 | if (devServer) { 30 | plugins.push(new webpack.HotModuleReplacementPlugin()); 31 | entries.push('webpack/hot/dev-server'); 32 | 33 | let serverProcess = null; 34 | 35 | function startServer() { 36 | // process.env.DEV_SERVER = 1; 37 | const buildProcess = spawn('npm', ['run', 'go:build']); 38 | console.info(`[go:build#${buildProcess.pid}] Starting`); 39 | buildProcess.on('close', (code) => { 40 | if (code === 0) { 41 | serverProcess = spawn('./wiplock', [], { 42 | env: Object.assign({ DEV_SERVER: 1 }, process.env) 43 | }); 44 | console.info(`[server#${serverProcess.pid}] Starting`); 45 | serverProcess.stdout.on('data', (data) => { 46 | console.log(`[server:error#${serverProcess.pid}] ${data}`); 47 | }); 48 | serverProcess.stdout.on('error', (data) => { 49 | console.error(`[server#${serverProcess.pid}:error] ${data}`); 50 | }); 51 | } else { 52 | console.error(`[go:build#${buildProcess.pid}] exited with status ${code}`) 53 | } 54 | }) 55 | buildProcess.stdout.on('data', (data) => { 56 | console.log(`[go:build#${buildProcess.pid}] ${data}`); 57 | }); 58 | buildProcess.stdout.on('error', (data) => { 59 | console.error(`[go:build#${buildProcess.pid}:error] ${data}`); 60 | }); 61 | } 62 | 63 | function stopServer() { 64 | if (serverProcess) { 65 | serverProcess.kill(); 66 | } 67 | serverProcess = null; 68 | } 69 | 70 | function restartServer() { 71 | stopServer(); 72 | startServer(); 73 | } 74 | 75 | fs.watch('./app', (event, filename) => { 76 | if (/.+\.go$/.test(filename)) { 77 | console.info(event, filename); 78 | restartServer(); 79 | } 80 | }); 81 | process.on('exit', stopServer); 82 | setTimeout(startServer, 1); 83 | 84 | } else { 85 | plugins.push( 86 | new webpack.optimize.UglifyJsPlugin({ 87 | minimize: true, 88 | output: { 89 | ascii_only: true 90 | } 91 | }) 92 | ); 93 | } 94 | 95 | export default { 96 | cache: true, 97 | entry: entries, 98 | output: { 99 | path: buildDir, 100 | filename: 'bundle.js', 101 | publicPath: '/assets' 102 | }, 103 | display: { errorDetails: true }, 104 | resolveLoader: { 105 | modulesDirectories: ['node_modules', srcDir] 106 | }, 107 | resolve: { 108 | extensions: ['', '.js', '.jsx'], 109 | modulesDirectories: ['node_modules', srcDir] 110 | }, 111 | module:{ 112 | preLoaders: [ 113 | { test: /\.jsx?$/, loader: 'eslint-loader', exclude: /node_modules/ }, 114 | { test: /\.styl?$/, loader: 'stylint-loader', exclude: /node_modules/ } 115 | ], 116 | loaders: [ 117 | { test: /\.(eot|ttf|svg)(\?.+)?$/, loaders: ['file'] }, 118 | { test: /\.styl$/, loaders: ['style', cssLoader, 'postcss', 'stylus'] }, 119 | { test: /\.css$/, loaders: ['style', cssLoader] }, 120 | { test: /\.jsx?$/, loaders: ['babel'], exclude: /node_modules/ }, 121 | { test: /\.json$/, loaders: ['json'] }, 122 | { test: /\.(jpg|woff|woff2|png|gif|mp3$)/, loaders: ['url?limit=102400'] } 123 | ] 124 | }, 125 | plugins, 126 | postcss: () => { 127 | return [autoprefixer, flexboxfixer, cssMqpacker]; 128 | }, 129 | eslint: { configFile: '.eslintrc' }, 130 | stylus: { 131 | use: [bootstrap(), nib()] 132 | }, 133 | devServer: { 134 | historyApiFallback: false, 135 | contentBase: buildDir, 136 | hot: true, 137 | inline: true, 138 | publicPath: '/assets/', 139 | proxy: { 140 | '/api/*': 'http://localhost:8000', 141 | '/': 'http://localhost:8000' 142 | } 143 | }, 144 | devtool: devServer ? '#cheap-module-inline-source-map' : null 145 | }; 146 | --------------------------------------------------------------------------------