octokit 2.1.1 → 2.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 45f3f29fd88cdbbacdaee29a925b50d458d2557b
4
+ data.tar.gz: 3ddfd44d5073cefef0c7944568cd06f5ece20db3
5
+ SHA512:
6
+ metadata.gz: 8350be3c9efbd2eb298d4322f37986f2a4c7edb4e4a84e66995f501cae68335fb2d826aaaea87eb78268722d60b23f1f77fcc01f786961c91639e0ddc0989f1e
7
+ data.tar.gz: d02327fef9bdad88627bf29a49b130e9c865b4661cc1704582aef7f692565b9886ebd60f97bc6b4a9729eddb02aae16a91054cde76e3430fececee80a63bd982
data/README.md CHANGED
@@ -190,6 +190,37 @@ user = client.users 'defunkt'
190
190
  [access scopes]: http://developer.github.com/v3/oauth/#scopes
191
191
  [app-creds]: http://developer.github.com/v3/#unauthenticated-rate-limited-requests
192
192
 
193
+ ## Pagination
194
+
195
+ Many GitHub API resources are [paginated][]. While you may be tempted to start
196
+ adding `:page` parameters to your calls, the API returns links to the next,
197
+ previous, and last pages for you in the `Link` response header as [Hypermedia
198
+ link relations](docs/hypermedia.md).
199
+
200
+ ```ruby
201
+ issues = Octokit.issues 'rails/rails', :per_page => 100
202
+ issues.concat Octokit.last_response.rels[:next].get.data
203
+ ```
204
+
205
+ ### Auto pagination
206
+
207
+ For smallish resource lists, Octokit provides auto pagination. When this is
208
+ enabled, calls for paginated resources will fetch and concatenate the results
209
+ from every page into a single array:
210
+
211
+ ```ruby
212
+ Octokit.auto_paginate = true
213
+ issues = Octokit.issues 'rails/rails'
214
+ issues.length
215
+
216
+ # => 702
217
+ ```
218
+
219
+ **Note:** While Octokit auto pagination will set the page size to the maximum
220
+ `100`, and seek to not overstep your rate limit, you probably want to use a
221
+ custom pattern for traversing large lists.
222
+
223
+ [paginated]: http://developer.github.com/v3/#pagination
193
224
 
194
225
  ## Configuration and defaults
195
226
 
@@ -21,7 +21,6 @@ module Octokit
21
21
  paginate 'authorizations', options
22
22
  end
23
23
 
24
-
25
24
  # Get a single authorization for the authenticated user.
26
25
  #
27
26
  # You can only access your own tokens, and only through
@@ -90,7 +90,6 @@ module Octokit
90
90
  def delete_commit_comment(repo, id, options = {})
91
91
  boolean_from_response :delete, "repos/#{Repository.new(repo)}/comments/#{id}", options
92
92
  end
93
-
94
93
  end
95
94
  end
96
95
  end
@@ -31,7 +31,7 @@ module Octokit
31
31
  alias :list_commits :commits
32
32
 
33
33
  # Get commits after a specified date
34
-
34
+ #
35
35
  # @overload commits_since(repo, date, options = {})
36
36
  # @param repo [String, Hash, Repository] A GitHub repository
37
37
  # @param date [String] Date on which we want to compare
@@ -311,7 +311,6 @@ module Octokit
311
311
  rescue ArgumentError
312
312
  raise ArgumentError, "#{date} is not a valid date"
313
313
  end
314
-
315
314
  end
316
315
  end
317
316
  end
@@ -155,7 +155,6 @@ module Octokit
155
155
 
156
156
  last_response.headers['Location']
157
157
  end
158
-
159
158
  end
160
159
  end
161
160
  end
@@ -84,6 +84,7 @@ module Octokit
84
84
  end
85
85
 
86
86
  private
87
+
87
88
  def create_download_resource(repo, name, size, options={})
88
89
  post "repos/#{Repository.new(repo)}/downloads", options.merge({:name => name, :size => size})
89
90
  end
@@ -3,6 +3,7 @@ module Octokit
3
3
 
4
4
  # Methods for the the unpublished Emojis API
5
5
  module Emojis
6
+
6
7
  # List all emojis used on GitHub
7
8
  #
8
9
  # @return [Sawyer::Resource] A list of all emojis on GitHub
@@ -6,6 +6,7 @@ module Octokit
6
6
  # @see http://developer.github.com/v3/activity/events/
7
7
  # @see http://developer.github.com/v3/issues/events/
8
8
  module Events
9
+
9
10
  # List all public events for GitHub
10
11
  #
11
12
  # @return [Array<Sawyer::Resource>] A list of all public events from GitHub
@@ -141,7 +142,6 @@ module Octokit
141
142
  def issue_event(repo, number, options = {})
142
143
  paginate "repos/#{Repository.new(repo)}/issues/events/#{number}", options
143
144
  end
144
-
145
145
  end
146
146
  end
147
147
  end
@@ -200,7 +200,6 @@ module Octokit
200
200
  def delete_gist_comment(gist_id, gist_comment_id, options = {})
