github_api2 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +770 -0
- data/LICENSE.txt +20 -0
- data/README.md +741 -0
- data/lib/github_api2/api/actions.rb +60 -0
- data/lib/github_api2/api/arguments.rb +253 -0
- data/lib/github_api2/api/config/property.rb +30 -0
- data/lib/github_api2/api/config/property_set.rb +120 -0
- data/lib/github_api2/api/config.rb +105 -0
- data/lib/github_api2/api/factory.rb +33 -0
- data/lib/github_api2/api.rb +398 -0
- data/lib/github_api2/authorization.rb +75 -0
- data/lib/github_api2/client/activity/events.rb +233 -0
- data/lib/github_api2/client/activity/feeds.rb +50 -0
- data/lib/github_api2/client/activity/notifications.rb +181 -0
- data/lib/github_api2/client/activity/starring.rb +130 -0
- data/lib/github_api2/client/activity/watching.rb +176 -0
- data/lib/github_api2/client/activity.rb +31 -0
- data/lib/github_api2/client/authorizations/app.rb +98 -0
- data/lib/github_api2/client/authorizations.rb +142 -0
- data/lib/github_api2/client/emojis.rb +19 -0
- data/lib/github_api2/client/gists/comments.rb +100 -0
- data/lib/github_api2/client/gists.rb +289 -0
- data/lib/github_api2/client/git_data/blobs.rb +51 -0
- data/lib/github_api2/client/git_data/commits.rb +101 -0
- data/lib/github_api2/client/git_data/references.rb +150 -0
- data/lib/github_api2/client/git_data/tags.rb +95 -0
- data/lib/github_api2/client/git_data/trees.rb +113 -0
- data/lib/github_api2/client/git_data.rb +31 -0
- data/lib/github_api2/client/gitignore.rb +57 -0
- data/lib/github_api2/client/issues/assignees.rb +77 -0
- data/lib/github_api2/client/issues/comments.rb +146 -0
- data/lib/github_api2/client/issues/events.rb +50 -0
- data/lib/github_api2/client/issues/labels.rb +189 -0
- data/lib/github_api2/client/issues/milestones.rb +146 -0
- data/lib/github_api2/client/issues.rb +248 -0
- data/lib/github_api2/client/markdown.rb +62 -0
- data/lib/github_api2/client/meta.rb +19 -0
- data/lib/github_api2/client/orgs/hooks.rb +182 -0
- data/lib/github_api2/client/orgs/members.rb +142 -0
- data/lib/github_api2/client/orgs/memberships.rb +131 -0
- data/lib/github_api2/client/orgs/projects.rb +57 -0
- data/lib/github_api2/client/orgs/teams.rb +407 -0
- data/lib/github_api2/client/orgs.rb +127 -0
- data/lib/github_api2/client/projects/cards.rb +158 -0
- data/lib/github_api2/client/projects/columns.rb +146 -0
- data/lib/github_api2/client/projects.rb +83 -0
- data/lib/github_api2/client/pull_requests/comments.rb +140 -0
- data/lib/github_api2/client/pull_requests/reviews.rb +158 -0
- data/lib/github_api2/client/pull_requests.rb +195 -0
- data/lib/github_api2/client/repos/branches/protections.rb +75 -0
- data/lib/github_api2/client/repos/branches.rb +48 -0
- data/lib/github_api2/client/repos/collaborators.rb +84 -0
- data/lib/github_api2/client/repos/comments.rb +125 -0
- data/lib/github_api2/client/repos/commits.rb +80 -0
- data/lib/github_api2/client/repos/contents.rb +263 -0
- data/lib/github_api2/client/repos/deployments.rb +138 -0
- data/lib/github_api2/client/repos/downloads.rb +62 -0
- data/lib/github_api2/client/repos/forks.rb +50 -0
- data/lib/github_api2/client/repos/hooks.rb +214 -0
- data/lib/github_api2/client/repos/invitations.rb +41 -0
- data/lib/github_api2/client/repos/keys.rb +104 -0
- data/lib/github_api2/client/repos/merging.rb +47 -0
- data/lib/github_api2/client/repos/pages.rb +48 -0
- data/lib/github_api2/client/repos/projects.rb +62 -0
- data/lib/github_api2/client/repos/pub_sub_hubbub.rb +133 -0
- data/lib/github_api2/client/repos/releases/assets.rb +136 -0
- data/lib/github_api2/client/repos/releases/tags.rb +24 -0
- data/lib/github_api2/client/repos/releases.rb +189 -0
- data/lib/github_api2/client/repos/statistics.rb +89 -0
- data/lib/github_api2/client/repos/statuses.rb +91 -0
- data/lib/github_api2/client/repos.rb +473 -0
- data/lib/github_api2/client/say.rb +25 -0
- data/lib/github_api2/client/scopes.rb +46 -0
- data/lib/github_api2/client/search/legacy.rb +111 -0
- data/lib/github_api2/client/search.rb +133 -0
- data/lib/github_api2/client/users/emails.rb +65 -0
- data/lib/github_api2/client/users/followers.rb +115 -0
- data/lib/github_api2/client/users/keys.rb +104 -0
- data/lib/github_api2/client/users.rb +117 -0
- data/lib/github_api2/client.rb +77 -0
- data/lib/github_api2/configuration.rb +70 -0
- data/lib/github_api2/connection.rb +82 -0
- data/lib/github_api2/constants.rb +61 -0
- data/lib/github_api2/core_ext/array.rb +25 -0
- data/lib/github_api2/core_ext/hash.rb +91 -0
- data/lib/github_api2/deprecation.rb +39 -0
- data/lib/github_api2/error/client_error.rb +89 -0
- data/lib/github_api2/error/service_error.rb +223 -0
- data/lib/github_api2/error.rb +32 -0
- data/lib/github_api2/ext/faraday.rb +40 -0
- data/lib/github_api2/mash.rb +7 -0
- data/lib/github_api2/middleware.rb +37 -0
- data/lib/github_api2/mime_type.rb +33 -0
- data/lib/github_api2/normalizer.rb +23 -0
- data/lib/github_api2/null_encoder.rb +25 -0
- data/lib/github_api2/page_iterator.rb +138 -0
- data/lib/github_api2/page_links.rb +63 -0
- data/lib/github_api2/paged_request.rb +42 -0
- data/lib/github_api2/pagination.rb +115 -0
- data/lib/github_api2/parameter_filter.rb +35 -0
- data/lib/github_api2/params_hash.rb +115 -0
- data/lib/github_api2/rate_limit.rb +25 -0
- data/lib/github_api2/request/basic_auth.rb +36 -0
- data/lib/github_api2/request/jsonize.rb +54 -0
- data/lib/github_api2/request/oauth2.rb +45 -0
- data/lib/github_api2/request/verbs.rb +63 -0
- data/lib/github_api2/request.rb +84 -0
- data/lib/github_api2/response/atom_parser.rb +22 -0
- data/lib/github_api2/response/follow_redirects.rb +140 -0
- data/lib/github_api2/response/header.rb +87 -0
- data/lib/github_api2/response/jsonize.rb +28 -0
- data/lib/github_api2/response/mashify.rb +24 -0
- data/lib/github_api2/response/raise_error.rb +22 -0
- data/lib/github_api2/response/xmlize.rb +28 -0
- data/lib/github_api2/response.rb +48 -0
- data/lib/github_api2/response_wrapper.rb +161 -0
- data/lib/github_api2/ssl_certs/cacerts.pem +2183 -0
- data/lib/github_api2/utils/url.rb +63 -0
- data/lib/github_api2/validations/format.rb +26 -0
- data/lib/github_api2/validations/presence.rb +32 -0
- data/lib/github_api2/validations/required.rb +21 -0
- data/lib/github_api2/validations/token.rb +41 -0
- data/lib/github_api2/validations.rb +22 -0
- data/lib/github_api2/version.rb +5 -0
- data/lib/github_api2.rb +92 -0
- metadata +363 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require_relative 'response'
|
|
4
|
+
require_relative 'response/mashify'
|
|
5
|
+
require_relative 'response/jsonize'
|
|
6
|
+
require_relative 'response/atom_parser'
|
|
7
|
+
require_relative 'response/raise_error'
|
|
8
|
+
require_relative 'response/header'
|
|
9
|
+
require_relative 'response/follow_redirects'
|
|
10
|
+
|
|
11
|
+
module Github
|
|
12
|
+
class Middleware
|
|
13
|
+
def self.default(options = {})
|
|
14
|
+
api = options[:api]
|
|
15
|
+
proc do |builder|
|
|
16
|
+
builder.use Github::Request::Jsonize
|
|
17
|
+
builder.use Faraday::Request::Multipart
|
|
18
|
+
builder.use Faraday::Request::UrlEncoded
|
|
19
|
+
builder.use Github::Request::OAuth2, api.oauth_token if api.oauth_token?
|
|
20
|
+
builder.use Github::Request::BasicAuth, api.authentication if api.basic_authed?
|
|
21
|
+
|
|
22
|
+
builder.use Github::Response::FollowRedirects if api.follow_redirects
|
|
23
|
+
builder.use Faraday::Response::Logger if ENV['DEBUG']
|
|
24
|
+
unless options[:raw]
|
|
25
|
+
builder.use Github::Response::Mashify
|
|
26
|
+
builder.use Github::Response::Jsonize
|
|
27
|
+
builder.use Github::Response::AtomParser
|
|
28
|
+
end
|
|
29
|
+
if api.stack
|
|
30
|
+
api.stack.call(builder)
|
|
31
|
+
end
|
|
32
|
+
builder.use Github::Response::RaiseError
|
|
33
|
+
builder.adapter options[:adapter]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end # Middleware
|
|
37
|
+
end # Github
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Github
|
|
4
|
+
module MimeType
|
|
5
|
+
|
|
6
|
+
MEDIA_LOOKUP = {
|
|
7
|
+
'json' => 'json',
|
|
8
|
+
'blob' => 'raw',
|
|
9
|
+
'raw' => 'raw+json',
|
|
10
|
+
'text' => 'text+json',
|
|
11
|
+
'html' => 'html+json',
|
|
12
|
+
'full' => 'full+json'
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
# Parse media type param
|
|
16
|
+
#
|
|
17
|
+
def parse(media)
|
|
18
|
+
version = 'v3'
|
|
19
|
+
media.sub!(/^[.]*|[.]*$/,"")
|
|
20
|
+
media = media.include?('+') ? media.split('+')[0] : media
|
|
21
|
+
version, media = media.split('.') if media.include?('.')
|
|
22
|
+
media_type = lookup_media(media)
|
|
23
|
+
"application/vnd.github.#{version}.#{media_type}"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def lookup_media(name)
|
|
27
|
+
MEDIA_LOOKUP.fetch(name) do
|
|
28
|
+
raise ArgumentError, "Provided Media Type #{name} is not valid"
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end # MimeType
|
|
33
|
+
end # Github
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# encoding: utf-8
|
|
3
|
+
|
|
4
|
+
module Github
|
|
5
|
+
# Normalize client-supplied parameter keys.
|
|
6
|
+
module Normalizer
|
|
7
|
+
# Turns any keys from nested hashes including nested arrays into strings
|
|
8
|
+
def normalize!(params)
|
|
9
|
+
case params
|
|
10
|
+
when Hash
|
|
11
|
+
params.keys.each do |k|
|
|
12
|
+
params[k.to_s] = params.delete(k)
|
|
13
|
+
normalize!(params[k.to_s])
|
|
14
|
+
end
|
|
15
|
+
when Array
|
|
16
|
+
params.map! do |el|
|
|
17
|
+
normalize!(el)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
params
|
|
21
|
+
end
|
|
22
|
+
end # Normalizer
|
|
23
|
+
end # Github
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'faraday'
|
|
4
|
+
|
|
5
|
+
module Github
|
|
6
|
+
|
|
7
|
+
# Skip encoding of the key nested parameters
|
|
8
|
+
module NullParamsEncoder
|
|
9
|
+
if defined?(Faraday::NestedParamsEncoder)
|
|
10
|
+
class << self
|
|
11
|
+
Faraday::NestedParamsEncoder.singleton_methods do |m|
|
|
12
|
+
define_method m, ::Faraday::NestedParamsEncoder.method(m).to_proc
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.escape(s)
|
|
18
|
+
s.to_s
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.unescape(s)
|
|
22
|
+
s.to_s
|
|
23
|
+
end
|
|
24
|
+
end # NullEncoder
|
|
25
|
+
end # Github
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'uri'
|
|
4
|
+
|
|
5
|
+
require_relative 'constants'
|
|
6
|
+
require_relative 'paged_request'
|
|
7
|
+
require_relative 'utils/url'
|
|
8
|
+
|
|
9
|
+
module Github
|
|
10
|
+
# A class responsible for requesting resources through page links
|
|
11
|
+
#
|
|
12
|
+
# @api private
|
|
13
|
+
class PageIterator
|
|
14
|
+
include Github::Constants
|
|
15
|
+
include Github::Utils::Url
|
|
16
|
+
include Github::PagedRequest
|
|
17
|
+
|
|
18
|
+
# Setup attribute accesor for all the link types
|
|
19
|
+
ATTRIBUTES = [META_FIRST, META_NEXT, META_PREV, META_LAST]
|
|
20
|
+
|
|
21
|
+
DEFAULT_SHA = 'master'
|
|
22
|
+
|
|
23
|
+
ATTRIBUTES.each do |attr|
|
|
24
|
+
attr_accessor :"#{attr}_page_uri", :"#{attr}_page"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
attr_reader :current_api
|
|
28
|
+
|
|
29
|
+
def initialize(links, current_api)
|
|
30
|
+
@links = links
|
|
31
|
+
@current_api = current_api
|
|
32
|
+
update_page_links(@links)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def next?
|
|
36
|
+
next_page == 0 || !next_page_uri.nil?
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def count
|
|
40
|
+
parse_query(URI(last_page_uri).query)['page'] if last_page_uri
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Perform http get request for the first resource
|
|
44
|
+
#
|
|
45
|
+
def first
|
|
46
|
+
perform_request(first_page_uri) if first_page_uri
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Perform http get request for the next resource
|
|
50
|
+
#
|
|
51
|
+
def next
|
|
52
|
+
perform_request(next_page_uri) if next?
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Perform http get request for the previous resource
|
|
56
|
+
#
|
|
57
|
+
def prev
|
|
58
|
+
perform_request(prev_page_uri) if prev_page_uri
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Perform http get request for the last resource
|
|
62
|
+
#
|
|
63
|
+
def last
|
|
64
|
+
perform_request(last_page_uri) if last_page_uri
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Returns the result for a specific page.
|
|
68
|
+
#
|
|
69
|
+
def get_page(page_number)
|
|
70
|
+
# Find URI that we can work with, if we cannot get the first or the
|
|
71
|
+
# last page URI then there is only one page.
|
|
72
|
+
page_uri = first_page_uri || last_page_uri
|
|
73
|
+
return nil unless page_uri
|
|
74
|
+
|
|
75
|
+
perform_request(page_uri, page_number)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
private
|
|
79
|
+
|
|
80
|
+
def perform_request(page_uri_path, page_number = nil)
|
|
81
|
+
page_uri = URI(page_uri_path)
|
|
82
|
+
params = parse_query(page_uri.query)
|
|
83
|
+
|
|
84
|
+
if page_number
|
|
85
|
+
params['page'] = page_number
|
|
86
|
+
elsif next_page < 1
|
|
87
|
+
sha = sha(params)
|
|
88
|
+
params['sha'] = sha if sha
|
|
89
|
+
else
|
|
90
|
+
params['page'] = parse_page_number(page_uri_path)
|
|
91
|
+
end
|
|
92
|
+
params['per_page'] = parse_per_page_number(page_uri_path)
|
|
93
|
+
|
|
94
|
+
response = page_request(page_uri.path, params)
|
|
95
|
+
update_page_links response.links
|
|
96
|
+
response
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def sha(params)
|
|
100
|
+
return params['last_sha'] if params.keys.include?('last_sha')
|
|
101
|
+
return DEFAULT_SHA if params.keys.include?('sha')
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def parse_per_page_number(uri) # :nodoc:
|
|
105
|
+
parse_page_params(uri, PARAM_PER_PAGE)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def parse_page_number(uri) # :nodoc:
|
|
109
|
+
parse_page_params(uri, PARAM_PAGE)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Extracts query string parameter for given name
|
|
113
|
+
def parse_page_params(uri, attr) # :nodoc:
|
|
114
|
+
return -1 if uri.nil? || uri.empty?
|
|
115
|
+
parsed = nil
|
|
116
|
+
begin
|
|
117
|
+
parsed = URI.parse(uri)
|
|
118
|
+
rescue URI::Error
|
|
119
|
+
return -1
|
|
120
|
+
end
|
|
121
|
+
param = parse_query_for_param(parsed.query, attr)
|
|
122
|
+
return -1 if param.nil? || param.empty?
|
|
123
|
+
begin
|
|
124
|
+
return param.to_i
|
|
125
|
+
rescue ArgumentError
|
|
126
|
+
return -1
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Wholesale update of all link attributes
|
|
131
|
+
def update_page_links(links) # :nodoc:
|
|
132
|
+
ATTRIBUTES.each do |attr|
|
|
133
|
+
send(:"#{attr}_page_uri=", links.send(:"#{attr}"))
|
|
134
|
+
send(:"#{attr}_page=", parse_page_number(links.send(:"#{attr}")))
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end # PageIterator
|
|
138
|
+
end # Github
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require_relative 'constants'
|
|
4
|
+
|
|
5
|
+
module Github
|
|
6
|
+
# Determines the links in the current response link header to be used
|
|
7
|
+
# to find the links to other pages of request responses. These will
|
|
8
|
+
# only be present if the result set size exceeds the per page limit.
|
|
9
|
+
#
|
|
10
|
+
# @api private
|
|
11
|
+
class PageLinks
|
|
12
|
+
include Github::Constants
|
|
13
|
+
|
|
14
|
+
DELIM_LINKS = ','.freeze # :nodoc:
|
|
15
|
+
|
|
16
|
+
# Hold the extracted values for URI from the Link header
|
|
17
|
+
# for the first, last, next and previous page.
|
|
18
|
+
attr_accessor :first, :last, :next, :prev
|
|
19
|
+
|
|
20
|
+
LINK_REGEX = /<([^>]+)>; rel=\"([^\"]+)\"/
|
|
21
|
+
|
|
22
|
+
# Parses links from executed request
|
|
23
|
+
#
|
|
24
|
+
# @param [Hash] response_headers
|
|
25
|
+
#
|
|
26
|
+
# @api private
|
|
27
|
+
def initialize(response_headers)
|
|
28
|
+
link_header = response_headers[HEADER_LINK]
|
|
29
|
+
if link_header && link_header =~ /(next|first|last|prev)/
|
|
30
|
+
extract_links(link_header)
|
|
31
|
+
else
|
|
32
|
+
# When on the first page
|
|
33
|
+
self.next = response_headers[HEADER_NEXT]
|
|
34
|
+
self.last = response_headers[HEADER_LAST]
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def extract_links(link_header)
|
|
41
|
+
link_header.split(DELIM_LINKS).each do |link|
|
|
42
|
+
LINK_REGEX.match(link.strip) do |match|
|
|
43
|
+
url_part, meta_part = match[1], match[2]
|
|
44
|
+
next if !url_part || !meta_part
|
|
45
|
+
assign_url_part(meta_part, url_part)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def assign_url_part(meta_part, url_part)
|
|
51
|
+
case meta_part
|
|
52
|
+
when META_FIRST
|
|
53
|
+
self.first = url_part
|
|
54
|
+
when META_LAST
|
|
55
|
+
self.last = url_part
|
|
56
|
+
when META_NEXT
|
|
57
|
+
self.next = url_part
|
|
58
|
+
when META_PREV
|
|
59
|
+
self.prev = url_part
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end # PageLinks
|
|
63
|
+
end # Github
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require_relative 'constants'
|
|
4
|
+
|
|
5
|
+
module Github
|
|
6
|
+
|
|
7
|
+
# A module that adds http get request to response pagination
|
|
8
|
+
module PagedRequest
|
|
9
|
+
include Github::Constants
|
|
10
|
+
|
|
11
|
+
FIRST_PAGE = 1 # Default request page if none provided
|
|
12
|
+
|
|
13
|
+
PER_PAGE = 30 # Default number of items as specified by API
|
|
14
|
+
|
|
15
|
+
NOT_FOUND = -1 # Either page or per_page parameter not present
|
|
16
|
+
|
|
17
|
+
# Check if current api instance has default per_page param set,
|
|
18
|
+
# otherwise use global default.
|
|
19
|
+
#
|
|
20
|
+
def default_page_size
|
|
21
|
+
current_api.per_page ? current_api.per_page : PER_PAGE
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def default_page
|
|
25
|
+
current_api.page ? current_api.page : FIRST_PAGE
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Perform http get request with pagination parameters
|
|
29
|
+
#
|
|
30
|
+
def page_request(path, params={})
|
|
31
|
+
if params[PARAM_PER_PAGE] == NOT_FOUND
|
|
32
|
+
params[PARAM_PER_PAGE] = default_page_size
|
|
33
|
+
end
|
|
34
|
+
if params[PARAM_PAGE] && params[PARAM_PAGE] == NOT_FOUND
|
|
35
|
+
params[PARAM_PAGE] = default_page
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
current_api.get_request(path, ParamsHash.new(params))
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
end # PagedRequest
|
|
42
|
+
end # Github
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require_relative 'constants'
|
|
4
|
+
require_relative 'page_links'
|
|
5
|
+
require_relative 'page_iterator'
|
|
6
|
+
|
|
7
|
+
module Github
|
|
8
|
+
# A module that decorates response with pagination helpers
|
|
9
|
+
module Pagination
|
|
10
|
+
include Github::Constants
|
|
11
|
+
|
|
12
|
+
# Return page links
|
|
13
|
+
def links
|
|
14
|
+
@links = Github::PageLinks.new(env[:response_headers])
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Retrieve number of total pages base on current :per_page parameter
|
|
18
|
+
def count_pages
|
|
19
|
+
page_iterator.count.to_i
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Iterate over results set pages by automatically calling `next_page`
|
|
23
|
+
# until all pages are exhausted. Caution needs to be exercised when
|
|
24
|
+
# using this feature - 100 pages iteration will perform 100 API calls.
|
|
25
|
+
# By default this is off. You can set it on the client, individual API
|
|
26
|
+
# instances or just per given request.
|
|
27
|
+
#
|
|
28
|
+
def auto_paginate(auto=false)
|
|
29
|
+
if (current_api.auto_pagination? || auto) && self.body.is_a?(Array)
|
|
30
|
+
resources_bodies = []
|
|
31
|
+
each_page { |resource| resources_bodies += resource.body }
|
|
32
|
+
self.body = resources_bodies
|
|
33
|
+
end
|
|
34
|
+
self
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Iterator like each for response pages. If there are no pages to
|
|
38
|
+
# iterate over this method will return current page.
|
|
39
|
+
def each_page
|
|
40
|
+
yield self
|
|
41
|
+
while page_iterator.next?
|
|
42
|
+
yield next_page
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Retrieves the result of the first page. Returns <tt>nil</tt> if there is
|
|
47
|
+
# no first page - either because you are already on the first page
|
|
48
|
+
# or there are no pages at all in the result.
|
|
49
|
+
def first_page
|
|
50
|
+
first_request = page_iterator.first
|
|
51
|
+
self.instance_eval { @env = first_request.env } if first_request
|
|
52
|
+
first_request
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Retrieves the result of the next page. Returns <tt>nil</tt> if there is
|
|
56
|
+
# no next page or no pages at all.
|
|
57
|
+
def next_page
|
|
58
|
+
next_request = page_iterator.next
|
|
59
|
+
self.instance_eval { @env = next_request.env } if next_request
|
|
60
|
+
next_request
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Retrieves the result of the previous page. Returns <tt>nil</tt> if there is
|
|
64
|
+
# no previous page or no pages at all.
|
|
65
|
+
def prev_page
|
|
66
|
+
prev_request = page_iterator.prev
|
|
67
|
+
self.instance_eval { @env = prev_request.env } if prev_request
|
|
68
|
+
prev_request
|
|
69
|
+
end
|
|
70
|
+
alias :previous_page :prev_page
|
|
71
|
+
|
|
72
|
+
# Retrieves the result of the last page. Returns <tt>nil</tt> if there is
|
|
73
|
+
# no last page - either because you are already on the last page,
|
|
74
|
+
# there is only one page or there are no pages at all in the result.
|
|
75
|
+
def last_page
|
|
76
|
+
last_request = page_iterator.last
|
|
77
|
+
self.instance_eval { @env = last_request.env } if last_request
|
|
78
|
+
last_request
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Retrieves a specific result for a page given page number.
|
|
82
|
+
# The <tt>page_number</tt> parameter is not validate, hitting a page
|
|
83
|
+
# that does not exist will return Github API error. Consequently, if
|
|
84
|
+
# there is only one page, this method returns nil
|
|
85
|
+
def page(page_number)
|
|
86
|
+
request = page_iterator.get_page(page_number)
|
|
87
|
+
self.instance_eval { @env = request.env } if request
|
|
88
|
+
request
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Returns <tt>true</tt> if there is another page in the result set,
|
|
92
|
+
# otherwise <tt>false</tt>
|
|
93
|
+
def has_next_page?
|
|
94
|
+
page_iterator.next?
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Handle pagination params when they are not passed directly
|
|
98
|
+
#
|
|
99
|
+
def self.per_page_as_param(per_page_config)
|
|
100
|
+
params = {}
|
|
101
|
+
if (per_page_config != Github::Configuration.property_set[:per_page])
|
|
102
|
+
params[:per_page] = per_page_config unless per_page_config.nil?
|
|
103
|
+
end
|
|
104
|
+
params
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
private
|
|
108
|
+
|
|
109
|
+
# Internally used page iterator
|
|
110
|
+
def page_iterator # :nodoc:
|
|
111
|
+
@page_iterator = Github::PageIterator.new(links, current_api)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
end # Pagination
|
|
115
|
+
end # Github
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require_relative 'params_hash'
|
|
4
|
+
require_relative 'validations'
|
|
5
|
+
|
|
6
|
+
module Github
|
|
7
|
+
# Allows you to specify parameters keys which will be preserved
|
|
8
|
+
# in parameters hash and its subhashes. Any keys from the nested
|
|
9
|
+
# hash that do not match will be removed.
|
|
10
|
+
module ParameterFilter
|
|
11
|
+
|
|
12
|
+
# Removes any keys from nested hashes that don't match predefiend keys
|
|
13
|
+
#
|
|
14
|
+
def filter!(keys, params, options={:recursive => true}) # :nodoc:
|
|
15
|
+
case params
|
|
16
|
+
when Hash, ParamsHash
|
|
17
|
+
params.keys.each do |k, v|
|
|
18
|
+
unless (keys.include?(k) or Github::Validations::VALID_API_KEYS.include?(k))
|
|
19
|
+
params.delete(k)
|
|
20
|
+
else
|
|
21
|
+
filter!(keys, params[k]) if options[:recursive]
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
when Array
|
|
25
|
+
params.map! do |el|
|
|
26
|
+
filter!(keys, el) if options[:recursive]
|
|
27
|
+
end
|
|
28
|
+
else
|
|
29
|
+
params
|
|
30
|
+
end
|
|
31
|
+
return params
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end # Filter
|
|
35
|
+
end # Github
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'delegate'
|
|
4
|
+
require 'base64'
|
|
5
|
+
|
|
6
|
+
require_relative 'normalizer'
|
|
7
|
+
require_relative 'mime_type'
|
|
8
|
+
|
|
9
|
+
module Github
|
|
10
|
+
# Class responsible for holding request parameters
|
|
11
|
+
class ParamsHash < DelegateClass(Hash)
|
|
12
|
+
include Normalizer
|
|
13
|
+
include MimeType
|
|
14
|
+
|
|
15
|
+
REQUEST_PARAMS = [:accept, :media, :data, :raw, :headers]
|
|
16
|
+
|
|
17
|
+
def initialize(hash)
|
|
18
|
+
super(normalize!(Hash[hash]))
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Create empty hash
|
|
22
|
+
#
|
|
23
|
+
# @api public
|
|
24
|
+
def self.empty
|
|
25
|
+
new({})
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Extract and parse media type param
|
|
29
|
+
#
|
|
30
|
+
# [.version].param[+json]
|
|
31
|
+
#
|
|
32
|
+
# @api public
|
|
33
|
+
def media
|
|
34
|
+
parse(delete('media'))
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Get accept header
|
|
38
|
+
#
|
|
39
|
+
# @api public
|
|
40
|
+
def accept
|
|
41
|
+
if key?('accept') then self['accept']
|
|
42
|
+
elsif key?('media') then media
|
|
43
|
+
else nil
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Extract request data from parameters
|
|
48
|
+
#
|
|
49
|
+
# @api public
|
|
50
|
+
def data
|
|
51
|
+
if key?('data') && !self['data'].nil?
|
|
52
|
+
self['data']
|
|
53
|
+
else
|
|
54
|
+
request_params
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def encoder
|
|
59
|
+
if key?('encoder') && self['encoder']
|
|
60
|
+
self['encoder']
|
|
61
|
+
else
|
|
62
|
+
{}
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Configuration options from request
|
|
67
|
+
#
|
|
68
|
+
# @return [Hash]
|
|
69
|
+
#
|
|
70
|
+
# @api public
|
|
71
|
+
def options
|
|
72
|
+
opts = fetch('options', {})
|
|
73
|
+
headers = fetch('headers', {})
|
|
74
|
+
if value = accept
|
|
75
|
+
headers[:accept] = value
|
|
76
|
+
end
|
|
77
|
+
opts[:raw] = key?('raw') ? self['raw'] : false
|
|
78
|
+
opts[:headers] = headers unless headers.empty?
|
|
79
|
+
opts
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Update hash with default parameters for non existing keys
|
|
83
|
+
#
|
|
84
|
+
def merge_default(defaults)
|
|
85
|
+
if defaults && !defaults.empty?
|
|
86
|
+
defaults.each do |key, value|
|
|
87
|
+
self[key] = value unless self.key?(key)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
self
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Base64 encode string removing newline characters
|
|
94
|
+
#
|
|
95
|
+
# @api public
|
|
96
|
+
def strict_encode64(key)
|
|
97
|
+
value = self[key]
|
|
98
|
+
encoded = if Base64.respond_to?(:strict_encode64)
|
|
99
|
+
Base64.strict_encode64(value)
|
|
100
|
+
else
|
|
101
|
+
[value].pack('m0')
|
|
102
|
+
end
|
|
103
|
+
self[key] = encoded.delete("\n\r")
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Filter out request params
|
|
107
|
+
#
|
|
108
|
+
# @api public
|
|
109
|
+
def request_params
|
|
110
|
+
to_hash.select do |key, value|
|
|
111
|
+
!REQUEST_PARAMS.include?(key.to_sym)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end # ParamsHash
|
|
115
|
+
end # Github
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Github
|
|
4
|
+
module RateLimit
|
|
5
|
+
|
|
6
|
+
def ratelimit(*args)
|
|
7
|
+
arguments(args)
|
|
8
|
+
|
|
9
|
+
get_request("/rate_limit", arguments.params).rate.limit
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def ratelimit_remaining(*args)
|
|
13
|
+
arguments(args)
|
|
14
|
+
|
|
15
|
+
get_request("/rate_limit", arguments.params).rate.remaining
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def ratelimit_reset(*args)
|
|
19
|
+
arguments(args)
|
|
20
|
+
|
|
21
|
+
get_request("/rate_limit", arguments.params).rate.reset
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end # RateLimit
|
|
25
|
+
end # Github
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'faraday'
|
|
4
|
+
require 'base64'
|
|
5
|
+
|
|
6
|
+
module Github
|
|
7
|
+
class Request
|
|
8
|
+
class BasicAuth < Faraday::Middleware
|
|
9
|
+
# dependency 'base64'
|
|
10
|
+
|
|
11
|
+
# @api private
|
|
12
|
+
def initialize(app, *args)
|
|
13
|
+
@app = app
|
|
14
|
+
@auth = nil
|
|
15
|
+
options = args.extract_options!
|
|
16
|
+
|
|
17
|
+
if options.key?(:login) && !options[:login].nil?
|
|
18
|
+
credentials = "#{options[:login]}:#{options[:password]}"
|
|
19
|
+
@auth = Base64.encode64(credentials)
|
|
20
|
+
@auth.gsub!("\n", "")
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Update request headers
|
|
25
|
+
#
|
|
26
|
+
# @api private
|
|
27
|
+
def call(env)
|
|
28
|
+
if @auth
|
|
29
|
+
env[:request_headers].merge!('Authorization' => "Basic #{@auth}")
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
@app.call(env)
|
|
33
|
+
end
|
|
34
|
+
end # BasicAuth
|
|
35
|
+
end # Request
|
|
36
|
+
end # Github
|