github_api 0.9.7 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/README.md +24 -14
  2. data/features/cassettes/media/get_default.yml +84 -0
  3. data/features/cassettes/media/get_full_json.yml +83 -0
  4. data/features/cassettes/media/get_html_json.yml +81 -0
  5. data/features/cassettes/media/get_raw_json.yml +80 -0
  6. data/features/cassettes/media/get_text_json.yml +80 -0
  7. data/features/cassettes/repos/stats/commits.yml +80 -0
  8. data/features/cassettes/repos/stats/contribs.yml +221 -0
  9. data/features/cassettes/repos/stats/frequency.yml +54 -0
  10. data/features/cassettes/repos/stats/participation.yml +68 -0
  11. data/features/cassettes/repos/stats/punch.yml +76 -0
  12. data/features/cassettes/search/users_keyword.yml +70 -0
  13. data/features/gitignore.feature +1 -1
  14. data/features/media_type.feature +76 -0
  15. data/features/repos/statistics.feature +60 -0
  16. data/features/search.feature +11 -0
  17. data/features/step_definitions/github_api_steps.rb +4 -0
  18. data/lib/github_api.rb +2 -0
  19. data/lib/github_api/arguments.rb +1 -1
  20. data/lib/github_api/authorization.rb +1 -1
  21. data/lib/github_api/connection.rb +5 -7
  22. data/lib/github_api/core_ext/deep_merge.rb +13 -0
  23. data/lib/github_api/git_data/trees.rb +1 -1
  24. data/lib/github_api/gitignore.rb +5 -4
  25. data/lib/github_api/markdown.rb +7 -5
  26. data/lib/github_api/mime_type.rb +19 -41
  27. data/lib/github_api/paged_request.rb +1 -1
  28. data/lib/github_api/parameter_filter.rb +1 -1
  29. data/lib/github_api/params_hash.rb +59 -22
  30. data/lib/github_api/repos.rb +9 -3
  31. data/lib/github_api/repos/pub_sub_hubbub.rb +4 -2
  32. data/lib/github_api/repos/statistics.rb +94 -0
  33. data/lib/github_api/request.rb +17 -28
  34. data/lib/github_api/response_wrapper.rb +8 -0
  35. data/lib/github_api/say.rb +2 -1
  36. data/lib/github_api/scopes.rb +3 -2
  37. data/lib/github_api/search.rb +3 -3
  38. data/lib/github_api/utils/url.rb +5 -2
  39. data/lib/github_api/version.rb +2 -2
  40. data/spec/fixtures/repos/commit_activity.json +15 -0
  41. data/spec/fixtures/repos/contribs.json +20 -0
  42. data/spec/fixtures/repos/frequency.json +7 -0
  43. data/spec/fixtures/repos/participation.json +110 -0
  44. data/spec/fixtures/repos/punch_card.json +17 -0
  45. data/spec/github/arguments/parse_spec.rb +2 -2
  46. data/spec/github/core_ext/deep_merge_spec.rb +23 -0
  47. data/spec/github/git_data/trees/create_spec.rb +6 -0
  48. data/spec/github/gitignore/get_spec.rb +1 -1
  49. data/spec/github/mime_type_spec.rb +24 -55
  50. data/spec/github/params_hash_spec.rb +64 -0
  51. data/spec/github/pull_requests/list_spec.rb +1 -1
  52. data/spec/github/repos/statistics/code_frequency_spec.rb +25 -0
  53. data/spec/github/repos/statistics/commit_activity_spec.rb +29 -0
  54. data/spec/github/repos/statistics/contributors_spec.rb +29 -0
  55. data/spec/github/repos/statistics/participation_spec.rb +25 -0
  56. data/spec/github/repos/statistics/punch_card_spec.rb +25 -0
  57. data/spec/github/request_spec.rb +10 -11
  58. data/spec/github/response_wrapper/overwrites_spec.rb +19 -0
  59. data/spec/github/users/keys/update_spec.rb +1 -1
  60. metadata +73 -34