201
201
  boolean_from_response(:delete, "gists/#{gist_id}/comments/#{gist_comment_id}", options)
202
202
  end
203
-
204
203
  end
205
204
  end
206
205
  end
@@ -27,7 +27,7 @@ module Octokit
27
27
  # the raw contents.
28
28
  #
29
29
  # @param template_name [String] Name of the template. Template names are
30
- # case sensitive, make sure to use a valid name from the
30
+ # case sensitive, make sure to use a valid name from the
31
31
  # .gitignore_templates list.
32
32
  #
33
33
  # @see http://developer.github.com/v3/gitignore/#get-a-single-template
@@ -39,7 +39,6 @@ module Octokit
39
39
  def gitignore_template(template_name, options = {})
40
40
  get "gitignore/templates/#{template_name}", options
41
41
  end
42
-
43
42
  end
44
43
  end
45
44
  end
@@ -151,7 +151,6 @@ module Octokit
151
151
  def labels_for_milestone(repo, number, options = {})
152
152
  get "repos/#{Repository.new(repo)}/milestones/#{number}/labels", options
153
153
  end
154
-
155
154
  end
156
155
  end
157
156
  end
@@ -37,7 +37,6 @@ module Octokit
37
37
  def legacy_search_users(search, options = {})
38
38
  get("legacy/user/search/#{search}", options)['users']
39
39
  end
40
-
41
40
  end
42
41
  end
43
42
  end
@@ -22,7 +22,6 @@ module Octokit
22
22
 
23
23
  post "markdown", options
24
24
  end
25
-
26
25
  end
27
26
  end
28
27
  end
@@ -85,7 +85,6 @@ module Octokit
85
85
  def delete_milestone(repository, number, options = {})
86
86
  boolean_from_response :delete, "repos/#{Repository.new(repository)}/milestones/#{number}", options
87
87
  end
88
-
89
88
  end
90
89
  end
91
90
  end
@@ -166,7 +166,6 @@ module Octokit
166
166
  def delete_thread_subscription(thread_id, options = {})
167
167
  boolean_from_response :delete, "notifications/threads/#{thread_id}/subscription", options
168
168
  end
169
-
170
169
  end
171
170
  end
172
171
  end
@@ -5,6 +5,7 @@ module Octokit
5
5
  #
6
6
  # @see http://developer.github.com/v3/git/
7
7
  module Objects
8
+
8
9
  # Get a single tree, fetching information about its root-level objects
9
10
  #
10
11
  # Pass <tt>:recursive => true</tt> in <tt>options</tt> to fetch information about all of the tree's objects, including those in subdirectories.
@@ -5,6 +5,7 @@ module Octokit
5
5
  #
6
6
  # @see http://developer.github.com/v3/orgs/
7
7
  module Organizations
8
+
8
9
  # Get an organization
9
10
  #
10
11
  # @param org [String] Organization GitHub username.
@@ -57,7 +58,7 @@ module Octokit
57
58
  #
58
59
  # Calling this method on a `@client` will return that users organizations.
59
60
  # Private organizations are included only if the `@client` is authenticated.
60
- #
61
+ #
61
62
  # @param user [String] Username of the user to get list of organizations.
62
63
  # @return [Array<Sawyer::Resource>] Array of hashes representing organizations.
63
64
  # @see http://developer.github.com/v3/orgs/#list-user-organizations
@@ -193,17 +194,17 @@ module Octokit
193
194
 
194
195
  # Create team
195
196
  #
196
- # Requires authenticated organization owner.
197
+ # Requires authenticated organization owner.
197
198
  #
198
199
  # @param org [String] Organization GitHub username.
199
200
  # @option options [String] :name Team name.
200
201
  # @option options [Array<String>] :repo_names Repositories for the team.
201
202
  # @option options [String, optional] :permission ('pull') Permissions the
202
- # team has for team repositories.
203
+ # team has for team repositories.
203
204
  #
204
- # `pull` - team members can pull, but not push to or administer these repositories.
205
- # `push` - team members can pull and push, but not administer these repositories.
206
- # `admin` - team members can pull, push and administer these repositories.
205
+ # `pull` - team members can pull, but not push to or administer these repositories.
206
+ # `push` - team members can pull and push, but not administer these repositories.
207
+ # `admin` - team members can pull, push and administer these repositories.
207
208
  # @return [Sawyer::Resource] Hash representing new team.
208
209
  # @see http://developer.github.com/v3/orgs/teams/#create-team
209
210
  # @example
@@ -235,10 +236,10 @@ module Octokit
235
236
  #
236
237
  # @param team_id [Integer] Team id.
237
238
  # @option options [String] :name Team name.
238
- # @option options [String] :permission Permissions the team has for team repositories.
239
+ # @option options [String] :permission Permissions the team has for team repositories.
239
240
  #
240
- # `pull` - team members can pull, but not push to or administer these repositories.
241
- # `push` - team members can pull and push, but not administer these repositories.
241
+ # `pull` - team members can pull, but not push to or administer these repositories.
242
+ # `push` - team members can pull and push, but not administer these repositories.
242
243
  # `admin` - team members can pull, push and administer these repositories.
