octokit 3.8.0 → 4.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.
@@ -153,9 +153,22 @@ module Octokit
153
153
  repo_ref = options.delete :ref
154
154
  format = (options.delete :format) || 'tarball'
155
155
  url = "#{Repository.path repo}/#{format}/#{repo_ref}"
156
- request :head, url, options
157
156
 
158
- last_response.headers['Location']
157
+ conn_opts = @connection_options
158
+ conn_opts[:url] = @api_endpoint
159
+ conn_opts[:builder] = @middleware.dup if @middleware
160
+ conn_opts[:proxy] = @proxy if @proxy
161
+ conn = Faraday.new(conn_opts) do |http|
162
+ if basic_authenticated?
163
+ http.basic_auth(@login, @password)
164
+ elsif token_authenticated?
165
+ http.authorization 'token', @access_token
166
+ end
167
+ end
168
+ conn.builder.delete(Octokit::Middleware::FollowRedirects)
169
+ response = conn.head(url, options)
170
+
171
+ response.headers['Location']
159
172
  end
160
173
  end
161
174
  end
@@ -4,8 +4,6 @@ module Octokit
4
4
  # Methods for the Hooks API
5
5
  module Hooks
6
6
 
7
- ORG_HOOKS_PREVIEW_MEDIA_TYPE = "application/vnd.github.sersi-preview+json".freeze
8
-
9
7
  # List all Service Hooks supported by GitHub
10
8
  #
11
9
  # @return [Sawyer::Resource] A list of all hooks on GitHub
@@ -118,7 +116,7 @@ module Octokit
118
116
  # }
119
117
  # )
120
118
  def edit_hook(repo, id, name, config, options = {})
121
- options = {:name => name, :config => config, :events => ["push"], :active => true}.merge(options)
119
+ options = {:name => name, :config => config}.merge(options)
122
120
  patch "#{Repository.path repo}/hooks/#{id}", options
123
121
  end
124
122
 
@@ -160,7 +158,6 @@ module Octokit
160
158
  # @example
161
159
  # @client.org_hooks('octokit')
162
160
  def org_hooks(org, options = {})
163
- options = ensure_org_hooks_api_media_type(options)
164
161
  paginate "orgs/#{org}/hooks", options
165
162
  end
166
163
  alias :list_org_hooks :org_hooks
@@ -176,7 +173,6 @@ module Octokit
176
173
  # @example
177
174
  # @client.org_hook('octokit', 123)
178
175
  def org_hook(org, id, options = {})
179
- options = ensure_org_hooks_api_media_type(options)
180
176
  get "orgs/#{org}/hooks/#{id}", options
181
177
  end
182
178
 
@@ -207,7 +203,6 @@ module Octokit
207
203
  # }
208
204
  # )
209
205
  def create_org_hook(org, config, options = {})
210
- options = ensure_org_hooks_api_media_type(options)
211
206
  options = { :name => "web", :config => config }.merge(options)
212
207
  post "orgs/#{org}/hooks", options
213
208
  end
@@ -241,7 +236,6 @@ module Octokit
241
236
  # }
242
237
  # )
243
238
  def edit_org_hook(org, id, config, options = {})
244
- options = ensure_org_hooks_api_media_type(options)
245
239
  options = { :config => config }.merge(options)
246
240
  patch "orgs/#{org}/hooks/#{id}", options
247
241
  end
@@ -258,7 +252,6 @@ module Octokit
258
252
  # @example
259
253
  # @client.ping_org_hook('octokit', 1000000)
260
254
  def ping_org_hook(org, id, options = {})
261
- options = ensure_org_hooks_api_media_type(options)
262
255
  boolean_from_response :post, "orgs/#{org}/hooks/#{id}/pings", options
263
256
  end
264
257
 
@@ -273,27 +266,17 @@ module Octokit
273
266
  # @example
274
267
  # @client.remove_org_hook('octokit', 1000000)
275
268
  def remove_org_hook(org, id, options = {})
276
- options = ensure_org_hooks_api_media_type(options)
277
269
  boolean_from_response :delete, "orgs/#{org}/hooks/#{id}", options
278
270
  end
279
271
 
