github_api 0.1.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. data/LICENSE.txt +20 -0
  2. data/README.rdoc +159 -0
  3. data/Rakefile +52 -0
  4. data/features/github.feature +9 -0
  5. data/features/step_definitions/github_steps.rb +0 -0
  6. data/features/support/env.rb +13 -0
  7. data/lib/github_api.rb +55 -0
  8. data/lib/github_api/api.rb +133 -0
  9. data/lib/github_api/api/extract_options.rb +17 -0
  10. data/lib/github_api/api/mime.rb +5 -0
  11. data/lib/github_api/api/utils.rb +9 -0
  12. data/lib/github_api/client.rb +35 -0
  13. data/lib/github_api/configuration.rb +84 -0
  14. data/lib/github_api/connection.rb +91 -0
  15. data/lib/github_api/error.rb +35 -0
  16. data/lib/github_api/gists.rb +199 -0
  17. data/lib/github_api/gists/comments.rb +74 -0
  18. data/lib/github_api/git_data.rb +26 -0
  19. data/lib/github_api/git_data/blobs.rb +9 -0
  20. data/lib/github_api/git_data/commits.rb +9 -0
  21. data/lib/github_api/git_data/references.rb +9 -0
  22. data/lib/github_api/git_data/tags.rb +9 -0
  23. data/lib/github_api/git_data/trees.rb +9 -0
  24. data/lib/github_api/issues.rb +201 -0
  25. data/lib/github_api/issues/comments.rb +98 -0
  26. data/lib/github_api/issues/events.rb +50 -0
  27. data/lib/github_api/issues/labels.rb +191 -0
  28. data/lib/github_api/issues/milestones.rb +119 -0
  29. data/lib/github_api/orgs.rb +90 -0
  30. data/lib/github_api/orgs/members.rb +109 -0
  31. data/lib/github_api/orgs/teams.rb +236 -0
  32. data/lib/github_api/pull_requests.rb +210 -0
  33. data/lib/github_api/pull_requests/comments.rb +134 -0
  34. data/lib/github_api/repos.rb +256 -0
  35. data/lib/github_api/repos/collaborators.rb +59 -0
  36. data/lib/github_api/repos/commits.rb +115 -0
  37. data/lib/github_api/repos/downloads.rb +77 -0
  38. data/lib/github_api/repos/forks.rb +29 -0
  39. data/lib/github_api/repos/hooks.rb +67 -0
  40. data/lib/github_api/repos/keys.rb +53 -0
  41. data/lib/github_api/repos/watching.rb +50 -0
  42. data/lib/github_api/request.rb +75 -0
  43. data/lib/github_api/request/oauth2.rb +33 -0
  44. data/lib/github_api/response.rb +10 -0
  45. data/lib/github_api/response/jsonize.rb +22 -0
  46. data/lib/github_api/response/mashify.rb +26 -0
  47. data/lib/github_api/response/raise_error.rb +33 -0
  48. data/lib/github_api/users.rb +82 -0
  49. data/lib/github_api/users/emails.rb +49 -0
  50. data/lib/github_api/users/followers.rb +98 -0
  51. data/lib/github_api/users/keys.rb +84 -0
  52. data/lib/github_api/version.rb +12 -0
  53. data/spec/fixtures/collaborators_list.json +6 -0
  54. data/spec/fixtures/commits_list.json +25 -0
  55. data/spec/fixtures/repos_branches_list.json +7 -0
  56. data/spec/fixtures/repos_list.json +27 -0
  57. data/spec/github/api_spec.rb +6 -0
  58. data/spec/github/client_spec.rb +6 -0
  59. data/spec/github/gists/comments_spec.rb +5 -0
  60. data/spec/github/gists_spec.rb +5 -0
  61. data/spec/github/git_data/blobs_spec.rb +5 -0
  62. data/spec/github/git_data/commits_spec.rb +5 -0
  63. data/spec/github/git_data/references_spec.rb +5 -0
  64. data/spec/github/git_data/tags_spec.rb +5 -0
  65. data/spec/github/git_data/trees_spec.rb +5 -0
  66. data/spec/github/git_data_spec.rb +5 -0
  67. data/spec/github/issues/comments_spec.rb +5 -0
  68. data/spec/github/issues/events_spec.rb +5 -0
  69. data/spec/github/issues/labels_spec.rb +5 -0
  70. data/spec/github/issues/milestones_spec.rb +5 -0
  71. data/spec/github/issues_spec.rb +5 -0
  72. data/spec/github/orgs/members_spec.rb +5 -0
  73. data/spec/github/orgs/teams_spec.rb +5 -0
  74. data/spec/github/orgs_spec.rb +5 -0
  75. data/spec/github/repos/collaborators_spec.rb +6 -0
  76. data/spec/github/repos/commits_spec.rb +5 -0
  77. data/spec/github/repos/downloads_spec.rb +5 -0
  78. data/spec/github/repos/forks_spec.rb +5 -0
  79. data/spec/github/repos/hooks_spec.rb +5 -0
  80. data/spec/github/repos/keys_spec.rb +5 -0
  81. data/spec/github/repos/watching_spec.rb +5 -0
  82. data/spec/github/repos_spec.rb +35 -0
  83. data/spec/github_spec.rb +5 -0
  84. data/spec/spec_helper.rb +15 -0
  85. metadata +284 -0
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Piotr Murach
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,159 @@
1
+ = github
2
+
3
+ A Ruby wrapper for the GitHub REST API v3.
4
+
5
+ Supports all the API methods(nearly 200). It's build in a modular way, that is, you can either instantiate the whole api wrapper Github.new or use parts of it e.i. Github::Repos.new if working solely with repositories is your main concern.
6
+
7
+ == Installation
8
+
9
+ Grab the gem by issuing
10
+
11
+ gem install github-api
12
+
13
+ or in your Gemfile
14
+
15
+ gem 'github-api'
16
+
17
+ == Usage
18
+
19
+ Create a new client instance
20
+
21
+ @github = Github.new
22
+
23
+ At this stage you can also supply various configuration parameters, such as :user, :repo, :org etc..,
24
+ which are used thoughtout the API
25
+
26
+ @github = Github.new :user => 'peter-murach', :repo => 'github-api'
27
+
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
33
+
34
+ Once you have your consumer and token keys, configure your github instance following instructions under Configuration.
35
+
36
+ You can interact with GitHub interface, for example repositories, by issueing following calls
37
+
38
+ @github.repos.commits
39
+ @github.repos.branches
40
+ @github.repos.contributors
41
+
42
+ The code base is modular and allows for you to work specifically with a given part of GitHub API e.g. repositories
43
+
44
+ @repos = Github::Repos.new
45
+ @repos.branches 'peter-murach', 'github'
46
+
47
+ or
48
+
49
+ @repos = Github::Repos.new :user => 'peter-murach', :repo => 'github'
50
+ @repos.branches
51
+
52
+ The response is of type [Hashie::Mash] and allows to traverse all the json response attributes like method calls e.i.
53
+
54
+ @repos = Github::Repos.new :user => 'peter-murach', :repo => 'github'
55
+ @repos.branches do |branch|
56
+ puts branch.name
57
+ end
58
+
59
+ == API
60
+
61
+ Main API methods are grouped into the following classes that can be instantiated on their own
62
+
63
+ Github - full API access
64
+ Github::Gists
65
+ Github::GitData
66
+ Github::Issues
67
+ Github::Orgs
68
+ Github::PullRequests
69
+ Github::Repos
70
+ Github::Users
71
+
72
+ Some parts of GitHub API v3 require you to be autheticated, for instance the following are examples of API only for the authenticated user
73
+
74
+ Github::Users::Emails
75
+ Github::Users::Keys
76
+
77
+ All method calls form ruby like sentences and allow for intuitive api navigation, for instance
78
+
79
+ @github = Github.new :oauth_token => '...'
80
+ @github.users.following 'wycats' # => returns users that 'wycats' is following
81
+ @github.users.following? 'wycats' # => returns true if following, otherwise false
82
+
83
+ For specification on all available methods go to http://developer.github.com/v3/ or
84
+ read the rdoc, all methods are documented there with examples of usage.
85
+
86
+ == MIME Types
87
+
88
+ Provides support for the following mime types
89
+
90
+ In order to pass a mime type with your request do
91
+
92
+ @github = Github.new :oauth_token
93
+ @github...
94
+
95
+ == Configuration
96
+
97
+ Certain methods require authentication. To get your GitHub OAuth v2 credentials,
98
+ register an app at https://github.com/account/applications/
99
+
100
+ Github.configure do |config|
101
+ config.oauth_token = YOUR_OAUTH_ACCESS_TOKEN
102
+ end
103
+
104
+ or
105
+
106
+ Github.new(:oauth_token => YOUR_OAUTH_TOKEN)
107
+
108
+ All parameters can be overwirtten as per method call. By passing parameters hash...
109
+
110
+ == Examples
111
+
112
+ Some api methods require input parameters, these are added simply as a hash properties, for instance
113
+
114
+ @issues = Github::Issues.new :user => 'peter-murach', :repo => 'github-api'
115
+ @issues.milestones :state => 'open', :sort => 'due_date', :direction => 'asc'
116
+
117
+ Other methods may require inputs as an array of strings
118
+
119
+ @users = Github::Users.new :oauth_token => '...'
120
+ @users.add_email 'email1', 'email2', ..., 'emailn' # => Adds emails to the authenticated user
121
+
122
+ If a method returns a collection, you can iterator over it by supplying a block parameter,
123
+
124
+ @issues = Github::Issues.new :user => 'peter-murach', :repo => 'github-api'
125
+ @issues.events do |event|
126
+ puts event.actor.login
127
+ end
128
+
129
+ Query requests instead of http responses return boolean values
130
+
131
+ @github = Github.new
132
+ @github.orgs.public_member? 'github', 'technoweenie' # => true
133
+
134
+ == Caching
135
+
136
+ == TODO
137
+
138
+ * Add support for mime types
139
+ * Add request caching - local filestore?, http caching?.
140
+ * Add oauth2 helper methods.
141
+ * Add response processing methods
142
+ * Add helper methods to return iterators over most common collections.
143
+ * Add response set helper methods e.i. pagination.
144
+ * Add DSL falvoured api access
145
+
146
+ == Contributing to github
147
+
148
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
149
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
150
+ * Fork the project
151
+ * Start a feature/bugfix branch
152
+ * Commit and push until you are happy with your contribution
153
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
154
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
155
+
156
+ == Copyright
157
+
158
+ Copyright (c) 2011 Piotr Murach. See LICENSE.txt for
159
+ further details.
data/Rakefile ADDED
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "github"
18
+ gem.homepage = "http://github.com/peter-murach/github"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{TODO: one-line summary of your gem}
21
+ gem.description = %Q{TODO: longer description of your gem}
22
+ gem.email = ""
23
+ gem.authors = ["Piotr Murach"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rspec/core'
29
+ require 'rspec/core/rake_task'
30
+ RSpec::Core::RakeTask.new(:spec) do |spec|
31
+ spec.pattern = FileList['spec/**/*_spec.rb']
32
+ end
33
+
34
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
35
+ spec.pattern = 'spec/**/*_spec.rb'
36
+ spec.rcov = true
37
+ end
38
+
39
+ require 'cucumber/rake/task'
40
+ Cucumber::Rake::Task.new(:features)
41
+
42
+ task :default => :spec
43
+
44
+ require 'rake/rdoctask'
45
+ Rake::RDocTask.new do |rdoc|
46
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
47
+
48
+ rdoc.rdoc_dir = 'rdoc'
49
+ rdoc.title = "github #{version}"
50
+ rdoc.rdoc_files.include('README*')
51
+ rdoc.rdoc_files.include('lib/**/*.rb')
52
+ end
@@ -0,0 +1,9 @@
1
+ Feature: something something
2
+ In order to something something
3
+ A user something something
4
+ something something something
5
+
6
+ Scenario: something something
7
+ Given inspiration
8
+ When I create a sweet new gem
9
+ Then everyone should see how awesome I am
File without changes
@@ -0,0 +1,13 @@
1
+ require 'bundler'
2
+ begin
3
+ Bundler.setup(:default, :development)
4
+ rescue Bundler::BundlerError => e
5
+ $stderr.puts e.message
6
+ $stderr.puts "Run `bundle install` to install missing gems"
7
+ exit e.status_code
8
+ end
9
+
10
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
11
+ require 'github'
12
+
13
+ require 'rspec/expectations'
data/lib/github_api.rb ADDED
@@ -0,0 +1,55 @@
1
+ # encoding: utf-8
2
+
3
+ require 'github_api/version'
4
+ require 'github_api/configuration'
5
+ require 'github_api/connection'
6
+
7
+ module Github
8
+ extend Configuration
9
+
10
+ class << self
11
+ # Alias for Github::Client.new
12
+ #
13
+ # @return [Github::Client]
14
+ def new(options = {})
15
+ Github::Client.new(options)
16
+ end
17
+
18
+ # Delegate to Github::Client
19
+ #
20
+ def method_missing(method, *args, &block)
21
+ return super unless new.respond_to?(method)
22
+ new.send(method, *args, &block)
23
+ end
24
+
25
+ def respond_to?(method, include_private = false)
26
+ new.respond_to?(method, include_private) || super(method, include_private)
27
+ end
28
+ end
29
+
30
+ module AutoloadHelper
31
+
32
+ def autoload_all(prefix, options)
33
+ options.each do |const_name, path|
34
+ autoload const_name, File.join(prefix, path)
35
+ end
36
+ end
37
+ end
38
+
39
+ extend AutoloadHelper
40
+
41
+ autoload_all 'github_api',
42
+ :API => 'api',
43
+ :Client => 'client',
44
+ :Repos => 'repos',
45
+ :Request => 'request',
46
+ :Response => 'response',
47
+ :Error => 'error',
48
+ :Issues => 'issues',
49
+ :Gists => 'gists',
50
+ :GitData => 'git_data',
51
+ :Orgs => 'orgs',
52
+ :PullRequests => 'pull_requests',
53
+ :Users => 'users'
54
+
55
+ end # Github
@@ -0,0 +1,133 @@
1
+ # encoding: utf-8
2
+
3
+ require 'github_api/configuration'
4
+ require 'github_api/connection'
5
+ require 'github_api/request'
6
+
7
+ module Github
8
+ # @private
9
+ class API
10
+ include Connection
11
+ include Request
12
+
13
+ VALID_API_KEYS = [
14
+ :per_page,
15
+ :pagination
16
+ ]
17
+
18
+ attr_reader *Configuration::VALID_OPTIONS_KEYS
19
+ attr_accessor *VALID_API_KEYS
20
+
21
+ # Callback to update global configuration options
22
+ class_eval do
23
+ Configuration::VALID_OPTIONS_KEYS.each do |key|
24
+ define_method "#{key}=" do |arg|
25
+ self.instance_variable_set("@#{key}", arg)
26
+ Github.send("#{key}=", arg)
27
+ end
28
+ end
29
+ end
30
+
31
+ # Creates new API
32
+ def initialize(options = {})
33
+ options = Github.options.merge(options)
34
+ Configuration::VALID_OPTIONS_KEYS.each do |key|
35
+ send("#{key}=", options[key])
36
+ end
37
+ @cached = Hash.new
38
+ end
39
+
40
+ private
41
+
42
+ # Responds to attribute query
43
+ def method_missing(method, *args, &block)
44
+ if method.to_s =~ /^(.*)\?$/
45
+ return !self.send($1.to_s).nil?
46
+ else
47
+ super
48
+ end
49
+ end
50
+
51
+ def _validate_inputs(required, provided)
52
+ required.all? do |key|
53
+ provided.has_key? key
54
+ end
55
+ end
56
+
57
+ def _validate_presence_of(*params)
58
+ params.each do |param|
59
+ raise ArgumentError, "parameter cannot be nil" if param.nil?
60
+ end
61
+ end
62
+
63
+ def _validate_user_repo_params(user_name, repo_name)
64
+ raise ArgumentError, "[user] parameter cannot be nil" if user_name.nil?
65
+ raise ArgumentError, "[repo] parameter cannot be nil" if repo_name.nil?
66
+ end
67
+
68
+ def _update_user_repo_params(user_name, repo_name=nil)
69
+ self.user = user_name || self.user
70
+ self.repo = repo_name || self.repo
71
+ end
72
+
73
+ def _merge_user_into_params!(params)
74
+ params.merge!({ 'user' => self.user }) if user?
75
+ end
76
+
77
+ def _merge_user_repo_into_params!(params)
78
+ { 'user' => self.user, 'repo' => self.repo }.merge!(params)
79
+ end
80
+
81
+ def _normalize_params_keys(params)
82
+ case params
83
+ when Hash
84
+ params.keys.each do |k|
85
+ params[k.to_s] = params.delete(k)
86
+ _normalize_params_keys(params[k.to_s])
87
+ end
88
+ when Array
89
+ params.map! { |el| el.to_s }
90
+ else
91
+ params
92
+ end
93
+ return params
94
+ end
95
+
96
+ def _filter_params_keys(keys, params)
97
+ params.reject! { |k,v| !keys.include? k }
98
+ end
99
+
100
+ def _validate_params_values(options, params)
101
+ params.each do |k, v|
102
+ next unless options.keys.include?(k)
103
+ if options[k].is_a?(Array) && !options[k].include?(params[k])
104
+ raise ArgumentError, "Wrong value for #{k}, allowed: #{options[k].join(', ')}"
105
+ elsif options[k].is_a?(Regexp) && !(options[k] =~ params[k])
106
+ raise ArgumentError, "String does not match the parameter value."
107
+ end
108
+ end
109
+ end
110
+
111
+ def _merge_parameters(params)
112
+ end
113
+
114
+ def _extract_parameters(array)
115
+ if array.last.is_a?(Hash) && array.last.instance_of?(Hash)
116
+ pop
117
+ else
118
+ {}
119
+ end
120
+ end
121
+
122
+ # Passes configuration options to instantiated class
123
+ # TODO implement
124
+ # @private
125
+ def _create_instance(klass)
126
+ klass.new(options)
127
+ end
128
+
129
+ def _token_required
130
+ end
131
+
132
+ end # API
133
+ end # Github