github_api 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/README.rdoc +51 -20
  2. data/lib/github_api.rb +3 -1
  3. data/lib/github_api/api.rb +8 -2
  4. data/lib/github_api/authorization.rb +52 -0
  5. data/lib/github_api/cache_control.rb +19 -0
  6. data/lib/github_api/configuration.rb +8 -11
  7. data/lib/github_api/connection.rb +18 -36
  8. data/lib/github_api/gists/comments.rb +17 -5
  9. data/lib/github_api/issues.rb +9 -1
  10. data/lib/github_api/issues/comments.rb +15 -4
  11. data/lib/github_api/mime_type.rb +55 -0
  12. data/lib/github_api/pull_requests.rb +14 -0
  13. data/lib/github_api/pull_requests/comments.rb +10 -0
  14. data/lib/github_api/repos/collaborators.rb +41 -19
  15. data/lib/github_api/repos/commits.rb +108 -43
  16. data/lib/github_api/repos/forks.rb +32 -13
  17. data/lib/github_api/request.rb +12 -3
  18. data/lib/github_api/request/caching.rb +33 -0
  19. data/lib/github_api/version.rb +1 -1
  20. data/spec/fixtures/repos/collaborators.json +8 -0
  21. data/spec/fixtures/repos/commit.json +53 -0
  22. data/spec/fixtures/repos/commit_comment.json +16 -0
  23. data/spec/fixtures/repos/commit_comments.json +18 -0
  24. data/spec/fixtures/repos/commits.json +27 -0
  25. data/spec/fixtures/{repos_list.json → repos/fork.json} +0 -0
  26. data/spec/fixtures/repos/forks.json +29 -0
  27. data/spec/fixtures/repos/repo_comments.json +18 -0
  28. data/spec/github/authorization_spec.rb +71 -0
  29. data/spec/github/mime_type_spec.rb +70 -0
  30. data/spec/github/repos/collaborators_spec.rb +166 -3
  31. data/spec/github/repos/commits_spec.rb +421 -2
  32. data/spec/github/repos/forks_spec.rb +101 -3
  33. data/spec/github/repos/watching_spec.rb +6 -0
  34. data/spec/github_spec.rb +8 -4
  35. metadata +17 -9
  36. data/lib/github_api/api/extract_options.rb +0 -17
  37. data/lib/github_api/api/mime.rb +0 -5
  38. data/spec/fixtures/collaborators_list.json +0 -6
  39. data/spec/fixtures/commits_list.json +0 -25
  40. data/spec/fixtures/repos_branches_list.json +0 -7
data/README.rdoc CHANGED
@@ -12,7 +12,7 @@ Grab the gem by issuing
12
12
 
13
13
  or in your Gemfile
14
14
 
15
- gem "github_api", "~> 0.2.0"
15
+ gem "github_api", "~> 0.2.1"
16
16
 
17
17
  == Usage
18
18
 
@@ -20,20 +20,12 @@ Create a new client instance
20
20
 
21
21
  @github = Github.new
22
22
 
23
- At this stage you can also supply various configuration parameters, such as :user, :repo, :org, :oauth_token, :login, :password or :basic_auth
24
- which are used thoughtout the API
23
+ At this stage you can also supply various configuration parameters, such as :user, :repo, :org, :oauth_token, :login, :password or :basic_auth which are used thoughtout the API
25
24
 
26
25
  @github = Github.new :user => 'peter-murach', :repo => 'github-api'
27
26
 
28
- In order to authenticate the user through OAuth2 on GitHub you need to
29
-
30
- * visit https://github.com/account/applications/ and register your app
31
- * authorize your credentials https://github.com/login/oauth/authorize
32
- * get your token https://github.com/login/oauth/access_token
27
+ You can authenticate either using OAuth authentication convenience methods(see section OAuth) or through basic authentication by passing your login and password credentials
33
28
 
34
- Once you have your consumer and token keys, configure your github instance following instructions under Configuration.
35
-
36
- You can also use basic authentication by passing your login and password credentials
37
29
  @github = Github.new :login => 'peter-murach', :password => '...'
38
30
 
39
31
  or use convenience method:
@@ -85,7 +77,7 @@ All method calls form ruby like sentences and allow for intuitive api navigation
85
77
 
86
78
  @github = Github.new :oauth_token => '...'
87
79
  @github.users.following 'wycats' # => returns users that 'wycats' is following
88
- @github.users.following? 'wycats' # => returns true if following, otherwise false
80
+ @github.users.following 'wycats' # => returns true if following, otherwise false
89
81
 