280
- private
281
-
282
- def ensure_org_hooks_api_media_type(options = {})
283
- if options[:accept].nil?
284
- options[:accept] = ORG_HOOKS_PREVIEW_MEDIA_TYPE
285
- warn_org_hooks_preview
286
- end
287
-
288
- options
289
- end
290
-
291
- def warn_org_hooks_preview
292
- octokit_warn <<-EOS
293
- WARNING: The preview version of the Org Hooks API is not yet suitable for production use.
294
- You can avoid this message by supplying an appropriate media type in the 'Accept' request
295
- header. See the blog post for details: http://git.io/uucWqg
296
- EOS
272
+ # Parse payload string
273
+ #
274
+ # @param payload_string [String] The payload
275
+ # @return [Sawyer::Resource] The payload object
276
+ # @see https://developer.github.com/v3/activity/events/types/
277
+ def parse_payload(payload_string)
278
+ payload_hash = agent.class.decode payload_string
279
+ Sawyer::Resource.new agent, payload_hash
297
280
  end
298
281
  end
299
282
  end
@@ -28,7 +28,8 @@ module Octokit
28
28
  # @client = Octokit::Client.new(:login => 'foo', :password => 'bar')
29
29
  # @client.list_issues
30
30
  def list_issues(repository = nil, options = {})
31
- paginate "#{Repository.new(repository).path}/issues", options
31
+ path = repository ? "#{Repository.new(repository).path}/issues" : "issues"
32
+ paginate path, options
32
33
  end
33
34
  alias :issues :list_issues
34
35
 
@@ -0,0 +1,50 @@
1
+ module Octokit
2
+ class Client
3
+
4
+ # Methods for licenses API
5
+ #
6
+ module Licenses
7
+
8
+ LICENSES_PREVIEW_MEDIA_TYPE = "application/vnd.github.drax-preview+json".freeze
9
+
10
+ # List all licenses
11
+ #
12
+ # @see https://developer.github.com/v3/licenses/#list-all-licenses
13
+ # @return [Array<Sawyer::Resource>] A list of licenses
14
+ # @example
15
+ # Octokit.licenses
16
+ def licenses(options = {})
17
+ options = ensure_license_api_media_type(options)
18
+ paginate "licenses", options
19
+ end
20
+
21
+ # List an individual license
22
+ #
23
+ # @see https://developer.github.com/v3/licenses/#get-an-individual-license
24
+ # @param license_name [String] The license name
25
+ # @return <Sawyer::Resource> An individual license
26
+ # @example
27
+ # Octokit.license 'mit'
28
+ def license(license_name, options = {})
29
+ options = ensure_license_api_media_type(options)
30
+ get "licenses/#{license_name}", options
31
+ end
32
+
33
+ def ensure_license_api_media_type(options = {})
34
+ if options[:accept].nil?
35
+ options[:accept] = LICENSES_PREVIEW_MEDIA_TYPE
36
+ warn_license_preview
37
+ end
38
+ options
39
+ end
40
+
41
+ def warn_license_preview
42
+ warn <<-EOS
43
+ WARNING: The preview version of the License API is not yet suitable for production use.
44
+ You can avoid this message by supplying an appropriate media type in the 'Accept' request
45
+ header.
46
+ EOS
47
+ end
48
+ end
49
+ end
50
+ end
@@ -44,7 +44,7 @@ module Octokit
44
44
  # @example
45
45
  # @client.update_org('github', {:company => 'Unicorns, Inc.'})
46
46
  def update_organization(org, values, options = {})
47
- patch Organization.path(org), options.merge({:organization => values})
47
+ patch Organization.path(org), options.merge(values)
48
48
  end
49
49
  alias :update_org :update_organization
50
50
 
@@ -76,12 +76,29 @@ module Octokit
76
76
  # @example
77
77
  # @client.organizations
78
78
  def organizations(user=nil, options = {})
79
- get "#{User.path user}/orgs", options
79
+ paginate "#{User.path user}/orgs", options
80
80
  end
81
81
  alias :list_organizations :organizations
82
82
  alias :list_orgs :organizations
83
83
  alias :orgs :organizations
84
84
 
85
+ # List all GitHub organizations
86
+ #
87
+ # This provides a list of every organization, in the order that they
88
+ # were created.
89
+ #
90
+ # @param options [Hash] Optional options.
91
+ # @option options [Integer] :since The integer ID of the last
92
+ # Organization that you’ve seen.
93
+ #
94
+ # @see https://developer.github.com/v3/orgs/#list-all-organizations
95
+ #
96
+ # @return [Array<Sawyer::Resource>] List of GitHub organizations.
97
+ def all_organizations(options = {})
98
+ paginate "organizations"
99
+ end
100
+ alias :all_orgs :all_organizations
101
+
85
102
  # List organization repositories
86
103
  #
87
104
  # Public repositories are available without authentication. Private repos
@@ -535,26 +552,49 @@ module Octokit
535
552
  end
536
553
  alias :org_memberships :organization_memberships
537
554
 
538
- # Get an organization membership for the authenticated user
555
+ # Get an organization membership
539
556
  #