@@ -0,0 +1,70 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://<BASIC_AUTH>@api.github.com/legacy/user/search/location:Sheffield%20repos:20?access_token=<TOKEN>
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - application/vnd.github.v3.full+json,application/vnd.github.beta.full+json;q=0.7,application/vnd.github+json;q=0.5,application/json;q=0.1
12
+ Accept-Charset:
13
+ - utf-8
14
+ User-Agent:
15
+ - Github Ruby Gem 0.9.7
16
+ Content-Type:
17
+ - application/json
18
+ Accept-Encoding:
19
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
20
+ response:
21
+ status:
22
+ code: 200
23
+ message: OK
24
+ headers:
25
+ Server:
26
+ - GitHub.com
27
+ Date:
28
+ - Sat, 18 May 2013 13:33:41 GMT
29
+ Content-Type:
30
+ - application/json; charset=utf-8
31
+ Transfer-Encoding:
32
+ - chunked
33
+ Connection:
34
+ - keep-alive
35
+ Status:
36
+ - 200 OK
37
+ X-Ratelimit-Limit:
38
+ - '5000'
39
+ X-Ratelimit-Remaining:
40
+ - '4999'
41
+ X-Github-Media-Type:
42
+ - github.v3; param=full; format=json
43
+ X-Content-Type-Options:
44
+ - nosniff
45
+ Access-Control-Allow-Credentials:
46
+ - 'true'
47
+ Access-Control-Expose-Headers:
48
+ - Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-OAuth-Scopes, X-Accepted-OAuth-Scopes
49
+ Access-Control-Allow-Origin:
50
+ - ! '*'
51
+ Etag:
52
+ - ! '"719c73d7273332047f0d1eacf695cedd"'
53
+ Cache-Control:
54
+ - max-age=0, private, must-revalidate
55
+ Vary:
56
+ - Accept-Encoding
57
+ Content-Encoding:
58
+ - gzip
59
+ body:
60
+ encoding: ASCII-8BIT
61
+ string: !binary |-
62
+ H4sIAAAAAAAAA3WQ3WrDMAyFXyX4uh124qRJXmEMxn5uNkZQ/JMaHDs49kYp
63
+ fffJoYXBNvCFj/Tp6KAzSasKK+nfz8RI0m9yzzmvWEl2ZArwCRHCsPX0WPJO
64
+ 1nXDgepW1EDHplNUHpis2453OJDHHcwK6UVFtJpTAHHEjvWTcb/LV/jR+BiK
65
+ hxusk7V/d6wXEI3PTs9HpbVRVu6KV2eiksW9cZP0c94Gbkow5RxPaTxhJZ6W
66
+ rHJAVEsarRFDUIsfhE8ukr6kO5I1HiN/tbfWf223qZof8obn4ip8QFN2h7wI
67
+ CjDDAGhFSsroPr/2hR36ivWUvuHWK/MfcPm4fAP71GbikAEAAA==
68
+ http_version: !!null
69
+ recorded_at: Sat, 18 May 2013 13:33:41 GMT
70
+ recorded_with: VCR 2.4.0
@@ -29,7 +29,7 @@ Feature: Markdown API
29
29
  | template_name |
30
30
  | Ruby |
31
31
  And I pass the following request options:
32
- | mime |
32
+ | accept |
33
33
  | application/vnd.github.raw |
34
34
  When I make request within a cassette named "gitignore/get_raw"
35
35
  Then the response status should be 200