90
82
  For specification on all available methods go to http://developer.github.com/v3/ or
91
83
  read the rdoc, all methods are documented there with examples of usage.
@@ -106,14 +98,35 @@ or organisation name, allow you to switch the way the data is returned to you, f
106
98
  puts file.path
107
99
  end
108
100
 
101
+ == OAuth
102
+
103
+ In order to authenticate the user through OAuth2 on GitHub you need to
104
+
105
+ * visit https://github.com/account/applications/ and register your app
106
+
107
+ * authorize your credentials https://github.com/login/oauth/authorize
108
+ You can use convenience methods to help you achieve this that come with this gem:
109
+
110
+ @github = Github.new :client_id => '...', :client_secret => '...'
111
+ @github.authorize_url :redirect_uri => 'http://localhost', :scope => 'repo'
112
+ # => "https://github.com/login/oauth/authorize?scope=repo&response_type=code&client_id='...'&redirect_uri=http%3A%2F%2Flocalhost"
113
+
114
+ After you get your authorization code, call to receive your access_token
115
+
116
+ token = github.get_token( authorization_code )
117
+
118
+ Once you have your access token, configure your github instance following instructions under Configuration.
119
+
109
120
  == MIME Types
110
121
 
111
- Provides support for the following mime types
122
+ Issues, PullRequests and few other API leverage custom mime types which are <tt>:json</tt>, <tt>:blob</tt>, <tt>:raw</tt>, <tt>:text</tt>, <tt>:html</tt>, <tt>:full</tt>. By default <tt>:raw</tt> is used.
112
123
 
113
124
  In order to pass a mime type with your request do
114
125
 
115
- @github = Github.new :oauth_token
116
- @github...
126
+ @github = Github.new
127
+ @github.pull_requests.pull_requests 'peter-murach', 'github', :mime_type => :full
128
+
129
+ Your header will contain 'Accept: "application/vnd.github-pull.full+json"' which in turn returns raw, text and html representations in response body.
117
130
 
118
131
  == Configuration
119
132
 
@@ -132,6 +145,12 @@ or
132
145
 
133
146
  All parameters can be overwirtten as per method call. By passing parameters hash...
134
147
 
148
+ == Caching
149
+
150
+ Each <tt>get</tt> request by default is not going to be cached. In order to set the cache do... If no cache type is provided a default memoization is done.
151
+
152
+ Github.cache do...
153
+
135
154
  == Examples
136
155
 
137
156
  Some api methods require input parameters, these are added simply as a hash properties, for instance
@@ -156,17 +175,29 @@ Query requests instead of http responses return boolean values
156
175
  @github = Github.new
157
176
  @github.orgs.public_member? 'github', 'technoweenie' # => true
158
177
 
159
- == Caching
178
+ == Rails Example
179
+
180
+ A Rails controller that allows a user to authorize their GitHub account and then perform request.
160
181
 
161
- Each call by default is not going to be cached. In order to set the inmemory cache do...
182
+ class GithubController < ApplicationController
183
+
184
+ def authorize
185
+ github = Github.new :client_id => '...', :client_secret => '...'
186
+ address = github.authorize_url :redirect_uri => 'http://...', :scope => 'repo'
187
+ redirect_to address
188
+ end
189
+
190
+ def callback
191
+ authorization_code = params[:code]
192
+ token = github.get_token authorization_code
193
+ access_token = token.token
194
+ end
195
+ end
162
196
 
163
197
  == TODO
164
198
 
165
- * Add support for mime types
166
199
  * Add request caching - local filestore?, http caching?.
167
- * Add oauth2 helper methods.
168
200
  * Add response processing methods
169
- * Add helper methods to return iterators over most common collections.
170
201
  * Add response set helper methods e.i. pagination.
171
202
  * Add DSL falvoured api access
172
203
 
data/lib/github_api.rb CHANGED
@@ -51,6 +51,8 @@ module Github
51
51
  :Orgs => 'orgs',
52
52
  :PullRequests => 'pull_requests',
53
53
  :Users => 'users',
54
- :CoreExt => 'core_ext'
54
+ :CoreExt => 'core_ext',
55
+ :MimeType => 'mime_type',
56
+ :Authorization => 'authorization'
55
57
 
56
58
  end # Github
@@ -3,12 +3,16 @@
3
3
  require 'github_api/configuration'
4
4
  require 'github_api/connection'
5
5
  require 'github_api/request'
