gitnetworkitis 0.2.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/Gemfile +6 -5
  2. data/Gemfile.lock +26 -20
  3. data/VERSION +1 -1
  4. data/get_token.rb +40 -0
  5. data/gitnetworkitis.gemspec +41 -76
  6. data/lib/gitnetworkitis/base.rb +10 -40
  7. data/lib/gitnetworkitis/batch_response.rb +24 -0
  8. data/lib/gitnetworkitis/branch.rb +10 -31
  9. data/lib/gitnetworkitis/commit.rb +2 -5
  10. data/lib/gitnetworkitis/commit_getter.rb +50 -0
  11. data/lib/gitnetworkitis/getter.rb +64 -0
  12. data/lib/gitnetworkitis/json_helper.rb +24 -0
  13. data/lib/gitnetworkitis/repository.rb +11 -30
  14. data/lib/gitnetworkitis.rb +10 -5
  15. data/spec/base_spec.rb +13 -20
  16. data/spec/branch_spec.rb +63 -19
  17. data/spec/getter_spec.rb +36 -0
  18. data/spec/github_config.yml.example +2 -0
  19. data/spec/repository_spec.rb +27 -39
  20. data/spec/spec_helper.rb +3 -64
  21. data/spec/support/vcr_setup.rb +8 -0
  22. data/spec/vcr_cassettes/all_branches.json +67 -0
  23. data/spec/vcr_cassettes/all_repos.json +67 -0
  24. data/spec/vcr_cassettes/bad_creds.json +58 -0
  25. data/spec/vcr_cassettes/find_repo.json +67 -0
  26. data/spec/vcr_cassettes/spec-branch-1_commits.json +2277 -0
  27. data/spec/vcr_cassettes/spec-branch-1_since_date.json +1 -0
  28. data/spec/vcr_cassettes/spec-branch-1_since_sha.json +67 -0
  29. data/spec/vcr_cassettes/spec-branch-2_commits.json +70 -0
  30. data/spec/vcr_cassettes/spec-branch-3_commits.json +67 -0
  31. metadata +84 -124
  32. data/lib/gitnetworkitis/network_data.rb +0 -66
  33. data/lib/gitnetworkitis/network_meta.rb +0 -17
  34. data/spec/commit_spec.rb +0 -8
  35. data/spec/network_data_spec.rb +0 -153
  36. data/spec/network_meta_spec.rb +0 -59
  37. data/spec/responses/branch_pages/turingstudio_loupe_51ac36280d2dfe16c37b66ef344859c9c714c8e1?page=0.json +0 -1
  38. data/spec/responses/branch_pages/turingstudio_loupe_51ac36280d2dfe16c37b66ef344859c9c714c8e1?page=1.json +0 -1
  39. data/spec/responses/branch_pages/turingstudio_loupe_51ac36280d2dfe16c37b66ef344859c9c714c8e1?page=2.json +0 -1
  40. data/spec/responses/branch_pages/turingstudio_loupe_51ac36280d2dfe16c37b66ef344859c9c714c8e1?page=3.json +0 -1
  41. data/spec/responses/branch_pages/turingstudio_loupe_51ac36280d2dfe16c37b66ef344859c9c714c8e1?page=4.json +0 -1
  42. data/spec/responses/branch_pages/turingstudio_loupe_51ac36280d2dfe16c37b66ef344859c9c714c8e1?page=5.json +0 -1
  43. data/spec/responses/branch_pages/turingstudio_loupe_bec7b23dc57b14d89fa2829e8c32a108a18e7248?page=0.json +0 -1
  44. data/spec/responses/branch_pages/turingstudio_loupe_bec7b23dc57b14d89fa2829e8c32a108a18e7248?page=1.json +0 -1
  45. data/spec/responses/branch_pages/turingstudio_loupe_bec7b23dc57b14d89fa2829e8c32a108a18e7248?page=2.json +0 -1
  46. data/spec/responses/branch_pages/turingstudio_loupe_bec7b23dc57b14d89fa2829e8c32a108a18e7248?page=3.json +0 -1
  47. data/spec/responses/branch_pages/turingstudio_loupe_bec7b23dc57b14d89fa2829e8c32a108a18e7248?page=4.json +0 -1
  48. data/spec/responses/branch_pages/turingstudio_loupe_c3aeb61e37f94bbb67c4f14b52c23b8e54d30d0e?page=0.json +0 -1
  49. data/spec/responses/branch_pages/turingstudio_loupe_c3aeb61e37f94bbb67c4f14b52c23b8e54d30d0e?page=1.json +0 -1
  50. data/spec/responses/branch_pages/turingstudio_loupe_c3aeb61e37f94bbb67c4f14b52c23b8e54d30d0e?page=2.json +0 -1
  51. data/spec/responses/branch_pages/turingstudio_loupe_c3aeb61e37f94bbb67c4f14b52c23b8e54d30d0e?page=3.json +0 -1
  52. data/spec/responses/branch_pages/turingstudio_loupe_c3aeb61e37f94bbb67c4f14b52c23b8e54d30d0e?page=4.json +0 -1
  53. data/spec/responses/girlambition/0-500.json +0 -1
  54. data/spec/responses/girlambition/1002-1502.json +0 -1
  55. data/spec/responses/girlambition/1503-2003.json +0 -1
  56. data/spec/responses/girlambition/2004-2504.json +0 -1
  57. data/spec/responses/girlambition/2505-3005.json +0 -1
  58. data/spec/responses/girlambition/3006-3506.json +0 -1
  59. data/spec/responses/girlambition/3507-4007.json +0 -1
  60. data/spec/responses/girlambition/4008-4508.json +0 -1
  61. data/spec/responses/girlambition/4509-4999.json +0 -1
  62. data/spec/responses/girlambition/501-1001.json +0 -1
  63. data/spec/responses/girlambition/repos_show_turingstudio_website-girlambition_branches.json +0 -1
  64. data/spec/responses/girlambition/turingstudio_website-girlambition_network_meta.json +0 -1
  65. data/spec/responses/loupe/repos_show_turingstudio_loupe.json +0 -1
  66. data/spec/responses/loupe/repos_show_turingstudio_loupe_branches.json +0 -1
  67. data/spec/responses/loupe/turingstudio_loupe_068161e2c05a6b8029a7eb410dd27b1dfa531338?start=1&end=5.json +0 -1
  68. data/spec/responses/loupe/turingstudio_loupe_068161e2c05a6b8029a7eb410dd27b1dfa531338?start=130.json +0 -1
  69. data/spec/responses/loupe/turingstudio_loupe_branch.json +0 -1
  70. data/spec/responses/loupe/turingstudio_loupe_network_data.json +0 -1
  71. data/spec/responses/loupe/turingstudio_loupe_network_meta.json +0 -1
  72. data/spec/responses/repos_show_jcoutu.json +0 -1
  73. data/spec/responses/repos_watched_jcoutu.json +0 -1