540
557
  # @param org [String] Organization GitHub login.
558
+ # @option options [String] :user The login of the user, otherwise authenticated user.
541
559
  # @return [Sawyer::Resource] Hash representing the organization membership.
542
560
  # @see https://developer.github.com/v3/orgs/members/#get-your-organization-membership
561
+ # @see https://developer.github.com/v3/orgs/members/#get-organization-membership
543
562
  def organization_membership(org, options = {})
544
- get "user/memberships/orgs/#{org}", options
563
+ if user = options.delete(:user)
564
+ get "orgs/#{org}/memberships/#{user}", options
565
+ else
566
+ get "user/memberships/orgs/#{org}", options
567
+ end
545
568
  end
546
569
  alias :org_membership :organization_membership
547
570
 
548
- # Edit an organization membership for the authenticated user
571
+ # Edit an organization membership
549
572
  #
550
573
  # @param org [String] Organization GitHub login.
574
+ # @option options [String] :role The role of the user in the organization.
551
575
  # @option options [String] :state The state that the membership should be in.
576
+ # @option options [String] :user The login of the user, otherwise authenticated user.
552
577
  # @return [Sawyer::Resource] Hash representing the updated organization membership.
553
578
  # @see https://developer.github.com/v3/orgs/members/#edit-your-organization-membership
579
+ # @see https://developer.github.com/v3/orgs/members/#add-or-update-organization-membership
554
580
  def update_organization_membership(org, options = {})
555
- patch "user/memberships/orgs/#{org}", options
581
+ if user = options.delete(:user)
582
+ put "orgs/#{org}/memberships/#{user}", options
583
+ else
584
+ patch "user/memberships/orgs/#{org}", options
585
+ end
556
586
  end
557
587
  alias :update_org_membership :update_organization_membership
588
+
589
+ # Remove an organization membership
590
+ #
591
+ # @param org [String] Organization GitHub login.
592
+ # @return [Boolean] Success
593
+ # @see https://developer.github.com/v3/orgs/members/#remove-organization-membership
594
+ def remove_organization_membership(org, options = {})
595
+ user = options.delete(:user)
596
+ user && boolean_from_response(:delete, "orgs/#{org}/memberships/#{user}", options)
597
+ end
558
598
  end
559
599
  end
560
600
  end
@@ -1,10 +1,3 @@
1
- major, minor, patch = RUBY_VERSION.split('.').map(&:to_i)
2
-
3
- if (major == 1 && minor < 9) || (major == 1 && minor == 9 && patch < 2)
4
- # pull in backports
5
- require 'octokit/backports/uri'
6
- end
7
-
8
1
  module Octokit
9
2
  class Client
10
3
 
@@ -93,7 +86,7 @@ module Octokit
93
86
  private
94
87
 
95
88
  def pub_sub_hubbub_request(options = {})
96
- # This method is janky, bypass normal stack so we don'tl
89
+ # This method is janky, bypass normal stack so we don't
97
90
  # serialize request as JSON
98
91
  conn = Faraday.new(:url => @api_endpoint) do |http|
99
92
  http.headers[:user_agent] = user_agent
@@ -12,24 +12,12 @@ module Octokit
12
12
  # @param repo [Integer, String, Hash, Repository] A GitHub repository
13
13
  # @param options [Hash] Method options
14
14
  # @option options [String] :state `open` or `closed`.
15
- # @overload pull_requests(repo, state, options)
16
- # @deprecated
17
- # @param repo [Integer, String, Hash, Repository] A GitHub repository
18
- # @param state [String] `open` or `closed`.
19
- # @param options [Hash] Method options
20
15
  # @return [Array<Sawyer::Resource>] Array of pulls
21
16
  # @see https://developer.github.com/v3/pulls/#list-pull-requests
22
17
  # @example
23
18
  # Octokit.pull_requests('rails/rails', :state => 'closed')
24
- def pull_requests(*args)
25
- arguments = Arguments.new(args)
26
- opts = arguments.options
27
- repo = arguments.shift
28
- if state = arguments.shift
29
- octokit_warn "DEPRECATED: Client#pull_requests: Passing state as positional argument is deprecated. Please use :state => '#{state}'"
30
- opts[:state] = state if state
31
- end
32
- paginate "#{Repository.path repo}/pulls", opts
19
+ def pull_requests(repo, options = {})
20
+ paginate "#{Repository.path repo}/pulls", options
33
21
  end
34
22
  alias :pulls :pull_requests
35
23
 
@@ -8,7 +8,7 @@ module Octokit
8
8
 
9
9
  # List all GitHub users
10
10
  #
