octodoggy 4.6.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/CONTRIBUTING.md +22 -0
- data/LICENSE.md +20 -0
- data/README.md +714 -0
- data/Rakefile +22 -0
- data/lib/ext/sawyer/relation.rb +10 -0
- data/lib/octokit.rb +59 -0
- data/lib/octokit/arguments.rb +14 -0
- data/lib/octokit/authentication.rb +82 -0
- data/lib/octokit/client.rb +238 -0
- data/lib/octokit/client/authorizations.rb +244 -0
- data/lib/octokit/client/commit_comments.rb +95 -0
- data/lib/octokit/client/commits.rb +239 -0
- data/lib/octokit/client/contents.rb +162 -0
- data/lib/octokit/client/deployments.rb +62 -0
- data/lib/octokit/client/downloads.rb +50 -0
- data/lib/octokit/client/emojis.rb +18 -0
- data/lib/octokit/client/events.rb +151 -0
- data/lib/octokit/client/feeds.rb +33 -0
- data/lib/octokit/client/gists.rb +233 -0
- data/lib/octokit/client/gitignore.rb +43 -0
- data/lib/octokit/client/hooks.rb +297 -0
- data/lib/octokit/client/integrations.rb +77 -0
- data/lib/octokit/client/issues.rb +321 -0
- data/lib/octokit/client/labels.rb +156 -0
- data/lib/octokit/client/legacy_search.rb +42 -0
- data/lib/octokit/client/licenses.rb +45 -0
- data/lib/octokit/client/markdown.rb +27 -0
- data/lib/octokit/client/meta.rb +21 -0
- data/lib/octokit/client/milestones.rb +87 -0
- data/lib/octokit/client/notifications.rb +171 -0
- data/lib/octokit/client/objects.rb +141 -0
- data/lib/octokit/client/organizations.rb +768 -0
- data/lib/octokit/client/pages.rb +63 -0
- data/lib/octokit/client/projects.rb +314 -0
- data/lib/octokit/client/pub_sub_hubbub.rb +111 -0
- data/lib/octokit/client/pull_requests.rb +301 -0
- data/lib/octokit/client/rate_limit.rb +54 -0
- data/lib/octokit/client/reactions.rb +158 -0
- data/lib/octokit/client/refs.rb +118 -0
- data/lib/octokit/client/releases.rb +163 -0
- data/lib/octokit/client/repositories.rb +654 -0
- data/lib/octokit/client/repository_invitations.rb +103 -0
- data/lib/octokit/client/reviews.rb +174 -0
- data/lib/octokit/client/say.rb +19 -0
- data/lib/octokit/client/search.rb +76 -0
- data/lib/octokit/client/service_status.rb +38 -0
- data/lib/octokit/client/source_import.rb +161 -0
- data/lib/octokit/client/stats.rb +105 -0
- data/lib/octokit/client/statuses.rb +47 -0
- data/lib/octokit/client/traffic.rb +69 -0
- data/lib/octokit/client/users.rb +354 -0
- data/lib/octokit/configurable.rb +147 -0
- data/lib/octokit/connection.rb +199 -0
- data/lib/octokit/default.rb +166 -0
- data/lib/octokit/enterprise_admin_client.rb +40 -0
- data/lib/octokit/enterprise_admin_client/admin_stats.rb +120 -0
- data/lib/octokit/enterprise_admin_client/license.rb +18 -0
- data/lib/octokit/enterprise_admin_client/orgs.rb +27 -0
- data/lib/octokit/enterprise_admin_client/search_indexing.rb +83 -0
- data/lib/octokit/enterprise_admin_client/users.rb +128 -0
- data/lib/octokit/enterprise_management_console_client.rb +50 -0
- data/lib/octokit/enterprise_management_console_client/management_console.rb +176 -0
- data/lib/octokit/error.rb +286 -0
- data/lib/octokit/gist.rb +36 -0
- data/lib/octokit/middleware/follow_redirects.rb +131 -0
- data/lib/octokit/organization.rb +17 -0
- data/lib/octokit/preview.rb +38 -0
- data/lib/octokit/rate_limit.rb +33 -0
- data/lib/octokit/repo_arguments.rb +19 -0
- data/lib/octokit/repository.rb +93 -0
- data/lib/octokit/response/feed_parser.rb +21 -0
- data/lib/octokit/response/raise_error.rb +21 -0
- data/lib/octokit/user.rb +19 -0
- data/lib/octokit/version.rb +17 -0
- data/lib/octokit/warnable.rb +17 -0
- data/octokit.gemspec +22 -0
- metadata +160 -0
data/lib/octokit/gist.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
module Octokit
|
2
|
+
|
3
|
+
# Class to parse and create Gist URLs
|
4
|
+
class Gist
|
5
|
+
|
6
|
+
# !@attribute id
|
7
|
+
# @return [String] Gist ID
|
8
|
+
attr_accessor :id
|
9
|
+
|
10
|
+
# Instantiate {Gist} object from Gist URL
|
11
|
+
# @ return [Gist]
|
12
|
+
def self.from_url(url)
|
13
|
+
Gist.new(URI.parse(url).path[1..-1])
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(gist)
|
17
|
+
case gist
|
18
|
+
when Integer, String
|
19
|
+
@id = gist.to_s
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Gist ID
|
24
|
+
# @return [String]
|
25
|
+
def to_s
|
26
|
+
@id
|
27
|
+
end
|
28
|
+
|
29
|
+
# Gist URL
|
30
|
+
# @return [String]
|
31
|
+
def url
|
32
|
+
"https://gist.github.com/#{@id}"
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'set'
|
3
|
+
|
4
|
+
# Adapted from lostisland/faraday_middleware. Trimmed down to just the logic
|
5
|
+
# that we need for octokit.rb.
|
6
|
+
#
|
7
|
+
# https://github.com/lostisland/faraday_middleware/blob/138766e/lib/faraday_middleware/response/follow_redirects.rb
|
8
|
+
|
9
|
+
module Octokit
|
10
|
+
|
11
|
+
module Middleware
|
12
|
+
|
13
|
+
# Public: Exception thrown when the maximum amount of requests is exceeded.
|
14
|
+
class RedirectLimitReached < Faraday::Error::ClientError
|
15
|
+
attr_reader :response
|
16
|
+
|
17
|
+
def initialize(response)
|
18
|
+
super "too many redirects; last one to: #{response['location']}"
|
19
|
+
@response = response
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Public: Follow HTTP 301, 302, 303, and 307 redirects.
|
24
|
+
#
|
25
|
+
# For HTTP 303, the original GET, POST, PUT, DELETE, or PATCH request gets
|
26
|
+
# converted into a GET. For HTTP 301, 302, and 307, the HTTP method remains
|
27
|
+
# unchanged.
|
28
|
+
#
|
29
|
+
# This middleware currently only works with synchronous requests; i.e. it
|
30
|
+
# doesn't support parallelism.
|
31
|
+
class FollowRedirects < Faraday::Middleware
|
32
|
+
# HTTP methods for which 30x redirects can be followed
|
33
|
+
ALLOWED_METHODS = Set.new [:head, :options, :get, :post, :put, :patch, :delete]
|
34
|
+
|
35
|
+
# HTTP redirect status codes that this middleware implements
|
36
|
+
REDIRECT_CODES = Set.new [301, 302, 303, 307]
|
37
|
+
|
38
|
+
# Keys in env hash which will get cleared between requests
|
39
|
+
ENV_TO_CLEAR = Set.new [:status, :response, :response_headers]
|
40
|
+
|
41
|
+
# Default value for max redirects followed
|
42
|
+
FOLLOW_LIMIT = 3
|
43
|
+
|
44
|
+
# Regex that matches characters that need to be escaped in URLs, sans
|
45
|
+
# the "%" character which we assume already represents an escaped
|
46
|
+
# sequence.
|
47
|
+
URI_UNSAFE = /[^\-_.!~*'()a-zA-Z\d;\/?:@&=+$,\[\]%]/
|
48
|
+
|
49
|
+
# Public: Initialize the middleware.
|
50
|
+
#
|
51
|
+
# options - An options Hash (default: {}):
|
52
|
+
# :limit - A Integer redirect limit (default: 3).
|
53
|
+
def initialize(app, options = {})
|
54
|
+
super(app)
|
55
|
+
@options = options
|
56
|
+
|
57
|
+
@convert_to_get = Set.new [303]
|
58
|
+
end
|
59
|
+
|
60
|
+
def call(env)
|
61
|
+
perform_with_redirection(env, follow_limit)
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def convert_to_get?(response)
|
67
|
+
![:head, :options].include?(response.env[:method]) &&
|
68
|
+
@convert_to_get.include?(response.status)
|
69
|
+
end
|
70
|
+
|
71
|
+
def perform_with_redirection(env, follows)
|
72
|
+
request_body = env[:body]
|
73
|
+
response = @app.call(env)
|
74
|
+
|
75
|
+
response.on_complete do |response_env|
|
76
|
+
if follow_redirect?(response_env, response)
|
77
|
+
raise(RedirectLimitReached, response) if follows.zero?
|
78
|
+
new_request_env = update_env(response_env, request_body, response)
|
79
|
+
response = perform_with_redirection(new_request_env, follows - 1)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
response
|
83
|
+
end
|
84
|
+
|
85
|
+
def update_env(env, request_body, response)
|
86
|
+
original_url = env[:url]
|
87
|
+
env[:url] += safe_escape(response["location"])
|
88
|
+
unless same_host?(original_url, env[:url])
|
89
|
+
env[:request_headers].delete("Authorization")
|
90
|
+
end
|
91
|
+
|
92
|
+
if convert_to_get?(response)
|
93
|
+
env[:method] = :get
|
94
|
+
env[:body] = nil
|
95
|
+
else
|
96
|
+
env[:body] = request_body
|
97
|
+
end
|
98
|
+
|
99
|
+
ENV_TO_CLEAR.each { |key| env.delete(key) }
|
100
|
+
|
101
|
+
env
|
102
|
+
end
|
103
|
+
|
104
|
+
def follow_redirect?(env, response)
|
105
|
+
ALLOWED_METHODS.include?(env[:method]) &&
|
106
|
+
REDIRECT_CODES.include?(response.status)
|
107
|
+
end
|
108
|
+
|
109
|
+
def follow_limit
|
110
|
+
@options.fetch(:limit, FOLLOW_LIMIT)
|
111
|
+
end
|
112
|
+
|
113
|
+
def same_host?(original_url, redirect_url)
|
114
|
+
original_uri = Addressable::URI.parse(original_url)
|
115
|
+
redirect_uri = Addressable::URI.parse(redirect_url)
|
116
|
+
|
117
|
+
redirect_uri.host.nil? || original_uri.host == redirect_uri.host
|
118
|
+
end
|
119
|
+
|
120
|
+
# Internal: Escapes unsafe characters from a URL which might be a path
|
121
|
+
# component only or a fully-qualified URI so that it can be joined onto a
|
122
|
+
# URI:HTTP using the `+` operator. Doesn't escape "%" characters so to not
|
123
|
+
# risk double-escaping.
|
124
|
+
def safe_escape(uri)
|
125
|
+
uri.to_s.gsub(URI_UNSAFE) { |match|
|
126
|
+
"%" + match.unpack("H2" * match.bytesize).join("%").upcase
|
127
|
+
}
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Octokit
|
2
|
+
# GitHub organization class to generate API path urls
|
3
|
+
class Organization
|
4
|
+
# Get the api path for an organization
|
5
|
+
#
|
6
|
+
# @param org [String, Integer] GitHub organization login or id
|
7
|
+
# @return [String] Organization Api path
|
8
|
+
def self.path org
|
9
|
+
case org
|
10
|
+
when String
|
11
|
+
"orgs/#{org}"
|
12
|
+
when Integer
|
13
|
+
"organizations/#{org}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Octokit
|
2
|
+
|
3
|
+
# Default setup options for preview features
|
4
|
+
module Preview
|
5
|
+
|
6
|
+
PREVIEW_TYPES = {
|
7
|
+
:branch_protection => 'application/vnd.github.loki-preview+json'.freeze,
|
8
|
+
:migrations => 'application/vnd.github.wyandotte-preview+json'.freeze,
|
9
|
+
:licenses => 'application/vnd.github.drax-preview+json'.freeze,
|
10
|
+
:source_imports => 'application/vnd.github.barred-rock-preview'.freeze,
|
11
|
+
:reactions => 'application/vnd.github.squirrel-girl-preview'.freeze,
|
12
|
+
:repository_invitations => 'application/vnd.github.swamp-thing-preview+json'.freeze,
|
13
|
+
:issue_timelines => 'application/vnd.github.mockingbird-preview+json'.freeze,
|
14
|
+
:pages => 'application/vnd.github.mister-fantastic-preview+json'.freeze,
|
15
|
+
:projects => 'application/vnd.github.inertia-preview+json'.freeze,
|
16
|
+
:traffic => 'application/vnd.github.spiderman-preview'.freeze,
|
17
|
+
:org_membership => 'application/vnd.github.korra-preview'.freeze,
|
18
|
+
:reviews => 'application/vnd.github.black-cat-preview'.freeze,
|
19
|
+
:integrations => 'application/vnd.github.machine-man-preview+json'.freeze
|
20
|
+
}
|
21
|
+
|
22
|
+
def ensure_api_media_type(type, options)
|
23
|
+
if options[:accept].nil?
|
24
|
+
options[:accept] = PREVIEW_TYPES[type]
|
25
|
+
warn_preview(type)
|
26
|
+
end
|
27
|
+
options
|
28
|
+
end
|
29
|
+
|
30
|
+
def warn_preview(type)
|
31
|
+
octokit_warn <<-EOS
|
32
|
+
WARNING: The preview version of the #{type.to_s.capitalize} API is not yet suitable for production use.
|
33
|
+
You can avoid this message by supplying an appropriate media type in the 'Accept' request
|
34
|
+
header.
|
35
|
+
EOS
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Octokit
|
2
|
+
|
3
|
+
# Class for API Rate Limit info
|
4
|
+
#
|
5
|
+
# @!attribute [w] limit
|
6
|
+
# @return [Integer] Max tries per rate limit period
|
7
|
+
# @!attribute [w] remaining
|
8
|
+
# @return [Integer] Remaining tries per rate limit period
|
9
|
+
# @!attribute [w] resets_at
|
10
|
+
# @return [Time] Indicates when rate limit resets
|
11
|
+
# @!attribute [w] resets_in
|
12
|
+
# @return [Integer] Number of seconds when rate limit resets
|
13
|
+
#
|
14
|
+
# @see https://developer.github.com/v3/#rate-limiting
|
15
|
+
class RateLimit < Struct.new(:limit, :remaining, :resets_at, :resets_in)
|
16
|
+
|
17
|
+
# Get rate limit info from HTTP response
|
18
|
+
#
|
19
|
+
# @param response [#headers] HTTP response
|
20
|
+
# @return [RateLimit]
|
21
|
+
def self.from_response(response)
|
22
|
+
info = new
|
23
|
+
if response && !response.headers.nil?
|
24
|
+
info.limit = (response.headers['X-RateLimit-Limit'] || 1).to_i
|
25
|
+
info.remaining = (response.headers['X-RateLimit-Remaining'] || 1).to_i
|
26
|
+
info.resets_at = Time.at((response.headers['X-RateLimit-Reset'] || Time.now).to_i)
|
27
|
+
info.resets_in = [(info.resets_at - Time.now).to_i, 0].max
|
28
|
+
end
|
29
|
+
|
30
|
+
info
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Octokit
|
2
|
+
|
3
|
+
# Class to extract options from Ruby arguments for
|
4
|
+
# Repository-related methods
|
5
|
+
class RepoArguments < Arguments
|
6
|
+
|
7
|
+
# !@attribute [r] repo
|
8
|
+
# @return [Repository]
|
9
|
+
attr_reader :repo
|
10
|
+
|
11
|
+
def initialize(args)
|
12
|
+
arguments = super(args)
|
13
|
+
@repo = arguments.shift
|
14
|
+
|
15
|
+
arguments
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module Octokit
|
2
|
+
|
3
|
+
# Class to parse GitHub repository owner and name from
|
4
|
+
# URLs and to generate URLs
|
5
|
+
class Repository
|
6
|
+
attr_accessor :owner, :name, :id
|
7
|
+
NAME_WITH_OWNER_PATTERN = /\A[\w.-]+\/[\w.-]+\z/i
|
8
|
+
|
9
|
+
# Instantiate from a GitHub repository URL
|
10
|
+
#
|
11
|
+
# @return [Repository]
|
12
|
+
def self.from_url(url)
|
13
|
+
new URI.parse(url).path[1..-1].
|
14
|
+
gsub(/^repos\//,'').
|
15
|
+
split('/', 3)[0..1].
|
16
|
+
join('/')
|
17
|
+
end
|
18
|
+
|
19
|
+
# @raise [Octokit::InvalidRepository] if the repository
|
20
|
+
# has an invalid format
|
21
|
+
def initialize(repo)
|
22
|
+
case repo
|
23
|
+
when Integer
|
24
|
+
@id = repo
|
25
|
+
when NAME_WITH_OWNER_PATTERN
|
26
|
+
@owner, @name = repo.split("/")
|
27
|
+
when Repository
|
28
|
+
@owner = repo.owner
|
29
|
+
@name = repo.name
|
30
|
+
when Hash
|
31
|
+
@name = repo[:repo] ||= repo[:name]
|
32
|
+
@owner = repo[:owner] ||= repo[:user] ||= repo[:username]
|
33
|
+
else
|
34
|
+
raise_invalid_repository!
|
35
|
+
end
|
36
|
+
if @owner && @name
|
37
|
+
validate_owner_and_name!
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Repository owner/name
|
42
|
+
# @return [String]
|
43
|
+
def slug
|
44
|
+
"#{@owner}/#{@name}"
|
45
|
+
end
|
46
|
+
alias :to_s :slug
|
47
|
+
|
48
|
+
# @return [String] Repository API path
|
49
|
+
def path
|
50
|
+
return named_api_path if @owner && @name
|
51
|
+
return id_api_path if @id
|
52
|
+
end
|
53
|
+
|
54
|
+
# Get the api path for a repo
|
55
|
+
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
|
56
|
+
# @return [String] Api path.
|
57
|
+
def self.path repo
|
58
|
+
new(repo).path
|
59
|
+
end
|
60
|
+
|
61
|
+
# @return [String] Api path for owner/name identified repos
|
62
|
+
def named_api_path
|
63
|
+
"repos/#{slug}"
|
64
|
+
end
|
65
|
+
|
66
|
+
# @return [String] Api path for id identified repos
|
67
|
+
def id_api_path
|
68
|
+
"repositories/#{@id}"
|
69
|
+
end
|
70
|
+
|
71
|
+
# Repository URL based on {Octokit::Client#web_endpoint}
|
72
|
+
# @return [String]
|
73
|
+
def url
|
74
|
+
"#{Octokit.web_endpoint}#{slug}"
|
75
|
+
end
|
76
|
+
|
77
|
+
alias :user :owner
|
78
|
+
alias :username :owner
|
79
|
+
alias :repo :name
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def validate_owner_and_name!
|
84
|
+
if @owner.include?('/') || @name.include?('/') || !url.match(URI::ABS_URI)
|
85
|
+
raise_invalid_repository!
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def raise_invalid_repository!
|
90
|
+
raise Octokit::InvalidRepository, "Invalid Repository. Use user/repo format."
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
module Octokit
|
4
|
+
|
5
|
+
module Response
|
6
|
+
|
7
|
+
# Parses RSS and Atom feed responses.
|
8
|
+
class FeedParser < Faraday::Response::Middleware
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def on_complete(env)
|
13
|
+
if env[:response_headers]["content-type"] =~ /(\batom|\brss)/
|
14
|
+
require 'rss'
|
15
|
+
env[:body] = RSS::Parser.parse env[:body]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'octokit/error'
|
3
|
+
|
4
|
+
module Octokit
|
5
|
+
# Faraday response middleware
|
6
|
+
module Response
|
7
|
+
|
8
|
+
# This class raises an Octokit-flavored exception based
|
9
|
+
# HTTP status codes returned by the API
|
10
|
+
class RaiseError < Faraday::Response::Middleware
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def on_complete(response)
|
15
|
+
if error = Octokit::Error.from_response(response)
|
16
|
+
raise error
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/octokit/user.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module Octokit
|
2
|
+
# GitHub user class to generate API path urls
|
3
|
+
class User
|
4
|
+
# Get the api path for a user
|
5
|
+
#
|
6
|
+
# @param user [String, Integer] GitHub user login or id
|
7
|
+
# @return [String] User Api path
|
8
|
+
def self.path user
|
9
|
+
case user
|
10
|
+
when String
|
11
|
+
"users/#{user}"
|
12
|
+
when Integer
|
13
|
+
"user/#{user}"
|
14
|
+
else
|
15
|
+
"user"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Octokit
|
2
|
+
# Current major release.
|
3
|
+
# @return [Integer]
|
4
|
+
MAJOR = 4
|
5
|
+
|
6
|
+
# Current minor release.
|
7
|
+
# @return [Integer]
|
8
|
+
MINOR = 6
|
9
|
+
|
10
|
+
# Current patch level.
|
11
|
+
# @return [Integer]
|
12
|
+
PATCH = 2
|
13
|
+
|
14
|
+
# Full release version.
|
15
|
+
# @return [String]
|
16
|
+
VERSION = [MAJOR, MINOR, PATCH].join('.').freeze
|
17
|
+
end
|