data/Gemfile CHANGED
@@ -2,14 +2,15 @@ source "http://rubygems.org"
2
2
  # Add dependencies required to use your gem here.
3
3
  # Example:
4
4
  # gem "activesupport", ">= 2.3.5"
5
- gem "httparty"
5
+ gem "httparty", ">= 0.8.1"
6
6
 
7
7
  # Add dependencies to develop your gem here.
8
8
  # Include everything needed to run rake, tests, features, etc.
9
9
  group :development do
10
- gem "rspec", "~> 2.1.0"
11
- gem "bundler", "~> 1.0.0"
12
- gem "jeweler", "~> 1.5.1"
13
- gem "rcov", ">= 0"
10
+ gem "rspec", "~> 2.8.0"
11
+ gem "bundler"#, "~> 1.0.0"
12
+ gem "jeweler"#, "~> 1.5.1"
13
+ #gem "rcov", ">= 0"
14
14
  gem "fakeweb"
15
+ gem "vcr", "~> 2.0.1"
15
16
  end
data/Gemfile.lock CHANGED
@@ -1,34 +1,40 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- crack (0.1.8)
5
- diff-lcs (1.1.2)
4
+ diff-lcs (1.1.3)
6
5
  fakeweb (1.3.0)
7
6
  git (1.2.5)
8
- httparty (0.6.1)
9
- crack (= 0.1.8)
10
- jeweler (1.5.1)
11
- bundler (~> 1.0.0)
7
+ httparty (0.8.2)
8
+ multi_json
9
+ multi_xml
10
+ jeweler (1.8.3)
11
+ bundler (~> 1.0)
12
12
  git (>= 1.2.5)
13
13
  rake