243
244
  # @return [Sawyer::Resource] Hash representing updated team.
244
245
  # @see http://developer.github.com/v3/orgs/teams/#edit-team
@@ -279,7 +280,7 @@ module Octokit
279
280
 
280
281
  # Add team member
281
282
  #
282
- # Requires authenticated organization owner or member with team
283
+ # Requires authenticated organization owner or member with team
283
284
  # `admin` permission.
284
285
  #
285
286
  # @param team_id [Integer] Team id.
@@ -297,7 +298,7 @@ module Octokit
297
298
 
298
299
  # Remove team member
299
300
  #
300
- # Requires authenticated organization owner or member with team
301
+ # Requires authenticated organization owner or member with team
301
302
  # `admin` permission.
302
303
  #
303
304
  # @param team_id [Integer] Team id.
@@ -5,6 +5,7 @@ module Octokit
5
5
  #
6
6
  # @see http://developer.github.com/v3/repos/hooks/#pubsubhubbub
7
7
  module PubSubHubbub
8
+
8
9
  # Subscribe to a pubsub topic
9
10
  #
10
11
  # @param topic [String] A recoginized and supported pubsub topic
@@ -55,7 +56,7 @@ module Octokit
55
56
  # client.subscribe_service_hook('joshk/device_imapable', 'Travis', { :token => "test", :domain => "domain", :user => "user" })
56
57
  def subscribe_service_hook(repo, service_name, service_arguments = {})
57
58
  topic = "#{Octokit.web_endpoint}#{Repository.new(repo)}/events/push"
58
- callback = "github://#{service_name}?#{service_arguments.collect{ |k,v| [ k,v ].join("=") }.join("&") }"
59
+ callback = "github://#{service_name}?#{service_arguments.collect{ |k,v| [ k,v ].map{ |p| URI.encode_www_form_component(p) }.join("=") }.join("&") }"
59
60
  subscribe(topic, callback)
60
61
  end
61
62
 
@@ -76,7 +77,7 @@ module Octokit
76
77
  private
77
78
 
78
79
  def pub_sub_hubbub_request(options = {})
79
- # This method is janky, bypass normal stack so we don'tl
80
+ # This method is janky, bypass normal stack so we don'tl
80
81
  # serialize request as JSON
81
82
  conn = Faraday.new(:url => @api_endpoint) do |http|
82
83
  http.headers[:user_agent] = user_agent
@@ -5,6 +5,7 @@ module Octokit
5
5
  #
6
6
  # @see http://developer.github.com/v3/pulls/
7
7
  module PullRequests
8
+
8
9
  # List pull requests for a repository
9
10
  #
10
11
  # @see http://developer.github.com/v3/pulls/#list-pull-requests
@@ -6,7 +6,6 @@ module Octokit
6
6
  # @see http://developer.github.com/v3/repos/
7
7
  module Repositories
8
8
 
9
-
10
9
  # Check if a repository exists
11
10
  #
12
11
  # @see http://developer.github.com/v3/repos/#get
@@ -647,7 +646,6 @@ module Octokit
647
646
  def delete_subscription(repo, options = {})
648
647
  boolean_from_response :delete, "repos/#{Repository.new repo}/subscription", options
649
648
  end
650
-
651
649
  end
652
650
  end
653
651
  end
@@ -33,7 +33,6 @@ module Octokit
33
33
  def github_status_messages
34
34
  get(STATUS_ROOT).rels[:messages].get.data
35
35
  end
36
-
37
36
  end
38
37
  end
39
38
  end
@@ -6,82 +6,81 @@ module Octokit
6
6
  # @see http://developer.github.com/v3/repos/statistics/
7
7
  module Stats
8
8
 
9
- # Get contributors list with additions, deletions, and commit counts
10
- #
11
- # @param repo [String, Hash, Repository] A GitHub repository
12
- # @return [Array<Sawyer::Resource>] Array of contributor stats
13
- # @see http://developer.github.com/v3/repos/statistics/#get-contributors-list-with-additions-deletions-and-commit-counts
14
- # @example Get contributor stats for octokit
15
- # @client.contributors_stats('octokit/octokit.rb')
16
- def contributors_stats(repo, options = {})
17
- get_stats(repo, "contributors", options)
18
- end
19
- alias :contributor_stats :contributors_stats
9
+ # Get contributors list with additions, deletions, and commit counts
10
+ #
11
+ # @param repo [String, Hash, Repository] A GitHub repository
12
+ # @return [Array<Sawyer::Resource>] Array of contributor stats
13
+ # @see http://developer.github.com/v3/repos/statistics/#get-contributors-list-with-additions-deletions-and-commit-counts
14
+ # @example Get contributor stats for octokit
15
+ # @client.contributors_stats('octokit/octokit.rb')
16
+ def contributors_stats(repo, options = {})
17
+ get_stats(repo, "contributors", options)
18
+ end
19
+ alias :contributor_stats :contributors_stats
20
20
 