@@ -0,0 +1,76 @@
1
+ Feature: Media Type
2
+
3
+ Background:
4
+ Given I have "Github::Issues" instance
5
+
6
+ Scenario: Default media
7
+
8
+ Given I want to get resource with the following params:
9
+ | user | repo | issue_id |
10
+ | peter-murach | github | 108 |
11
+ When I make request within a cassette named "media/get_default"
12
+ Then the response status should be 200
13
+ And the request header Accept should be
14
+ """
15
+ application/vnd.github.v3+json,application/vnd.github.beta+json;q=0.5,application/json;q=0.1
16
+ """
17
+
18
+ Scenario: Raw media
19
+
20
+ Given I want to get resource with the following params:
21
+ | user | repo | issue_id |
22
+ | peter-murach | github | 108 |
23
+ And I pass the following request options:
24
+ | media |
25
+ | raw |
26
+ When I make request within a cassette named "media/get_raw_json"
27
+ Then the response status should be 200
28
+ And the request header Accept should be
29
+ """
30
+ application/vnd.github.v3.raw+json
31
+ """
32
+
33
+ Scenario: Text media
34
+
35
+ Given I want to get resource with the following params:
36
+ | user | repo | issue_id |
37
+ | peter-murach | github | 108 |
38
+ And I pass the following request options:
39
+ | media |
40
+ | text |
41
+ When I make request within a cassette named "media/get_text_json"
42
+ Then the response status should be 200
43
+ And the request header Accept should be
44
+ """
45
+ application/vnd.github.v3.text+json
46
+ """
47
+
48
+ Scenario: Html media
49
+
50
+ Given I want to get resource with the following params:
51
+ | user | repo | issue_id |
52
+ | peter-murach | github | 108 |
53
+ And I pass the following request options:
54
+ | media |
55
+ | html |
56
+ When I make request within a cassette named "media/get_html_json"
57
+ Then the response status should be 200
58
+ And the request header Accept should be
59
+ """
60
+ application/vnd.github.v3.html+json
61
+ """
62
+
63
+ Scenario: Full media
64
+
65
+ Given I want to get resource with the following params:
66
+ | user | repo | issue_id |
67
+ | peter-murach | github | 108 |
68
+ And I pass the following request options:
69
+ | media |
70
+ | beta.full |
71
+ When I make request within a cassette named "media/get_full_json"
72
+ Then the response status should be 200
73
+ And the request header Accept should be
74
+ """
75
+ application/vnd.github.beta.full+json
76
+ """
@@ -0,0 +1,60 @@
1
+ Feature: Statistics API
2
+
3
+ Background:
4
+ Given I have "Github::Repos::Statistics" instance
5
+
6
+ Scenario: Contributors
7
+
8
+ Given I want contributors resources
9
+ And I pass the following request options:
10
+ | user | repo |
11
+ | peter-murach | github |
12
+ When I make request within a cassette named "repos/stats/contribs"
13
+ Then the response status should be 200
14
+ And the response type should be JSON
15
+ And the response should not be empty
16
+
17
+ Scenario: Commit Activity
18
+
19
+ Given I want commit_activity resources
20
+ And I pass the following request options:
21
+ | user | repo |
22
+ | peter-murach | github |
23
+ When I make request within a cassette named "repos/stats/commits"
24
+ Then the response status should be 200
25
+ And the response type should be JSON
26
+ And the response should not be empty
27
+
28
+ # Scenario: Code Frequency
29
+ #
30
+ # Given I want code_frequency resources
31
+ # And I pass the following request options:
32
+ # | user | repo |
33
+ # | peter-murach | github |
34
+ # When I make request within a cassette named "repos/stats/frequency"
35
+ # Then the response status should be 200
36
+ # And the response type should be JSON
37
+ # And the response should not be empty
38
+
39
+ Scenario: Participation
40
+
41
+ Given I want participation resources
42
+ And I pass the following request options:
43
+ | user | repo |
44
+ | peter-murach | github |
45
+ When I make request within a cassette named "repos/stats/participation"
46
+ Then the response status should be 200
47
+ And the response type should be JSON
48
+ And the response should not be empty
49
+
50
+ Scenario: Punch Card
51
+
52
+ Given I want punch_card resources
53
+ And I pass the following request options:
54
+ | user | repo |
55
+ | peter-murach | github |
56
+ When I make request within a cassette named "repos/stats/punch"
57
+ Then the response status should be 200
58
+ And the response type should be JSON
59
+ And the response should not be empty
60
+
@@ -36,6 +36,17 @@ Feature: Search API
36
36
  And the response type should be JSON
37
37
  And the response should not be empty
38
38
 
39
+ Scenario: Users with complex keyword
40
+
41
+ Given I want users resource
42
+ And I pass the following request options:
43
+ | keyword |
44
+ | location:Sheffield repos:20 |
45
+ When I make request within a cassette named "search/users_keyword"
46
+ Then the response status should be 200
47
+ And the response type should be JSON
48
+ And the response should not be empty
49
+
39
50
  Scenario: Email
40
51
 
41
52
  Given I want email resource
@@ -71,6 +71,10 @@ When /^I iterate through collection pages$/ do
71
71
  end
72
72
  end
73
73
 
74
+ Then /^the request header (.*) should be$/ do |header, value|
75
+ expect(@response.headers.env[:request_headers][header]).to eql(value)
76
+ end
77
+
74
78
  Then /^the response collection of resources is different for "([^"]*)" attribute$/ do |attr|