11
- # This provides a dump of every user, in the order that they signed up
11
+ # This provides a list of every user, in the order that they signed up
12
12
  # for GitHub.
13
13
  #
14
14
  # @param options [Hash] Optional options.
@@ -24,6 +24,10 @@ module Octokit
24
24
  # @return [Hash] Configure connection options for Faraday
25
25
  # @!attribute login
26
26
  # @return [String] GitHub username for Basic Authentication
27
+ # @!attribute management_console_password
28
+ # @return [String] An admin password set up for your GitHub Enterprise management console
29
+ # @!attribute management_console_endpoint
30
+ # @return [String] Base URL for API requests to the GitHub Enterprise management console
27
31
  # @!attribute middleware
28
32
  # @see https://github.com/lostisland/faraday
29
33
  # @return [Faraday::Builder or Faraday::RackBuilder] Configure middleware for Faraday
@@ -45,6 +49,7 @@ module Octokit
45
49
 
46
50
  attr_accessor :access_token, :auto_paginate, :client_id,
47
51
  :client_secret, :default_media_type, :connection_options,
52
+ :management_console_endpoint, :management_console_password,
48
53
  :middleware, :netrc, :netrc_file,
49
54
  :per_page, :proxy, :user_agent
50
55
  attr_writer :password, :web_endpoint, :api_endpoint, :login
@@ -63,6 +68,8 @@ module Octokit
63
68
  :connection_options,
64
69
  :default_media_type,
65
70
  :login,
71
+ :management_console_endpoint,
72
+ :management_console_password,
66
73
  :middleware,
67
74
  :netrc,
68
75
  :netrc_file,
@@ -89,10 +96,22 @@ module Octokit
89
96
  end
90
97
  alias setup reset!
91
98
 
99
+ # Compares client options to a Hash of requested options
100
+ #
101
+ # @param opts [Hash] Options to compare with current client options
102
+ # @return [Boolean]
103
+ def same_options?(opts)
104
+ opts.hash == options.hash
105
+ end
106
+
92
107
  def api_endpoint
93
108
  File.join(@api_endpoint, "")
94
109
  end
95
110
 
111
+ def management_console_endpoint
112
+ File.join(@management_console_endpoint, "")
113
+ end
114
+
96
115
  # Base URL for generated web URLs
97
116
  #
98
117
  # @return [String] Default: https://github.com/