21
- # Get the last year of commit activity data
22
- #
23
- # @param repo [String, Hash, Repository] A GitHub repository
24
- # @return [Array<Sawyer::Resource>] The last year of commit activity grouped by
25
- # week. The days array is a group of commits per day, starting on Sunday.
26
- # @see http://developer.github.com/v3/repos/statistics/#get-the-last-year-of-commit-activity-data
27
- # @example Get commit activity for octokit
28
- # @client.commit_activity_stats('octokit/octokit.rb')
29
- def commit_activity_stats(repo, options = {})
30
- get_stats(repo, "commit_activity", options)
31
- end
21
+ # Get the last year of commit activity data
22
+ #
23
+ # @param repo [String, Hash, Repository] A GitHub repository
24
+ # @return [Array<Sawyer::Resource>] The last year of commit activity grouped by
25
+ # week. The days array is a group of commits per day, starting on Sunday.
26
+ # @see http://developer.github.com/v3/repos/statistics/#get-the-last-year-of-commit-activity-data
27
+ # @example Get commit activity for octokit
28
+ # @client.commit_activity_stats('octokit/octokit.rb')
29
+ def commit_activity_stats(repo, options = {})
30
+ get_stats(repo, "commit_activity", options)
31
+ end
32
32
 
33
- # Get the number of additions and deletions per week
34
- #
35
- # @param repo [String, Hash, Repository] A GitHub repository
36
- # @return [Array<Sawyer::Resource>] Weekly aggregate of the number of additions
37
- # and deletions pushed to a repository.
38
- # @see http://developer.github.com/v3/repos/statistics/#get-the-number-of-additions-and-deletions-per-week
39
- # @example Get code frequency stats for octokit
40
- # @client.code_frequency_stats('octokit/octokit.rb')
41
- def code_frequency_stats(repo, options = {})
42
- get_stats(repo, "code_frequency", options)
43
- end
33
+ # Get the number of additions and deletions per week
34
+ #
35
+ # @param repo [String, Hash, Repository] A GitHub repository
36
+ # @return [Array<Sawyer::Resource>] Weekly aggregate of the number of additions
37
+ # and deletions pushed to a repository.
38
+ # @see http://developer.github.com/v3/repos/statistics/#get-the-number-of-additions-and-deletions-per-week
39
+ # @example Get code frequency stats for octokit
40
+ # @client.code_frequency_stats('octokit/octokit.rb')
41
+ def code_frequency_stats(repo, options = {})
42
+ get_stats(repo, "code_frequency", options)
43
+ end
44
44
 
45
- # Get the weekly commit count for the repo owner and everyone else
46
- #
47
- # @param repo [String, Hash, Repository] A GitHub repository
48
- # @return [Sawyer::Resource] Total commit counts for the owner and total commit
49
- # counts in all. all is everyone combined, including the owner in the last
50
- # 52 weeks. If you’d like to get the commit counts for non-owners, you can
51
- # subtract all from owner.
52
- # @see http://developer.github.com/v3/repos/statistics/#get-the-weekly-commit-count-for-the-repo-owner-and-everyone-else
53
- # @example Get weekly commit counts for octokit
54
- # @client.participation_stats("octokit/octokit.rb")
55
- def participation_stats(repo, options = {})
56
- get_stats(repo, "participation", options)
57
- end
58
-
59
- # Get the number of commits per hour in each day
60
- #
61
- # @param repo [String, Hash, Repository] A GitHub repository
62
- # @return [Array<Array>] Arrays containing the day number, hour number, and
63
- # number of commits
64
- # @see http://developer.github.com/v3/repos/statistics/#get-the-number-of-commits-per-hour-in-each-day
65
- # @example Get octokit punch card
66
- # @octokit.punch_card_stats
67
- def punch_card_stats(repo, options = {})
68
- get_stats(repo, "punch_card", options)
69
- end
70
- alias :punch_card :punch_card_stats
45
+ # Get the weekly commit count for the repo owner and everyone else
46
+ #
47
+ # @param repo [String, Hash, Repository] A GitHub repository
48
+ # @return [Sawyer::Resource] Total commit counts for the owner and total commit
49
+ # counts in all. all is everyone combined, including the owner in the last
50
+ # 52 weeks. If you’d like to get the commit counts for non-owners, you can
51
+ # subtract all from owner.
52
+ # @see http://developer.github.com/v3/repos/statistics/#get-the-weekly-commit-count-for-the-repo-owner-and-everyone-else
53
+ # @example Get weekly commit counts for octokit
54
+ # @client.participation_stats("octokit/octokit.rb")
55
+ def participation_stats(repo, options = {})
56
+ get_stats(repo, "participation", options)
57
+ end
71
58
 
72
- private
59
+ # Get the number of commits per hour in each day
60
+ #
61
+ # @param repo [String, Hash, Repository] A GitHub repository
62
+ # @return [Array<Array>] Arrays containing the day number, hour number, and
63
+ # number of commits
64
+ # @see http://developer.github.com/v3/repos/statistics/#get-the-number-of-commits-per-hour-in-each-day
65
+ # @example Get octokit punch card
66
+ # @octokit.punch_card_stats
67
+ def punch_card_stats(repo, options = {})
68
+ get_stats(repo, "punch_card", options)
69
+ end
70
+ alias :punch_card :punch_card_stats
73
71
 