75
79
  @next_response.first.send(:"#{attr}").should_not eql @response.first.send(:"#{attr}")
76
80
  end
@@ -7,6 +7,7 @@ require 'github_api/utils/url'
7
7
  require 'github_api/connection'
8
8
  require 'github_api/deprecation'
9
9
  require 'github_api/core_ext/ordered_hash'
10
+ require 'github_api/core_ext/deep_merge'
10
11
 
11
12
  module Github
12
13
  extend Configuration
@@ -90,6 +91,7 @@ module Github
90
91
  :PagedRequest => 'paged_request',
91
92
  :Validations => 'validations',
92
93
  :ParameterFilter => 'parameter_filter',
94
+ :ParamsHash => 'params_hash',
93
95
  :Normalizer => 'normalizer'
94
96
 
95
97
  end # Github
@@ -45,7 +45,7 @@ module Github
45
45
  # Arguments can be part of parameters hash or be simple string arguments.
46
46
  #
47
47
  def parse(*args, &block)
48
- options = args.extract_options!
48
+ options = ParamsHash.new(args.extract_options!)
49
49
  normalize! options
50
50
 
51
51
  if !args.size.zero?
@@ -25,7 +25,7 @@ module Github
25
25
 
26
26
  # Sends authorization request to GitHub.
27
27
  # = Parameters
28
- # * <tt>:redirect_uri</tt> - Required string.
28
+ # * <tt>:redirect_uri</tt> - Optional string.
29
29
  # * <tt>:scope</tt> - Optional string. Comma separated list of scopes.
30
30
  # Available scopes:
31
31
  # * (no scope) - public read-only access (includes public user profile info, public repo info, and gists).
@@ -26,17 +26,15 @@ module Github
26
26
  def default_options(options={})
27
27
  {
28
28
  :headers => {
29
- ACCEPT => "application/vnd.github.v3.full+json," \
30
- "application/vnd.github.beta.full+json;q=0.7," \
31
- "application/vnd.github+json;q=0.5," \
29
+ ACCEPT => "application/vnd.github.v3+json," \
30
+ "application/vnd.github.beta+json;q=0.5," \
32
31
  "application/json;q=0.1",
33
32
  ACCEPT_CHARSET => "utf-8",
34
- USER_AGENT => user_agent,
35
- CONTENT_TYPE => 'application/json'
33
+ USER_AGENT => user_agent
36
34
  },
37
- :ssl => options.fetch(:ssl) { ssl },
35
+ :ssl => ssl,
38
36
  :url => options.fetch(:endpoint) { Github.endpoint }
39
- }.merge(options)
37
+ }.deep_merge(options)
40
38
  end
41
39
 
42
40
  # Default middleware stack that uses default adapter as specified at
@@ -0,0 +1,13 @@
1
+ class Hash
2
+ def deep_merge(other)
3
+ dup.deep_merge!(other)
4
+ end
5
+
6
+ def deep_merge!(other)
7
+ other.each_pair do |key, val|
8
+ tval = self[key]
9
+ self[key] = tval.is_a?(Hash) && val.is_a?(Hash) ? tval.deep_merge(val) : val
10
+ end
11
+ self
12
+ end
13
+ end
@@ -81,7 +81,7 @@ module Github
81
81
  def create(*args)
82
82
  arguments(args, :required => [:user, :repo]) do
83
83
  assert_required %w[ tree ]
84
- sift VALID_TREE_PARAM_NAMES, 'tree'
84
+ sift VALID_TREE_PARAM_NAMES, 'tree', { recursive: true }
85
85
  assert_values VALID_TREE_PARAM_VALUES, 'tree'
86
86
  end
87
87
 
@@ -32,16 +32,17 @@ module Github
32
32
  #
33
33
  # = Examples
34
34
  # github = Github.new
35
- # github.gitignore.get "template-name", mime: 'applicatin/vnd.github.raw'
35
+ # github.gitignore.get "template-name", accept: 'applicatin/vnd.github.raw'
36
36
  #
37
37
  def get(*args)
38
38
  params = arguments(args, :required => [:name]).params
39
39
 