6
+ require 'github_api/mime_type'
6
7
  require 'github_api/core_ext/hash'
7
8
  require 'github_api/core_ext/array'
8
9
 
9
10
  module Github
11
+
10
12
  # @private
11
13
  class API
14
+ include Authorization
15
+ include MimeType
12
16
  include Connection
13
17
  include Request
14
18
 
@@ -37,7 +41,7 @@ module Github
37
41
  send("#{key}=", options[key])
38
42
  end
39
43
  _process_basic_auth(options[:basic_auth])
40
- @cached = Hash.new
44
+ client if client_id? && client_secret?
41
45
  end
42
46
 
43
47
  private
@@ -143,7 +147,9 @@ module Github
143
147
  end
144
148
  end
145
149
 
146
- def _merge_parameters(params)
150
+ def _merge_mime_type(resource, params) # :nodoc:
151
+ params['resource'] = resource
152
+ params['mime_type'] = params['mime_type'] || :raw
147
153
  end
148
154
 
149
155
  # TODO add to core extensions
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+
3
+ module Github
4
+ module Authorization
5
+
6
+ attr_accessor :scopes
7
+
8
+ # Setup OAuth2 instance
9
+ def client
10
+ @client ||= ::OAuth2::Client.new(client_id, client_secret,
11
+ :site => 'https://github.com',
12
+ :authorize_url => 'login/oauth/authorize',
13
+ :token_url => 'login/oauth/access_token'
14
+ )
15
+ end
16
+
17
+ # Strategy token
18
+ def auth_code
19
+ _verify_client
20
+ @client.auth_code
21
+ end
22
+
23
+ # Sends authorization request to GitHub.
24
+ # = Parameters
25
+ # * <tt>:redirect_uri</tt> - Required string.
26
+ # * <tt>:scope</tt> - Optional string. Comma separated list of scopes.
27
+ # Available scopes:
28
+ # * (no scope) - public read-only access (includes public user profile info, public repo info, and gists).
29
+ # * <tt>user</tt> - DB read/write access to profile info only.
30
+ # * <tt>public_repo</tt> - DB read/write access, and Git read access to public repos.
31
+ # * <tt>repo</tt> - DB read/write access, and Git read access to public and private repos.
32
+ # * <tt>gist</tt> - write access to gists.
33
+ #
34
+ def authorize_url(params = {})
35
+ _verify_client
36
+ @client.auth_code.authorize_url(params)
37
+ end
38
+
39
+ # Makes request to token endpoint and retrieves access token value
40
+ def get_token(authorization_code, params = {})
41
+ _verify_client
42
+ @client.auth_code.get_token(authorization_code, params)
43
+ end
44
+
45
+ private
46
+
47
+ def _verify_client # :nodoc:
48
+ raise ArgumentError, 'Need to provide client_id and client_secret' unless client_id? && client_secret?
49
+ end
50
+
51
+ end # Authorization
52
+ end # Github
@@ -0,0 +1,19 @@
1
+ module Github
2
+ module CacheOptions
3
+ extend self
4
+
5
+ def self.option_accessor(key)
6
+ defined_method("#{key}=") { |value| }
7
+ end
8
+
9
+ private
10
+
11
+ def initialize_options(options={})
12
+ @default_options = {
13
+ 'type' => :memoization,
14
+
15
+ }
16
+ end
17
+
18
+ end
19
+ end
@@ -9,10 +9,9 @@ module Github
9
9
  :client_secret,
10
10
  :oauth_token,
11
11
  :endpoint,
12
- :format,
13
- :resource,
12
+ :mime_type,
14
13
  :user_agent,
15
- :faraday_options,
14
+ :connection_options,
16
15
  :repo,
17
16
  :user,
18
17
  :login,
@@ -47,12 +46,11 @@ module Github
47
46
  # The value sent in the http header for 'User-Agent' if none is set
48
47
  DEFAULT_USER_AGENT = "Github Ruby Gem #{Github::VERSION::STRING}".freeze
49
48
 
50
- DEFAULT_FORMAT = :json
49
+ # By default the <tt>Accept</tt> header will make a request for <tt>JSON</tt>
50
+ DEFAULT_MIME_TYPE = :json
51
51
 
52
- # By default,
53
- DEFAULT_RESOURCE = nil
54
-
55
- DEFAULT_FARADAY_OPTIONS = {}
52
+ # By default uses the Faraday connection options if none is set
53
+ DEFAULT_CONNECTION_OPTIONS = {}
56
54
 
57
55
  # By default, don't set user name