74
- # @private Get stats for a repository
75
- #
76
- # @param repo [String, Hash, Repository] A GitHub repository
77
- # @param metric [String] The metrics you are looking for
78
- # @return [Array<Sawyer::Resource>] Magical unicorn stats
79
- def get_stats(repo, metric, options = {})
80
- data = get("repos/#{Repository.new repo}/stats/#{metric}", options)
72
+ private
81
73
 
82
- last_response.status == 202 ? nil : data
83
- end
74
+ # @private Get stats for a repository
75
+ #
76
+ # @param repo [String, Hash, Repository] A GitHub repository
77
+ # @param metric [String] The metrics you are looking for
78
+ # @return [Array<Sawyer::Resource>] Magical unicorn stats
79
+ def get_stats(repo, metric, options = {})
80
+ data = get("repos/#{Repository.new repo}/stats/#{metric}", options)
84
81
 
82
+ last_response.status == 202 ? nil : data
83
+ end
85
84
  end
86
85
  end
87
86
  end
@@ -110,7 +110,7 @@ module Octokit
110
110
  get "users/#{user}/following", options
111
111
  end
112
112
 
113
- # Check if you are following a user. Alternatively, check if a given user
113
+ # Check if you are following a user. Alternatively, check if a given user
114
114
  # is following a target user.
115
115
  #
116
116
  # Requries an authenticated client.
@@ -182,14 +182,21 @@ module Octokit
182
182
  #
183
183
  # Requires authenticated client.
184
184
  #
185
- # @param user [String] Username of repository owner.
186
- # @param repo [String] Name of the repository.
185
+ # @param args [String, Hash, Repository] A GitHub repository
187
186
  # @return [Boolean] True if you are following the repo, false otherwise.
188
187
  # @see http://developer.github.com/v3/repos/starring/#check-if-you-are-starring-a-repository
189
188
  # @example
190
- # @client.starred?('pengwynn', 'octokit')
191
- def starred?(user, repo, options = {})
192
- boolean_from_response :get, "user/starred/#{user}/#{repo}", options
189
+ # @client.starred?('pengwynn/octokit')
190
+ # @client.starred?('pengwynn', 'octokit') # deprecated
191
+ def starred?(*args)
192
+ arguments = Octokit::Arguments.new(args)
193
+ options = arguments.options
194
+ name = name_with_owner = arguments.shift
195
+ if repo = arguments.shift
196
+ name_with_owner = "#{name}/#{repo}"
197
+ warn "`.starred?('#{name}', '#{repo}')` is deprecated. Please use `.starred?('#{name_with_owner}')` instead."
198
+ end
199
+ boolean_from_response :get, "user/starred/#{Repository.new name_with_owner}", options
193
200
  end
194
201
 
195
202
  # Get a public key.
@@ -13,28 +13,19 @@ module Octokit
13
13
  headers = response[:response_headers]
14
14
 
15
15
  if klass = case status
16
- when 400 then Octokit::BadRequest
17
- when 401
18
- if Octokit::OneTimePasswordRequired.required_header(headers)
19
- Octokit::OneTimePasswordRequired
20
- else
21
- Octokit::Unauthorized
22
- end
23
- when 403
24
- if body =~ /rate limit exceeded/i
25
- Octokit::TooManyRequests
26
- elsif body =~ /login attempts exceeded/i
27
- Octokit::TooManyLoginAttempts
28
- else
29
- Octokit::Forbidden
30
- end
31
- when 404 then Octokit::NotFound
32
- when 406 then Octokit::NotAcceptable
33
- when 422 then Octokit::UnprocessableEntity
34
- when 500 then Octokit::InternalServerError
35
- when 501 then Octokit::NotImplemented
36
- when 502 then Octokit::BadGateway
37
- when 503 then Octokit::ServiceUnavailable
16
+ when 400 then Octokit::BadRequest
17
+ when 401 then error_for_401(headers)
18
+ when 403 then error_for_403(body)
19
+ when 404 then Octokit::NotFound
20
+ when 406 then Octokit::NotAcceptable
21
+ when 415 then Octokit::UnsupportedMediaType
22
+ when 422 then Octokit::UnprocessableEntity
23
+ when 400..499 then Octokit::ClientError
24
+ when 500 then Octokit::InternalServerError
25
+ when 501 then Octokit::NotImplemented
26
+ when 502 then Octokit::BadGateway
27
+ when 503 then Octokit::ServiceUnavailable
28
+ when 500..599 then Octokit::ServerError
38
29
  end
39
30
  klass.new(response)
40
31
  end
@@ -45,6 +36,35 @@ module Octokit
45
36
  super(build_error_message)
46
37
  end
47
38
 