14
- rake (0.8.7)
15
- rcov (0.9.9)
16
- rspec (2.1.0)
17
- rspec-core (~> 2.1.0)
18
- rspec-expectations (~> 2.1.0)
19
- rspec-mocks (~> 2.1.0)
20
- rspec-core (2.1.0)
21
- rspec-expectations (2.1.0)
14
+ rdoc
15
+ json (1.6.6)
16
+ multi_json (1.3.2)
17
+ multi_xml (0.4.4)
18
+ rake (0.9.2.2)
19
+ rdoc (3.12)
20
+ json (~> 1.4)
21
+ rspec (2.8.0)
22
+ rspec-core (~> 2.8.0)
23
+ rspec-expectations (~> 2.8.0)
24
+ rspec-mocks (~> 2.8.0)
25
+ rspec-core (2.8.0)
26
+ rspec-expectations (2.8.0)
22
27
  diff-lcs (~> 1.1.2)
23
- rspec-mocks (2.1.0)
28
+ rspec-mocks (2.8.0)
29
+ vcr (2.0.1)
24
30
 
25
31
  PLATFORMS
26
32
  ruby
27
33
 
28
34
  DEPENDENCIES
29
- bundler (~> 1.0.0)
35
+ bundler
30
36
  fakeweb
31
- httparty
32
- jeweler (~> 1.5.1)
33
- rcov
34
- rspec (~> 2.1.0)
37
+ httparty (>= 0.8.1)
38
+ jeweler
39
+ rspec (~> 2.8.0)
40
+ vcr (~> 2.0.1)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.4.0
data/get_token.rb ADDED
@@ -0,0 +1,40 @@
1
+ require 'rubygems'
2
+ require 'sinatra'
3
+ require 'oauth2' # ~> 0.5.0
4
+ require 'json'
5
+
6
+ def client
7
+ OAuth2::Client.new('CLIENT ID', 'SECRET',
8
+ :ssl => {:ca_file => '/etc/ssl/ca-bundle.pem'},
9
+ :site => 'https://api.github.com',
10
+ :authorize_url => 'https://github.com/login/oauth/authorize',
11
+ :token_url => 'https://github.com/login/oauth/access_token')
12
+ end
13
+
14
+ get "/" do
15
+ %(<p>Update the <code>#new_client</code> method in the sinatra app and <a href="/auth/github">try to authorize</a>.</p>)
16
+ end
17
+
18
+ get '/auth/github' do
19
+ url = client.auth_code.authorize_url(:redirect_uri => redirect_uri, :scope => 'user')
20
+ puts "Redirecting to URL: #{url.inspect}"
21
+ redirect url
22
+ end
23
+
24
+ get '/auth/github/callback' do
25
+ puts params[:code]
26
+ begin
27
+ access_token = client.auth_code.get_token(params[:code], :redirect_uri => redirect_uri)
28
+ user = JSON.parse(access_token.get('/user').body)
29
+ "<p>Your OAuth access token: #{access_token.token}</p><p>Your extended profile data:\n#{user.inspect}</p>"
30
+ rescue OAuth2::Error => e
31
+ %(<p>Outdated ?code=#{params[:code]}:</p><p>#{$!}</p><p><a href="/auth/github">Retry</a></p>)
32
+ end
33
+ end
34
+
35
+ def redirect_uri(path = '/auth/github/callback', query = nil)
36
+ uri = URI.parse(request.url)
37
+ uri.path = path
38
+ uri.query = query
39
+ uri.to_s
40
+ end
@@ -4,14 +4,14 @@
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
- s.name = %q{gitnetworkitis}
8
- s.version = "0.2.0"
7
+ s.name = "gitnetworkitis"
8
+ s.version = "0.4.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Julian Coutu"]
12
- s.date = %q{2011-05-26}
13
- s.description = %q{Git API Gem utilizing the Network API}
14
- s.email = %q{jcoutu@phaseiiicreations.com}
12
+ s.date = "2012-04-20"
13
+ s.description = "Git API Gem utilizing the Network API"
14
+ s.email = "jcoutu@phaseiiicreations.com"
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE.txt",
17
17
  "README.rdoc"
@@ -26,102 +26,67 @@ Gem::Specification.new do |s|
26
26
  "README.rdoc",
27
27
  "Rakefile",
28
28
  "VERSION",
29
+ "get_token.rb",
29
30
  "gitnetworkitis-0.1.0.gem",
30
31
  "gitnetworkitis.gemspec",
31
32
  "lib/gitnetworkitis.rb",
32
33
  "lib/gitnetworkitis/base.rb",
34
+ "lib/gitnetworkitis/batch_response.rb",
33
35
  "lib/gitnetworkitis/branch.rb",
34
36
  "lib/gitnetworkitis/commit.rb",
35
- "lib/gitnetworkitis/network_data.rb",
36
- "lib/gitnetworkitis/network_meta.rb",
37
+ "lib/gitnetworkitis/commit_getter.rb",
38
+ "lib/gitnetworkitis/getter.rb",
39
+ "lib/gitnetworkitis/json_helper.rb",
37
40
  "lib/gitnetworkitis/repository.rb",
38
41
  "spec/base_spec.rb",
39
42
  "spec/branch_spec.rb",
40
- "spec/commit_spec.rb",
43
+ "spec/getter_spec.rb",
44
+ "spec/github_config.yml.example",
41
45
  "spec/gitnetworkitis_spec.rb",
42
- "spec/network_data_spec.rb",
43
- "spec/network_meta_spec.rb",
44
46
  "spec/repository_spec.rb",
45
- "spec/responses/branch_pages/turingstudio_loupe_51ac36280d2dfe16c37b66ef344859c9c714c8e1?page=0.json",
46
- "spec/responses/branch_pages/turingstudio_loupe_51ac36280d2dfe16c37b66ef344859c9c714c8e1?page=1.json",
47
- "spec/responses/branch_pages/turingstudio_loupe_51ac36280d2dfe16c37b66ef344859c9c714c8e1?page=2.json",
48
- "spec/responses/branch_pages/turingstudio_loupe_51ac36280d2dfe16c37b66ef344859c9c714c8e1?page=3.json",
49
- "spec/responses/branch_pages/turingstudio_loupe_51ac36280d2dfe16c37b66ef344859c9c714c8e1?page=4.json",
50
- "spec/responses/branch_pages/turingstudio_loupe_51ac36280d2dfe16c37b66ef344859c9c714c8e1?page=5.json",
51
- "spec/responses/branch_pages/turingstudio_loupe_bec7b23dc57b14d89fa2829e8c32a108a18e7248?page=0.json",
52
- "spec/responses/branch_pages/turingstudio_loupe_bec7b23dc57b14d89fa2829e8c32a108a18e7248?page=1.json",
53
- "spec/responses/branch_pages/turingstudio_loupe_bec7b23dc57b14d89fa2829e8c32a108a18e7248?page=2.json",
54
- "spec/responses/branch_pages/turingstudio_loupe_bec7b23dc57b14d89fa2829e8c32a108a18e7248?page=3.json",
55
- "spec/responses/branch_pages/turingstudio_loupe_bec7b23dc57b14d89fa2829e8c32a108a18e7248?page=4.json",
56
- "spec/responses/branch_pages/turingstudio_loupe_c3aeb61e37f94bbb67c4f14b52c23b8e54d30d0e?page=0.json",
57
- "spec/responses/branch_pages/turingstudio_loupe_c3aeb61e37f94bbb67c4f14b52c23b8e54d30d0e?page=1.json",
58
- "spec/responses/branch_pages/turingstudio_loupe_c3aeb61e37f94bbb67c4f14b52c23b8e54d30d0e?page=2.json",
59
- "spec/responses/branch_pages/turingstudio_loupe_c3aeb61e37f94bbb67c4f14b52c23b8e54d30d0e?page=3.json",
60
- "spec/responses/branch_pages/turingstudio_loupe_c3aeb61e37f94bbb67c4f14b52c23b8e54d30d0e?page=4.json",
61
- "spec/responses/girlambition/0-500.json",
62
- "spec/responses/girlambition/1002-1502.json",
63
- "spec/responses/girlambition/1503-2003.json",
64
- "spec/responses/girlambition/2004-2504.json",
65
- "spec/responses/girlambition/2505-3005.json",
66
- "spec/responses/girlambition/3006-3506.json",
67
- "spec/responses/girlambition/3507-4007.json",
68
- "spec/responses/girlambition/4008-4508.json",
69
- "spec/responses/girlambition/4509-4999.json",
70
- "spec/responses/girlambition/501-1001.json",
71
- "spec/responses/girlambition/repos_show_turingstudio_website-girlambition_branches.json",
72
- "spec/responses/girlambition/turingstudio_website-girlambition_network_meta.json",
73
- "spec/responses/loupe/repos_show_turingstudio_loupe.json",
74
- "spec/responses/loupe/repos_show_turingstudio_loupe_branches.json",
75
- "spec/responses/loupe/turingstudio_loupe_068161e2c05a6b8029a7eb410dd27b1dfa531338?start=1&end=5.json",
76
- "spec/responses/loupe/turingstudio_loupe_068161e2c05a6b8029a7eb410dd27b1dfa531338?start=130.json",
77
- "spec/responses/loupe/turingstudio_loupe_branch.json",
78
- "spec/responses/loupe/turingstudio_loupe_network_data.json",
79
- "spec/responses/loupe/turingstudio_loupe_network_meta.json",
80
- "spec/responses/repos_show_jcoutu.json",
81
- "spec/responses/repos_watched_jcoutu.json",
82
- "spec/spec_helper.rb"
47
+ "spec/spec_helper.rb",
48
+ "spec/support/vcr_setup.rb",
49
+ "spec/vcr_cassettes/all_branches.json",
50
+ "spec/vcr_cassettes/all_repos.json",
51
+ "spec/vcr_cassettes/bad_creds.json",
52
+ "spec/vcr_cassettes/find_repo.json",
53
+ "spec/vcr_cassettes/spec-branch-1_commits.json",
54
+ "spec/vcr_cassettes/spec-branch-1_since_date.json",
55
+ "spec/vcr_cassettes/spec-branch-1_since_sha.json",
56
+ "spec/vcr_cassettes/spec-branch-2_commits.json",
57
+ "spec/vcr_cassettes/spec-branch-3_commits.json"
83
58
  ]