40
- if (mime_type = params.delete('mime'))
41
- options = { :raw => true, :headers => {'Accept' => mime_type} }
40
+ if (media = params.delete('accept'))
41
+ params['accept'] = media
42
+ params['raw'] = true
42
43
  end
43
44
 
44
- get_request("/gitignore/templates/#{name}", params, options || {})
45
+ get_request("/gitignore/templates/#{name}", params)
45
46
  end
46
47
  alias :find :get
47
48
 
@@ -28,11 +28,12 @@ module Github
28
28
  arguments(args) do
29
29
  assert_required ['text']
30
30
  end
31
+ params = arguments.params
32
+ params['raw'] = true
31
33
 
32
- post_request("markdown", arguments.params, :raw => true)
34
+ post_request("markdown", arguments.params)
33
35
  end
34
36
 
35
-
36
37
  # Render a Markdown document in raw mode
37
38
  #
38
39
  # = Input
@@ -44,14 +45,15 @@ module Github
44
45
  # = Examples
45
46
  # github = Github.new
46
47
  # github.markdown.render_raw "Hello github/linguist#1 **cool**, and #1!",
47
- # "mime": "text/plain",
48
+ # "accept": "text/plain",
48
49
  #
49
50
  def render_raw(*args)
50
51
  params = arguments(args).params
51
52
  mime_type, params['data'] = params['mime'], args.shift
53
+ params['raw'] = true
54
+ params['accept'] = params.fetch('accept') { 'text/plain' }
52
55
 
53
- post_request("markdown/raw", params, :raw => true,
54
- :headers => {'Content-Type' => mime_type || 'text/plain'})
56
+ post_request("markdown/raw", params)
55
57
  end
56
58
 
57
59
  end # Markdown
@@ -3,51 +3,29 @@
3
3
  module Github
4
4
  module MimeType
5
5
 
6
- attr_accessor :accepts
7
-
8
- RESOURCE_LOOKUP = {
9
- :json => 'json',
10
- :issue => 'vnd.github-issue.',
11
- :issue_comment => 'vnd.github-issuecomment.',
12
- :commit_comment => 'vnd.github-commitcomment.',
13
- :pull_request => 'vnd.github-pull.',
14
- :pull_comment => 'vnd.github-pullcomment.',
15
- :gist_comment => 'vnd.github-gistcomment.',
16
- :blob => 'vnd.github-blob.'
17
- }
18
-
19
- MIME_LOOKUP = {
20
- :json => 'json',
21
- :blob => 'raw',
22
- :raw => 'raw+json',
23
- :text => 'text+json',
24
- :html => 'html+json',
25
- :full => 'full+json'
6
+ MEDIA_LOOKUP = {
7
+ 'json' => 'json',
8
+ 'blob' => 'raw',
9
+ 'raw' => 'raw+json',
10
+ 'text' => 'text+json',
11
+ 'html' => 'html+json',
12
+ 'full' => 'full+json'
26
13
  }
27
14
 
28
- def parse(resource = nil, mime_type = :json)
29
- resource = lookup_resource(resource) if resource
30
- mime_type = lookup_mime(mime_type)
31
- self.accepts = "application/#{resource || ''}#{mime_type}"
32
- end
33
-
34
- def lookup_resource(name)
35
- RESOURCE_LOOKUP.fetch(name)
36
- end
37
-
38
- def lookup_mime(name)
39
- MIME_LOOKUP.fetch(name)
15
+ # Parse media type param
16
+ #
17
+ def parse(media)
18
+ version = 'v3'
19
+ media.sub!(/^[.]*|[.]*$/,"")
20
+ media = media.include?('+') ? media.split('+')[0] : media
21
+ version, media = media.split('.') if media.include?('.')
22
+ media_type = lookup_media(media)
23
+ "application/vnd.github.#{version}.#{media_type}"
40
24
  end
41
25
 
42
- def _normalize_name(name)
43
- puts "NAME: #{name}"
44
- case name
45
- when String
46
- name.strip.downcase.to_sym
47
- when Symbol
48
- name
49
- else
50
- raise ArgumentError, 'Provided MIME Type is not a valid or recognized entry'
26
+ def lookup_media(name)
27
+ MEDIA_LOOKUP.fetch(name) do
28
+ raise ArgumentError, "Provided Media Type #{name} is not valid"
51
29
  end
52
30
  end
53
31