39
+ # Documentation URL returned by the API for some errors
40
+ #
41
+ # @return [String]
42
+ def documentation_url
43
+ data[:documentation_url] if data
44
+ end
45
+
46
+ # Returns most appropriate error for 401 HTTP status code
47
+ # @private
48
+ def self.error_for_401(headers)
49
+ if Octokit::OneTimePasswordRequired.required_header(headers)
50
+ Octokit::OneTimePasswordRequired
51
+ else
52
+ Octokit::Unauthorized
53
+ end
54
+ end
55
+
56
+ # Returns most appropriate error for 403 HTTP status code
57
+ # @private
58
+ def self.error_for_403(body)
59
+ if body =~ /rate limit exceeded/i
60
+ Octokit::TooManyRequests
61
+ elsif body =~ /login attempts exceeded/i
62
+ Octokit::TooManyLoginAttempts
63
+ else
64
+ Octokit::Forbidden
65
+ end
66
+ end
67
+
48
68
  private
49
69
 
50
70
  def data
@@ -96,32 +116,41 @@ module Octokit
96
116
  message << "#{response_message}" unless response_message.nil?
97
117
  message << "#{response_error}" unless response_error.nil?
98
118
  message << "#{response_error_summary}" unless response_error_summary.nil?
119
+ message << " // See: #{documentation_url}" unless documentation_url.nil?
99
120
  message
100
121
  end
101
122
  end
102
123
 
124
+ # Raised on errors in the 400-499 range
125
+ class ClientError < Error; end
126
+
103
127
  # Raised when GitHub returns a 400 HTTP status code
104
- class BadRequest < Error; end
128
+ class BadRequest < ClientError; end
105
129
 
106
130
  # Raised when GitHub returns a 401 HTTP status code
107
- class Unauthorized < Error; end
131
+ class Unauthorized < ClientError; end
108
132
 
109
133
  # Raised when GitHub returns a 401 HTTP status code
110
134
  # and headers include "X-GitHub-OTP"
111
- class OneTimePasswordRequired < Error
135
+ class OneTimePasswordRequired < ClientError
136
+ #@private
112
137
  HEADER = /required; (?<delivery>\w+)/i
113
138
 
139
+ #@private
114
140
  def self.required_header(headers)
115
141
  HEADER.match headers['X-GitHub-OTP'].to_s
116
142
  end
117
143
 
144
+ # Delivery method for the user's OTP
145
+ #
146
+ # @return [String]
118
147
  def password_delivery
119
148
  @password_delivery ||= self.class.required_header(@response[:response_headers])[:delivery]
120
149
  end
121
150
  end
122
151
 
123
152
  # Raised when GitHub returns a 403 HTTP status code
124
- class Forbidden < Error; end
153
+ class Forbidden < ClientError; end
125
154
 
126
155
  # Raised when GitHub returns a 403 HTTP status code
127
156
  # and body matches 'rate limit exceeded'
@@ -132,23 +161,29 @@ module Octokit
132
161
  class TooManyLoginAttempts < Forbidden; end
133
162
 
134
163
  # Raised when GitHub returns a 404 HTTP status code
135
- class NotFound < Error; end
164
+ class NotFound < ClientError; end
136
165
 
137
166
  # Raised when GitHub returns a 406 HTTP status code
138
- class NotAcceptable < Error; end
167
+ class NotAcceptable < ClientError; end
168
+
169
+ # Raised when GitHub returns a 414 HTTP status code
170
+ class UnsupportedMediaType < ClientError; end
139
171
 
140
172
  # Raised when GitHub returns a 422 HTTP status code
141
- class UnprocessableEntity < Error; end
173
+ class UnprocessableEntity < ClientError; end
174
+
175
+ # Raised on errors in the 500-599 range
176
+ class ServerError < Error; end
142
177
 
143
178
  # Raised when GitHub returns a 500 HTTP status code
144
- class InternalServerError < Error; end
179
+ class InternalServerError < ServerError; end
145
180
 
146
181
  # Raised when GitHub returns a 501 HTTP status code
147
- class NotImplemented < Error; end
182
+ class NotImplemented < ServerError; end
148
183
 
149
184
  # Raised when GitHub returns a 502 HTTP status code
150
- class BadGateway < Error; end
185
+ class BadGateway < ServerError; end
151
186
 
152
187
  # Raised when GitHub returns a 503 HTTP status code
153
- class ServiceUnavailable < Error; end
188
+ class ServiceUnavailable < ServerError; end
154
189
  end
@@ -2,6 +2,6 @@ module Octokit
2
2
 
3
3
  # Current version
4
4
  # @return [String]
5
- VERSION = "2.1.1".freeze
5
+ VERSION = "2.1.2".freeze
6
6
 
7
7
  end
@@ -5,7 +5,7 @@ require 'octokit/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.add_development_dependency 'bundler', '~> 1.0'
8
- spec.add_dependency 'sawyer', '~> 0.3.0'
8
+ spec.add_dependency 'sawyer', '~> 0.5.0'
9
9
  spec.authors = ["Wynn Netherland", "Erik Michaels-Ober", "Clint Shryock"]
10
10
  spec.description = %q{Simple wrapper for the GitHub API}
11
11
  spec.email = ['wynn.netherland@gmail.com', 'sferik@gmail.com', 'clint@ctshryock.com']