58
56
  DEFAULT_USER = nil
@@ -84,9 +82,8 @@ module Github
84
82
  self.oauth_token = DEFAULT_OAUTH_TOKEN
85
83
  self.endpoint = DEFAULT_ENDPOINT
86
84
  self.user_agent = DEFAULT_USER_AGENT
87
- self.faraday_options = DEFAULT_FARADAY_OPTIONS
88
- self.format = DEFAULT_FORMAT
89
- self.resource = DEFAULT_RESOURCE
85
+ self.connection_options = DEFAULT_CONNECTION_OPTIONS
86
+ self.mime_type = DEFAULT_MIME_TYPE
90
87
  self.user = DEFAULT_USER
91
88
  self.repo = DEFAULT_REPO
92
89
  self.login = DEFAULT_LOGIN
@@ -11,55 +11,38 @@ require 'github_api/request/basic_auth'
11
11
  module Github
12
12
  module Connection
13
13
 
14
- # Available resources
15
- RESOURCES = {
16
- :issue => 'vnd.github-issue.',
17
- :issuecomment => 'vnd.github-issuecomment.',
18
- :commitcomment => 'vnd.github-commitcomment',
19
- :pull => 'vnd.github-pull.',
20
- :pullcomment => 'vnd.github-pullcomment.',
21
- :gistcomment => 'vnd.github-gistcomment.'
22
- }
23
-
24
- # Mime types used by resources
25
- RESOURCE_MIME_TYPES = {
26
- :raw => 'raw+json',
27
- :text => 'text+json',
28
- :html => 'html+json',
29
- :full => 'html+full'
30
- }
31
-
32
- BLOB_MIME_TYPES = {
33
- :raw => 'vnd.github-blob.raw',
34
- :json => 'json'
35
- }
36
-
37
- def default_faraday_options()
14
+ private
15
+
16
+ def header_options() # :nodoc:
38
17
  {
39
18
  :headers => {
40
- 'Accept' => "application/#{resource}#{format}",
41
- 'User-Agent' => user_agent
19
+ 'Accept' => '*/*', #accepts,
20
+ 'User-Agent' => user_agent,
21
+ 'Content-Type' => 'application/x-www-form-urlencoded'
42
22
  },
43
23
  :ssl => { :verify => false },
44
24
  :url => endpoint
45
25
  }
46
26
  end
47
27
 
48
- # TODO Write mime format conversion
49
-
50
- # Create cache hash and store connection there and then pass it to @connection
51
- # add method to invalidate it if previous options are different from current
52
-
53
- def clear_cache
28
+ def clear_cache # :nodoc:
54
29
  @connection = nil
55
30
  end
56
31
 
57
- def caching?
32
+ def caching? # :nodoc:
58
33
  !@connection.nil?
59
34
  end
60
35
 
61
- def connection(options = {})
62
- merged_options = faraday_options.merge(default_faraday_options)
36
+ def connection(options = {}) # :nodoc:
37
+
38
+ # parse(options['resource'], options['mime_type'] || mime_type) if options['mime_type']
39
+ debugger
40
+
41
+ merged_options = if connection_options.empty?
42
+ header_options
43
+ else
44
+ connection_options.merge(header_options)
45
+ end
63
46
 
64
47
  clear_cache unless options.empty?
65
48
 
@@ -89,4 +72,3 @@ module Github
89
72
 
90
73
  end # Connection
91
74
  end # Github
92
-
@@ -4,8 +4,12 @@ module Github
4
4
  class Gists
5
5
  module Comments
6
6
 
7
- REQUIRED_GIST_COMMENT_INPUTS = %w[ body ]
8
-
7
+ REQUIRED_GIST_COMMENT_INPUTS = %w[
8
+ body
9
+ mime_type
10
+ resource
11
+ ].freeze
12
+
9
13
  # List comments on a gist
10
14
  #
11
15
  # = Examples
@@ -14,6 +18,8 @@ module Github
14
18
  #
15
19
  def gist_comments(gist_id, params={})
16
20
  _normalize_params_keys(params)
21
+ _merge_mime_type(:gist_comment, params)
22
+
17
23
  get("/gists/#{gist_id}/comments", params)
18
24
  end
19
25
 
@@ -25,6 +31,8 @@ module Github
25
31
  #
26
32
  def gist_comment(comment_id, params={})
27
33
  _normalize_params_keys(params)
34
+ _merge_mime_type(:gist_comment, params)
35
+
28
36
  get("/gists/comments/#{comment_id}", params)