@@ -0,0 +1,196 @@
1
+ require 'sawyer'
2
+ require 'octokit/authentication'
3
+ module Octokit
4
+
5
+ # Network layer for API clients.
6
+ module Connection
7
+
8
+ include Octokit::Authentication
9
+
10
+ # Header keys that can be passed in options hash to {#get},{#head}
11
+ CONVENIENCE_HEADERS = Set.new([:accept, :content_type])
12
+
13
+ # Make a HTTP GET request
14
+ #
15
+ # @param url [String] The path, relative to {#api_endpoint}
16
+ # @param options [Hash] Query and header params for request
17
+ # @return [Sawyer::Resource]
18
+ def get(url, options = {})
19
+ request :get, url, parse_query_and_convenience_headers(options)
20
+ end
21
+
22
+ # Make a HTTP POST request
23
+ #
24
+ # @param url [String] The path, relative to {#api_endpoint}
25
+ # @param options [Hash] Body and header params for request
26
+ # @return [Sawyer::Resource]
27
+ def post(url, options = {})
28
+ request :post, url, options
29
+ end
30
+
31
+ # Make a HTTP PUT request
32
+ #
33
+ # @param url [String] The path, relative to {#api_endpoint}
34
+ # @param options [Hash] Body and header params for request
35
+ # @return [Sawyer::Resource]
36
+ def put(url, options = {})
37
+ request :put, url, options
38
+ end
39
+
40
+ # Make a HTTP PATCH request
41
+ #
42
+ # @param url [String] The path, relative to {#api_endpoint}
43
+ # @param options [Hash] Body and header params for request
44
+ # @return [Sawyer::Resource]
45
+ def patch(url, options = {})
46
+ request :patch, url, options
47
+ end
48
+
49
+ # Make a HTTP DELETE request
50
+ #
51
+ # @param url [String] The path, relative to {#api_endpoint}
52
+ # @param options [Hash] Query and header params for request
53
+ # @return [Sawyer::Resource]
54
+ def delete(url, options = {})
55
+ request :delete, url, options
56
+ end
57
+
58
+ # Make a HTTP HEAD request
59
+ #
60
+ # @param url [String] The path, relative to {#api_endpoint}
61
+ # @param options [Hash] Query and header params for request
62
+ # @return [Sawyer::Resource]
63
+ def head(url, options = {})
64
+ request :head, url, parse_query_and_convenience_headers(options)
65
+ end
66
+
67
+ # Make one or more HTTP GET requests, optionally fetching
68
+ # the next page of results from URL in Link response header based
69
+ # on value in {#auto_paginate}.
70
+ #
71
+ # @param url [String] The path, relative to {#api_endpoint}
72
+ # @param options [Hash] Query and header params for request
73
+ # @param block [Block] Block to perform the data concatination of the
74
+ # multiple requests. The block is called with two parameters, the first
75
+ # contains the contents of the requests so far and the second parameter
76
+ # contains the latest response.
77
+ # @return [Sawyer::Resource]
78
+ def paginate(url, options = {}, &block)
79
+ opts = parse_query_and_convenience_headers(options.dup)
80
+ if @auto_paginate || @per_page
81
+ opts[:query][:per_page] ||= @per_page || (@auto_paginate ? 100 : nil)
82
+ end
83
+
84
+ data = request(:get, url, opts.dup)
85
+
86
+ if @auto_paginate
87
+ while @last_response.rels[:next] && rate_limit.remaining > 0
88
+ @last_response = @last_response.rels[:next].get(:headers => opts[:headers])
89
+ if block_given?
90
+ yield(data, @last_response)
91
+ else
92
+ data.concat(@last_response.data) if @last_response.data.is_a?(Array)
93
+ end
94
+ end
95
+
96
+ end
97
+
98
+ data
99
+ end
100
+
101
+ # Hypermedia agent for the GitHub API
102
+ #
103
+ # @return [Sawyer::Agent]
104
+ def agent
105
+ @agent ||= Sawyer::Agent.new(endpoint, sawyer_options) do |http|
106
+ http.headers[:accept] = default_media_type
107
+ http.headers[:content_type] = "application/json"
108
+ http.headers[:user_agent] = user_agent
109
+ if basic_authenticated?
110
+ http.basic_auth(@login, @password)
111
+ elsif token_authenticated?
112
+ http.authorization 'token', @access_token
113
+ elsif application_authenticated?
114
+ http.params = http.params.merge application_authentication
115
+ end
116
+ end
117
+ end
118
+
119
+ # Fetch the root resource for the API
120
+ #
121
+ # @return [Sawyer::Resource]
122
+ def root
123
+ get "/"
124
+ end
125
+
126
+ # Response for last HTTP request
127
+ #
128
+ # @return [Sawyer::Response]
129
+ def last_response
130
+ @last_response if defined? @last_response
131
+ end
132
+
133
+ protected
134
+
135
+ def endpoint
136
+ api_endpoint
137
+ end
138
+
139
+ private
140
+
141
+ def reset_agent
142
+ @agent = nil
143
+ end
144
+
145
+ def request(method, path, data, options = {})
146
+ if data.is_a?(Hash)
147
+ options[:query] = data.delete(:query) || {}
148
+ options[:headers] = data.delete(:headers) || {}
149
+ if accept = data.delete(:accept)
150
+ options[:headers][:accept] = accept
151
+ end
152
+ end
153
+
154
+ @last_response = response = agent.call(method, URI::Parser.new.escape(path.to_s), data, options)
155
+ response.data
156
+ end
157
+
158
+ # Executes the request, checking if it was successful
159
+ #
160
+ # @return [Boolean] True on success, false otherwise
161
+ def boolean_from_response(method, path, options = {})
162
+ request(method, path, options)
163
+ @last_response.status == 204
164
+ rescue Octokit::NotFound
165
+ false
166
+ end
167
+
168
+
169
+ def sawyer_options
170
+ opts = {
171
+ :links_parser => Sawyer::LinkParsers::Simple.new
172
+ }
173
+ conn_opts = @connection_options
174
+ conn_opts[:builder] = @middleware if @middleware
175
+ conn_opts[:proxy] = @proxy if @proxy
176
+ opts[:faraday] = Faraday.new(conn_opts)
177
+
178
+ opts
179
+ end
180
+
181
+ def parse_query_and_convenience_headers(options)
182
+ headers = options.delete(:headers) { Hash.new }
183
+ CONVENIENCE_HEADERS.each do |h|
184
+ if header = options.delete(h)
185
+ headers[h] = header
186
+ end
187
+ end
188
+ query = options.delete(:query)
189
+ opts = {:query => options}
190
+ opts[:query].merge!(query) if query && query.is_a?(Hash)
191
+ opts[:headers] = headers unless headers.empty?
192
+
193
+ opts
194
+ end
195
+ end
196
+ end