@@ -0,0 +1 @@
1
+ {"http_interactions":[{"request":{"method":"get","uri":"https://api.github.com/user/starred/sferik/rails_admin","body":{"encoding":"US-ASCII","base64_string":""},"headers":{"Accept":["application/vnd.github.beta+json"],"User-Agent":["Octokit Ruby Gem 2.1.1"],"Authorization":["token <<ACCESS_TOKEN>>"],"Accept-Encoding":["gzip;q=1.0,deflate;q=0.6,identity;q=0.3"]}},"response":{"status":{"code":404,"message":"Not Found"},"headers":{"Server":["GitHub.com"],"Date":["Sun, 08 Sep 2013 15:01:28 GMT"],"Content-Type":["application/json; charset=utf-8"],"Transfer-Encoding":["chunked"],"Status":["404 Not Found"],"X-Ratelimit-Limit":["5000"],"X-Ratelimit-Remaining":["4995"],"X-Ratelimit-Reset":["1378654817"],"X-Oauth-Scopes":["user, public_repo, repo, gist"],"X-Accepted-Oauth-Scopes":["repo, public_repo, repo:status, repo:deployment, delete_repo, site_admin"],"X-Github-Media-Type":["github.beta; format=json"],"X-Content-Type-Options":["nosniff"],"Access-Control-Allow-Credentials":["true"],"Access-Control-Expose-Headers":["ETag, Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes"],"Access-Control-Allow-Origin":["*"],"X-Github-Request-Id":["fec2764a-0d89-4c63-8645-0c8f89a4294b"]},"body":{"encoding":"UTF-8","base64_string":"eyJtZXNzYWdlIjoiTm90IEZvdW5kIn0=\n"},"http_version":null},"recorded_at":"Sun, 08 Sep 2013 15:01:28 GMT"}],"recorded_with":"VCR 2.4.0"}
@@ -60,6 +60,18 @@ describe Octokit::Client::PubSubHubbub do
60
60
  assert_requested :post, github_url("/hub"), :body => subscribe_request_body, :times => 1,
61
61
  :headers => {'Content-type' => 'application/x-www-form-urlencoded'}
62
62
  end
63
+ it "encodes URL parameters" do
64
+ irc_request_body = {
65
+ :"hub.callback" => 'github://irc?server=chat.freenode.org&room=%23myproject',
66
+ :"hub.mode" => 'subscribe',
67
+ :"hub.topic" => 'https://github.com/joshk/completeness-fu/events/push'
68
+ }
69
+ stub_post("/hub").
70
+ with(irc_request_body).
71
+ to_return(:status => 204)
72
+ expect(@client.subscribe_service_hook("joshk/completeness-fu", "irc", { :server => "chat.freenode.org", :room => "#myproject"})).to eql(true)
73
+ assert_requested :post, "https://api.github.com/hub", :body => irc_request_body, :times => 1
74
+ end
63
75
  end # .subscribe_service_hook
64
76
 
65
77
  describe "unsubscribe_service_hook", :vcr do
@@ -93,6 +93,10 @@ describe Octokit::Client::Users do
93
93
 
94
94
  describe ".starred?", :vcr do
95
95
  it "checks if the authenticated user has starred a repository" do
96
+ starred = @client.starred?("sferik/rails_admin")
97
+ assert_requested :get, github_url("/user/starred/sferik/rails_admin")
98
+ end
99
+ it "checks if the authenticated user has starred a repository (deprecated)" do
96
100
  starred = @client.starred?("sferik", "rails_admin")
97
101
  assert_requested :get, github_url("/user/starred/sferik/rails_admin")
98
102
  end
@@ -478,6 +478,45 @@ describe Octokit::Client do
478
478
  :body => {:message => "Maximum number of login attempts exceeded"}.to_json
479
479
  expect { Octokit.get('/user') }.to raise_error Octokit::TooManyLoginAttempts
480
480
  end
481
+
482
+ it "raises on unknown client errors" do
483
+ stub_get('/user').to_return \
484
+ :status => 418,
485
+ :headers => {
486
+ :content_type => "application/json",
487
+ },
488
+ :body => {:message => "I'm a teapot"}.to_json
489
+ expect { Octokit.get('/user') }.to raise_error Octokit::ClientError
490
+ end
491
+
492
+ it "raises on unknown server errors" do
493
+ stub_get('/user').to_return \
494
+ :status => 509,
495
+ :headers => {
496
+ :content_type => "application/json",
497
+ },
498
+ :body => {:message => "Bandwidth exceeded"}.to_json
499
+ expect { Octokit.get('/user') }.to raise_error Octokit::ServerError
500
+ end
501
+
502
+ it "handles documentation URLs in error messages" do
503
+ stub_get('/user').to_return \
504
+ :status => 415,
505
+ :headers => {
506
+ :content_type => "application/json",
507
+ },
508
+ :body => {
509
+ :message => "Unsupported Media Type",
510
+ :documentation_url => "http://developer.github.com/v3"
511
+ }.to_json
512
+ begin
513
+ Octokit.get('/user')
514
+ rescue Octokit::UnsupportedMediaType => e
515
+ msg = "415 - Unsupported Media Type"
516
+ expect(e.message).to include(msg)
517
+ expect(e.documentation_url).to eq("http://developer.github.com/v3")
518
+ end
519
+ end
481
520
  end