29
37
  end
30
38
 
@@ -36,8 +44,9 @@ module Github
36
44
  #
37
45
  def create_gist_comment(gist_id, params={})
38
46
  _normalize_params_keys(params)
47
+ _merge_mime_type(:gist_comment, params)
39
48
  _filter_params_keys(REQUIRED_GIST_COMMENT_INPUTS, params)
40
-
49
+
41
50
  raise ArgumentError, "Required inputs are: :body" unless _validate_inputs(REQUIRED_GIST_COMMENT_INPUTS, params)
42
51
 
43
52
  post("/gists/#{gist_id}/comments", params)
@@ -51,8 +60,9 @@ module Github
51
60
  #
52
61
  def edit_gist_comment(comment_id, params={})
53
62
  _normalize_params_keys(params)
63
+ _merge_mime_type(:gist_comment, params)
54
64
  _filter_params_keys(REQUIRED_GIST_COMMENT_INPUTS, params)
55
-
65
+
56
66
  raise ArgumentError, "Required inputs are: :body" unless _validate_inputs(REQUIRED_GIST_COMMENT_INPUTS, params)
57
67
 
58
68
  patch("/gists/comments/#{comment_id}", params)
@@ -66,9 +76,11 @@ module Github
66
76
  #
67
77
  def delete_gist_comment(comment_id, params={})
68
78
  _normalize_params_keys(params)
79
+ _merge_mime_type(:gist_comment, params)
80
+
69
81
  delete("/gists/comments/#{comment_id}", params)
70
82
  end
71
-
83
+
72
84
  end # Comments
73
85
  end # Gists
74
86
  end # Github
@@ -27,6 +27,8 @@ module Github
27
27
  mentioned
28
28
  title
29
29
  body
30
+ resource
31
+ mime_type
30
32
  ]
31
33
 
32
34
  VALID_ISSUE_PARAM_VALUES = {
@@ -58,7 +60,7 @@ module Github
58
60
  #
59
61
  # = Examples
60
62
  # @github = Github.new :oauth_token => '...'
61
- # @github.issues.issues :since => '2011-04-12312:12:121',
63
+ # @github.issues.issues :since => '2011-04-12312:12:121',
62
64
  # :filter => 'created',
63
65
  # :state => 'open',
64
66
  # :labels => "bug,ui,bla",
@@ -68,6 +70,7 @@ module Github
68
70
  def issues(params={})
69
71
  _normalize_params_keys(params)
70
72
  _filter_params_keys(VALID_ISSUE_PARAM_NAMES, params)
73
+ _merge_mime_type(:issue, params)
71
74
  _validate_params_values(VALID_ISSUE_PARAM_VALUES, params)
72
75
 
73
76
  response = get("/issues", params)
@@ -111,6 +114,7 @@ module Github
111
114
 
112
115
  _normalize_params_keys(params)
113
116
  _filter_params_keys(VALID_ISSUE_PARAM_NAMES, params)
117
+ _merge_mime_type(:issue, params)
114
118
  _validate_params_values(VALID_ISSUE_PARAM_VALUES, params)
115
119
 
116
120
  response = get("/repos/#{user}/#{repo}/issues", params)
@@ -127,7 +131,9 @@ module Github
127
131
  def get_issue(user_name, repo_name, issue_id, params={})
128
132
  _update_user_repo_params(user_name, repo_name)
129
133
  _validate_user_repo_params(user, repo) unless user? && repo?
134
+
130
135
  _normalize_params_keys(params)
136
+ _merge_mime_type(:issue, params)
131
137
 
132
138
  get("/repos/#{user}/#{repo}/issues/#{issue_id}")
133
139
  end
@@ -157,6 +163,7 @@ module Github
157
163
  _validate_user_repo_params(user, repo) unless user? && repo?
158
164
 
159
165
  _normalize_params_keys(params)
166
+ _merge_mime_type(:issue, params)
160
167
  _filter_params_keys(VALID_MILESTONE_INPUTS, params)
161
168
 
162
169
  raise ArgumentError, "Required params are: :title" unless _validate_inputs(%w[ title ], params)
@@ -192,6 +199,7 @@ module Github
192
199
  _validate_presence_of issue_id
193
200
 
194
201
  _normalize_params_keys(params)
202
+ _merge_mime_type(:issue, params)
195
203
  _filter_params_keys(VALID_MILESTONE_INPUTS, params)
196
204
 
197
205
  patch("/repos/#{user}/#{repo}/issues/#{issue_id}", params)