84
- s.homepage = %q{http://github.com/jcoutu/gitnetworkitis}
59
+ s.homepage = "http://github.com/jcoutu/gitnetworkitis"
85
60
  s.licenses = ["MIT"]
86
61
  s.require_paths = ["lib"]
87
- s.rubygems_version = %q{1.5.2}
88
- s.summary = %q{Git API Gem utilizing the Network API}
89
- s.test_files = [
90
- "spec/base_spec.rb",
91
- "spec/branch_spec.rb",
92
- "spec/commit_spec.rb",
93
- "spec/gitnetworkitis_spec.rb",
94
- "spec/network_data_spec.rb",
95
- "spec/network_meta_spec.rb",
96
- "spec/repository_spec.rb",
97
- "spec/spec_helper.rb"
98
- ]
62
+ s.rubygems_version = "1.8.15"
63
+ s.summary = "Git API Gem utilizing the Network API"
99
64
 
100
65
  if s.respond_to? :specification_version then
101
66
  s.specification_version = 3
102
67
 
103
68
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
104
- s.add_runtime_dependency(%q<httparty>, [">= 0"])
105
- s.add_development_dependency(%q<rspec>, ["~> 2.1.0"])
106
- s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
107
- s.add_development_dependency(%q<jeweler>, ["~> 1.5.1"])
108
- s.add_development_dependency(%q<rcov>, [">= 0"])
69
+ s.add_runtime_dependency(%q<httparty>, [">= 0.8.1"])
70
+ s.add_development_dependency(%q<rspec>, ["~> 2.8.0"])
71
+ s.add_development_dependency(%q<bundler>, [">= 0"])
72
+ s.add_development_dependency(%q<jeweler>, [">= 0"])
109
73
  s.add_development_dependency(%q<fakeweb>, [">= 0"])
74
+ s.add_development_dependency(%q<vcr>, ["~> 2.0.1"])
110
75
  else
111
- s.add_dependency(%q<httparty>, [">= 0"])
112
- s.add_dependency(%q<rspec>, ["~> 2.1.0"])
113
- s.add_dependency(%q<bundler>, ["~> 1.0.0"])
114
- s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
115
- s.add_dependency(%q<rcov>, [">= 0"])
76
+ s.add_dependency(%q<httparty>, [">= 0.8.1"])
77
+ s.add_dependency(%q<rspec>, ["~> 2.8.0"])
78
+ s.add_dependency(%q<bundler>, [">= 0"])
79
+ s.add_dependency(%q<jeweler>, [">= 0"])
116
80
  s.add_dependency(%q<fakeweb>, [">= 0"])
81
+ s.add_dependency(%q<vcr>, ["~> 2.0.1"])
117
82
  end
118
83
  else
119
- s.add_dependency(%q<httparty>, [">= 0"])
120
- s.add_dependency(%q<rspec>, ["~> 2.1.0"])
121
- s.add_dependency(%q<bundler>, ["~> 1.0.0"])
122
- s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
123
- s.add_dependency(%q<rcov>, [">= 0"])
84
+ s.add_dependency(%q<httparty>, [">= 0.8.1"])
85
+ s.add_dependency(%q<rspec>, ["~> 2.8.0"])
86
+ s.add_dependency(%q<bundler>, [">= 0"])
87
+ s.add_dependency(%q<jeweler>, [">= 0"])
124
88
  s.add_dependency(%q<fakeweb>, [">= 0"])
89
+ s.add_dependency(%q<vcr>, ["~> 2.0.1"])
125
90
  end
126
91
  end
127
92
 
@@ -1,51 +1,21 @@
1
1
  module GitNetworkitis
2
2
  class Base
3
- include HTTParty
4
- attr_accessor :username, :token
3
+ include JSONHelper
4
+ attr_accessor :token
5
5
 
6
- def initialize(username, token, options={})
7
- @username = username
6
+ # token is an oauth2 token
7
+ def initialize(token, options={})
8
8
  @token = token
9
- self.class.basic_auth "#{username}/token", token
10
9
  options.each do |key, value|
11
10
  method = "#{key}="
12
11
  self.send(method, value) if respond_to? method
13
12
  end
14
13
  end
15
14
 
16
- def get url
17
- ret = self.class.get(url)
18
- if ret.response.code == "200"
19
- return ret
20
- else
21
- raise "Unable to find Github Repository"
22
- end
23
- end
24
-
25
- def parse_json json
26
- begin
27
- return JSON.parse(escape_json(json))
28
- rescue => e
29
- raise "Unable to parse JSON result" #{e.message}
30
- end
31
- end
32
-
33
-
34
- private
35
- def parse_attributes(json, object)
36
- json.each do |key, value|
37
- method = "#{key}="
38
- if object.respond_to? method
39
- object.send(method, value)
40
- end
41
- end
42
- object
43
- end
44
-
45
- #This is for parsing bad json returned from github
46
- def escape_json(json)
47
- json.gsub(/(....\[31m)./, '')
48
- end
49
-
15
+ # see Getter for options
16
+ def get(url, options={})
17
+ opts = {access_token: token}.merge options
18
+ Getter.new(url, opts).get
50
19
  end
51
- end
20
+ end
21
+ end
@@ -0,0 +1,24 @@
1
+ module GitNetworkitis
2
+ # This class serves as a sort of proxy for HTTParty::Response. When a
3
+ # Base#batched_get is performed, a BatchResponse object is returned,
4
+ # with a #body made up of the concatenation of its responses'. This
5
+ # way, paged responses (like for commits) can appear as a single
6
+ # response body to the code that handles it. This is necessary
7
+ # because HTTParty::Response has no setter on its #body attribute,
8
+ # and sets it directly from its #response on #initialize.
9
+ class BatchResponse
10
+
11
+ attr_reader :responses, :body
12
+
13
+ def initialize responses
14
+ @responses = responses
15
+
16
+ # Since we're combining response bodies, we have a series of JSON
17
+ # arrays that need to be joined (hence the gsub).
18
+ @body = responses.map {|r| r.body.to_s }.
19
+ join('').
20
+ gsub(/\]\[/, ', ')
21
+ end
22
+
23
+ end
24
+ end
@@ -1,42 +1,21 @@
1
1
  module GitNetworkitis
2
2
  class Branch < Base
3
- base_uri 'https://github.com/api/v2/json/'
4
-
5
- attr_accessor :name, :id, :owner, :repo
3
+ attr_accessor :commit, :name, :owner, :repo
6
4
 
7
5
  #Retrieves all branches based on a specific repo.
8
6
  def find_all(options={})
9
- if options.has_key?(:owner) & options.has_key?(:repo)
10
- resp = get("/repos/show/#{options[:owner]}/#{options[:repo]}/branches")
11
- json_result = parse_json(escape_json(resp.body.to_s))
12
- result = Array.new
13
- json_result["branches"].each do |branch|
14
- result.push Branch.new(self.username, self.token, {:name =>branch[0], :id => branch[1], :owner => options[:owner], :repo => options[:repo]})
7
+ if options.has_key?(:owner) & options.has_key?(:repo)
8
+ resp = get("/repos/#{options[:owner]}/#{options[:repo]}/branches")
9
+ parse_json(escape_json(resp.body.to_s)).inject([]) do |branches, branch|
10
+ branches << parse_attributes(branch, Branch.new(token, :owner => options[:owner], :repo => options[:repo]))
15
11
  end
16
- return result
17
12
  end
18
13
  end
19
14
 
20
-
21
- #Loops pages and returns all commits specific to a branch
22
- def commits
23
- pages = true
24
- counter = 0
25
- result = Array.new
26
- while pages do
27
- resp = self.get("/commits/list/#{self.owner}/#{self.repo}/#{self.id}?page=#{counter}")
28
- json_result = parse_json(escape_json(resp.body.to_s))
29
- if !json_result.has_key?("error")
30
- json_result["commits"].each do |commit|
31
- temp_commit = parse_attributes(commit, Commit.new(self.username, self.token))
32
- result.push temp_commit
33
- end
34
- else
35
- pages = false
36
- end
37
- counter = counter+1
38
- end
39
- result
15
+ def commits(options={})
16
+ opts = {access_token: token, per_page: 100, batch: true}.merge options
17
+ CommitGetter.new("/repos/#{owner}/#{repo}/commits?sha=#{commit['sha']}", opts).get
40
18
  end
19
+
41
20
  end
42
- end
21
+ end
@@ -1,8 +1,5 @@
1
1
  module GitNetworkitis
2
2
  class Commit < Base
3
- base_uri 'https://github.com/'
4
-
5
- attr_accessor :parents, :author, :time, :id, :date, :gravatar, :space, :message, :login
6
-
3
+ attr_accessor :sha, :url, :author, :committer, :message, :tree, :parents
7
4
  end
8
- end
5
+ end
@@ -0,0 +1,50 @@
1
+ module GitNetworkitis
2
+ #NOTE tested via the Branch specs
3
+ class CommitGetter < Getter
4
+ def get
5
+ if local_options[:since]
6
+ since_commits
7
+ else
8
+ response = super
9
+ build_commits response
10
+ end
11
+ end
12
+
13
+ private
14
+
15
+ def since_commits
16
+ since_date = DateTime.parse local_options[:since]
17
+ batched_since_commits {|c| c.committer['date'] }
18
+ rescue ArgumentError => e
19
+ batched_since_commits &:sha
20
+ end
21
+
22
+ def batched_since_commits &block
23
+ links = {next: url}
24
+ results = []
25
+ while links[:next] do
26
+ self.url = links[:next]
27
+ resp = single_get
28
+ staged_commits = build_commits resp
29
+ since_index = staged_commits.find_index {|c| yield(c) == local_options[:since] }
30
+ if since_index
31
+ results += staged_commits.first(since_index)
32
+ links = {}
33
+ else
34
+ results << staged_commits
35
+ links = build_links_from_headers resp.headers['link']
36
+ end
37
+ end
38
+ results
39
+ end
40
+
41
+ def build_commits(response)
42
+ parse_json(escape_json(response.body.to_s)).inject([]) do |commits, commit|
43
+ commit_attrs = commit['commit'].merge('sha' => commit['sha'], 'parents' => commit['parents'])
44
+ parsed_commit = parse_attributes(commit_attrs, Commit.new(query_options[:access_token]))
45
+ commits << parsed_commit
46
+ end
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,64 @@
1
+ module GitNetworkitis
2
+ class Getter
3
+ include HTTParty
4
+ include JSONHelper
5
+ base_uri 'https://api.github.com'
6
+
7
+ attr_accessor :url, :local_options, :query_options
8
+
9
+ LOCAL_KEYS = [:batch, :since, :branch]
10
+
11
+ def initialize(url, options={})
12
+ @url = url
13
+ scrub_local_options options
14
+ @query_options = options
15
+ end
16
+
17
+ def get
18
+ local_options[:batch] ? batched_get : single_get
19
+ end
20
+
21
+ private
22
+ def scrub_local_options(options={})
23
+ @local_options = LOCAL_KEYS.inject({}) {|opts, key| opts[key] = options.delete(key); opts }
24
+ @local_options[:batch] = true unless @local_options[:since].nil?
25
+ end
26
+
27
+ def single_get(use_query_options=true)
28
+ ret = use_query_options ? Getter.get(url, query: query_options) : Getter.get(url)
29
+ if ret.response.code == "200"
30
+ return ret
31
+ else
32
+ raise "Unable to find Github Repository"
33
+ end
34
+ end
35
+
36
+ def batched_get
37
+ resps = []
38
+ links = {next: url}
39
+ first_batch = true
40
+ while links[:next] do
41
+ self.url = links[:next]
42
+ resp = single_get first_batch
43
+ resps << resp
44
+ first_batch = false
45
+ links = build_links_from_headers resp.headers['link']
46
+ end
47
+ BatchResponse.new resps
48
+ end
49
+
50
+ # see the json files in spec/vcr_cassettes for examples of what the link headers look like
51
+ def build_links_from_headers(headers)
52
+ return {} if headers.nil?
53
+
54
+ links = headers.split(',')
55
+ links.inject({}) do |rel, link|
56
+ l = link.strip.split(';')
57
+ next_link = l.first[1...-1] # [1...-1] because the actual link is enclosed within '<' '>' tags
58
+ rel_command = l.last.strip.match(/rel=\"(.*)\"/).captures.first.to_sym # e.g. "rel=\"next\"" #=> :next
59
+ rel.tap {|r| r[rel_command] = next_link }
60
+ end
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +1,24 @@
1
+ module GitNetworkitis
2
+ module JSONHelper
3
+ def parse_json(json)
4
+ return JSON.parse(escape_json(json))
5
+ rescue => e
6
+ raise "Unable to parse JSON result" #{e.message}
7
+ end
8
+
9
+ #This is for parsing bad json returned from github
10
+ def escape_json(json)
11
+ json.gsub(/(....\[31m)./, '')
12
+ end
13
+
14
+ def parse_attributes(json, object)
15
+ json.each do |key, value|
16
+ method = "#{key}="
17
+ if object.respond_to? method
18
+ object.send(method, value)
19
+ end
20
+ end
21
+ object
22
+ end
23
+ end
24
+ end
@@ -1,44 +1,25 @@
1
1
  module GitNetworkitis
2
2
  class Repository < Base
3
- base_uri 'https://github.com/api/v2/json/'
3
+ attr_accessor :watchers, :homepage, :has_downloads, :forks, :url, :has_wiki, :size, :private
4
+ attr_accessor :owner, :name, :description, :open_issues
4
5
 
5
- attr_accessor :description, :has_wiki, :url, :forks, :open_issues, :forks, :name, :homepage, :watchers, :owner, :private, :pledgie, :size, :has_downloads
6
-
7
- def find_all_watched
8
- result = Array.new
9
- unless !self.username && !self.token
10
- resp = get("/repos/watched/#{self.username}")
11
- json_result = self.parse_json(resp.body.to_s)
12
- json_result["repositories"].each do |repo|
13
- result.push parse_attributes(repo, Repository.new(self.username, self.token))
14
- end
15
- end
16
- return result
17
- end
18
-
19
- def find_all_owned
20
- result = Array.new
21
- unless !self.username && !self.token
22
- resp = get("/repos/show/#{self.username}")
23
- json_result = parse_json(resp.body.to_s)
24
- json_result["repositories"].each do |repo|
25
- result.push parse_attributes(repo, Repository.new(self.username, self.token))
26
- end
6
+ #TODO use options to handle the optional filter params that github v3 supports
7
+ def find_all(options={})
8
+ resp = get("/user/repos", type: (options[:type] || 'all'))
9
+ parse_json(resp.body.to_s).inject([]) do |repos, repo|
10
+ repos << parse_attributes(repo, Repository.new(token))
27
11
  end
28
- return result
29
12
  end
30
13
 
31
14
  def find(options={})
32
- result = Array.new
33
- if options.has_key?(:owner) & options.has_key?(:repo)
34
- resp = get("/repos/show/#{options[:owner]}/#{options[:repo]}")
35
- json_result = parse_json(resp.body.to_s)
36
- parse_attributes(json_result["repository"], Repository.new(self.username, self.token))
15
+ if options.has_key?(:owner) & options.has_key?(:repo)
16
+ resp = get("/repos/#{options[:owner]}/#{options[:repo]}")
17
+ parse_attributes(parse_json(resp.body.to_s), Repository.new(token))
37
18
  end
38
19
  end
39
20
 
40
21
  def remote_id
41
- return "#{self.owner}/#{self.name}"
22
+ return "#{self.owner['login']}/#{self.name}"
42
23
  end
43
24
 
44
25
  end
@@ -1,11 +1,16 @@
1
1
  require 'httparty'
2
2
  require 'json'
3
3
 
4
- # GitNetworkitis stuff
5
- # By sorting them we ensure that api and base are loaded first on all sane operating systems
6
- Dir[File.join(File.dirname(__FILE__), "gitnetworkitis/*.rb")].sort.each { |f| require f }
4
+ ['gitnetworkitis/json_helper',
5
+ 'gitnetworkitis/base',
6
+ 'gitnetworkitis/commit',
7
+ 'gitnetworkitis/repository',
8
+ 'gitnetworkitis/branch',
9
+ 'gitnetworkitis/getter',
10
+ 'gitnetworkitis/commit_getter',
11
+ 'gitnetworkitis/batch_response'].each {|f| require File.join(File.dirname(__FILE__), f) }
7
12
 
8
13
  module GitNetworkitis
9
14
 
10
-
11
- end
15
+
16
+ end