482
521
 
483
522
  it "knows the difference between unauthorized and needs OTP" do
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: octokit
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
5
- prerelease:
4
+ version: 2.1.2
6
5
  platform: ruby
7
6
  authors:
8
7
  - Wynn Netherland
@@ -11,12 +10,11 @@ authors:
11
10
  autorequire:
12
11
  bindir: bin
13
12
  cert_chain: []
14
- date: 2013-09-03 00:00:00.000000000 Z
13
+ date: 2013-09-22 00:00:00.000000000 Z
15
14
  dependencies:
16
15
  - !ruby/object:Gem::Dependency
17
16
  name: bundler
18
17
  requirement: !ruby/object:Gem::Requirement
19
- none: false
20
18
  requirements:
21
19
  - - ~>
22
20
  - !ruby/object:Gem::Version
@@ -24,7 +22,6 @@ dependencies:
24
22
  type: :development
25
23
  prerelease: false
26
24
  version_requirements: !ruby/object:Gem::Requirement
27
- none: false
28
25
  requirements:
29
26
  - - ~>
30
27
  - !ruby/object:Gem::Version
@@ -32,19 +29,17 @@ dependencies:
32
29
  - !ruby/object:Gem::Dependency
33
30
  name: sawyer
34
31
  requirement: !ruby/object:Gem::Requirement
35
- none: false
36
32
  requirements:
37
33
  - - ~>
38
34
  - !ruby/object:Gem::Version
39
- version: 0.3.0
35
+ version: 0.5.0
40
36
  type: :runtime
41
37
  prerelease: false
42
38
  version_requirements: !ruby/object:Gem::Requirement
43
- none: false
44
39
  requirements:
45
40
  - - ~>
46
41
  - !ruby/object:Gem::Version
47
- version: 0.3.0
42
+ version: 0.5.0
48
43
  description: Simple wrapper for the GitHub API
49
44
  email:
50
45
  - wynn.netherland@gmail.com
@@ -370,6 +365,7 @@ files:
370
365
  - spec/cassettes/Octokit_Client_Users/_starred/returns_starred_repositories_for_a_user.json
371
366
  - spec/cassettes/Octokit_Client_Users/_starred/returns_starred_repositories_for_the_authenticated_user.json
372
367
  - spec/cassettes/Octokit_Client_Users/_starred_/checks_if_the_authenticated_user_has_starred_a_repository.json
368
+ - spec/cassettes/Octokit_Client_Users/_starred_/checks_if_the_authenticated_user_has_starred_a_repository_deprecated_.json
373
369
  - spec/cassettes/Octokit_Client_Users/_subscriptions/returns_the_repositories_a_user_watches_for_notifications.json
374
370
  - spec/cassettes/Octokit_Client_Users/_subscriptions/returns_the_repositories_the_authenticated_user_watches_for_notifications.json
375
371
  - spec/cassettes/Octokit_Client_Users/_unfollow/unfollows_a_user.json
@@ -426,27 +422,26 @@ files:
426
422
  homepage: https://github.com/octokit/octokit.rb
427
423
  licenses:
428
424
  - MIT
425
+ metadata: {}
429
426
  post_install_message:
430
427
  rdoc_options: []
431
428
  require_paths:
432
429
  - lib
433
430
  required_ruby_version: !ruby/object:Gem::Requirement
434
- none: false
435
431
  requirements:
436
- - - ! '>='
432
+ - - '>='
437
433
  - !ruby/object:Gem::Version
438
434
  version: '0'
439
435
  required_rubygems_version: !ruby/object:Gem::Requirement
440
- none: false
441
436
  requirements:
442
- - - ! '>='
437
+ - - '>='
443
438
  - !ruby/object:Gem::Version
444
439
  version: 1.3.5
445
440
  requirements: []
446
441
  rubyforge_project:
447
- rubygems_version: 1.8.23
442
+ rubygems_version: 2.0.3
448
443
  signing_key:
449
- specification_version: 3
444
+ specification_version: 4
450
445
  summary: Ruby toolkit for working with the GitHub API
451
446
  test_files:
452
447
  - spec/cassettes/delete_authorization.json
@@ -717,6 +712,7 @@ test_files:
717
712
  - spec/cassettes/Octokit_Client_Users/_starred/returns_starred_repositories_for_a_user.json
718
713
  - spec/cassettes/Octokit_Client_Users/_starred/returns_starred_repositories_for_the_authenticated_user.json
719
714
  - spec/cassettes/Octokit_Client_Users/_starred_/checks_if_the_authenticated_user_has_starred_a_repository.json
715
+ - spec/cassettes/Octokit_Client_Users/_starred_/checks_if_the_authenticated_user_has_starred_a_repository_deprecated_.json
720
716
  - spec/cassettes/Octokit_Client_Users/_subscriptions/returns_the_repositories_a_user_watches_for_notifications.json
721
717
  - spec/cassettes/Octokit_Client_Users/_subscriptions/returns_the_repositories_the_authenticated_user_watches_for_notifications.json
722
718
  - spec/cassettes/Octokit_Client_Users/_unfollow/unfollows_a_user.json