octodoggy 4.6.2
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/.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
|