reenhanced_bitbucket_api 0.1.6 → 0.3.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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/lib/bitbucket_rest_api/api/arguments.rb +248 -0
  3. data/lib/bitbucket_rest_api/api/config/property.rb +30 -0
  4. data/lib/bitbucket_rest_api/api/config/property_set.rb +118 -0
  5. data/lib/bitbucket_rest_api/api/config.rb +107 -0
  6. data/lib/bitbucket_rest_api/api/factory.rb +29 -0
  7. data/lib/bitbucket_rest_api/api.rb +155 -33
  8. data/lib/bitbucket_rest_api/{invitations.rb → client/invitations.rb} +4 -3
  9. data/lib/bitbucket_rest_api/{issues → client/issues}/comments.rb +2 -11
  10. data/lib/bitbucket_rest_api/{issues → client/issues}/components.rb +3 -6
  11. data/lib/bitbucket_rest_api/{issues → client/issues}/milestones.rb +3 -7
  12. data/lib/bitbucket_rest_api/{issues.rb → client/issues.rb} +9 -25
  13. data/lib/bitbucket_rest_api/{repos → client/repos}/changesets.rb +3 -2
  14. data/lib/bitbucket_rest_api/{repos → client/repos}/following.rb +2 -1
  15. data/lib/bitbucket_rest_api/{repos → client/repos}/keys.rb +2 -1
  16. data/lib/bitbucket_rest_api/client/repos/pull_requests/activity.rb +22 -0
  17. data/lib/bitbucket_rest_api/client/repos/pull_requests/comments.rb +40 -0
  18. data/lib/bitbucket_rest_api/client/repos/pull_requests/commits.rb +24 -0
  19. data/lib/bitbucket_rest_api/client/repos/pull_requests.rb +205 -0
  20. data/lib/bitbucket_rest_api/{repos → client/repos}/services.rb +2 -1
  21. data/lib/bitbucket_rest_api/{repos → client/repos}/sources.rb +2 -1
  22. data/lib/bitbucket_rest_api/{repos.rb → client/repos.rb} +26 -40
  23. data/lib/bitbucket_rest_api/{user.rb → client/user.rb} +2 -7
  24. data/lib/bitbucket_rest_api/{users → client/users}/account.rb +2 -1
  25. data/lib/bitbucket_rest_api/client/users.rb +14 -0
  26. data/lib/bitbucket_rest_api/client.rb +28 -32
  27. data/lib/bitbucket_rest_api/configuration.rb +24 -67
  28. data/lib/bitbucket_rest_api/connection.rb +15 -50
  29. data/lib/bitbucket_rest_api/constants.rb +1 -9
  30. data/lib/bitbucket_rest_api/core_ext/array.rb +1 -1
  31. data/lib/bitbucket_rest_api/error/invalid_options.rb +1 -1
  32. data/lib/bitbucket_rest_api/error/required_params.rb +1 -1
  33. data/lib/bitbucket_rest_api/error/unknown_value.rb +1 -1
  34. data/lib/bitbucket_rest_api/ext/faraday.rb +38 -0
  35. data/lib/bitbucket_rest_api/middleware.rb +31 -0
  36. data/lib/bitbucket_rest_api/null_encoder.rb +25 -0
  37. data/lib/bitbucket_rest_api/page_iterator.rb +90 -0
  38. data/lib/bitbucket_rest_api/page_links.rb +33 -0
  39. data/lib/bitbucket_rest_api/paged_request.rb +29 -0
  40. data/lib/bitbucket_rest_api/pagination.rb +98 -0
  41. data/lib/bitbucket_rest_api/parameter_filter.rb +1 -1
  42. data/lib/bitbucket_rest_api/params_hash.rb +100 -0
  43. data/lib/bitbucket_rest_api/request/basic_auth.rb +4 -2
  44. data/lib/bitbucket_rest_api/request/jsonize.rb +5 -0
  45. data/lib/bitbucket_rest_api/request/oauth.rb +3 -3
  46. data/lib/bitbucket_rest_api/request/verbs.rb +53 -0
  47. data/lib/bitbucket_rest_api/request.rb +60 -36
  48. data/lib/bitbucket_rest_api/response/header.rb +68 -0
  49. data/lib/bitbucket_rest_api/response_wrapper.rb +157 -0
  50. data/lib/bitbucket_rest_api/result.rb +5 -77
  51. data/lib/bitbucket_rest_api/users.rb +4 -8
  52. data/lib/bitbucket_rest_api/validations/presence.rb +16 -11
  53. data/lib/bitbucket_rest_api/validations.rb +6 -6
  54. data/lib/bitbucket_rest_api/version.rb +2 -2
  55. data/lib/bitbucket_rest_api.rb +89 -44
  56. metadata +39 -131
  57. data/lib/bitbucket_rest_api/api_factory.rb +0 -30
@@ -1,54 +1,83 @@
1
1
  # encoding: utf-8
2
2
 
3
+ require 'bitbucket_rest_api/request/oauth'
4
+ require 'bitbucket_rest_api/request/basic_auth'
5
+ require 'bitbucket_rest_api/request/jsonize'
6
+
7
+ require 'bitbucket_rest_api/connection'
8
+
3
9
  module BitBucket
4
10
  # Defines HTTP verbs
5
- module Request
11
+ class Request
12
+ include Connection
6
13
 
7
- METHODS = [:get, :post, :put, :delete, :patch]
14
+ HTTP_METHODS = [:get, :post, :put, :delete, :patch]
8
15
  METHODS_WITH_BODIES = [ :post, :put, :patch ]
9
16
 
10
- def get_request(path, params={}, options={})
11
- request(:get, path, params, options)
12
- end
17
+ # Return http verb
18
+ #
19
+ # @return [Symbol]
20
+ attr_reader :action
13
21
 
14
- def patch_request(path, params={}, options={})
15
- request(:patch, path, params, options)
16
- end
22
+ # Return url
23
+ #
24
+ # @return [String]
25
+ attr_accessor :path
17
26
 
18
- def post_request(path, params={}, options={})
19
- request(:post, path, params, options)
20
- end
27
+ # Return api this request is associated with
28
+ #
29
+ # @return [BitBucket::API]
30
+ attr_reader :api
21
31
 
22
- def put_request(path, params={}, options={})
23
- request(:put, path, params, options)
32
+ # Create a new Request
33
+ #
34
+ # @return [BitBucket::Request]
35
+ #
36
+ # @api public
37
+ def initialize(action, path, api)
38
+ @action = action
39
+ @path = path
40
+ @api = api
24
41
  end
25
42
 
26
- def delete_request(path, params={}, options={})
27
- request(:delete, path, params, options)
28
- end
29
-
30
- def request(method, path, params, options)
31
- if !METHODS.include?(method)
32
- raise ArgumentError, "unkown http method: #{method}"
43
+ # Performs a request
44
+ #
45
+ # @param [Symbol] method - The Symbol the HTTP verb
46
+ # @param [String] path - String relative URL to access
47
+ # @param [Hash] params - Hash to configure the request API
48
+ #
49
+ # @return [BitBucket::ResponseWrapper]
50
+ #
51
+ # @api private
52
+ def call(current_options, params)
53
+ unless HTTP_METHODS.include?(action)
54
+ raise ArgumentError, "unknown http method: #{method}"
33
55
  end
34
- # _extract_mime_type(params, options)
35
56
 
36
- puts "EXECUTED: #{method} - #{path} with #{params} and #{options}" if ENV['DEBUG']
57
+ puts "EXECUTED: #{action} - #{path} with PARAMS: #{params}" if ENV['DEBUG']
58
+
59
+ request_options = params.options
60
+ connection_options = current_options.merge(request_options)
61
+ conn = connection(api, connection_options)
37
62
 
38
- conn = connection(options)
39
- path = (conn.path_prefix + path).gsub(/\/\//,'/') if conn.path_prefix != '/'
63
+ if conn.path_prefix != '/' && self.path.index(conn.path_prefix) != 0
64
+ self.path = (conn.path_prefix + self.path).gsub(/\/(\/)*/, '/')
65
+ end
40
66
 
41
- response = conn.send(method) do |request|
42
- case method.to_sym
43
- when *(METHODS - METHODS_WITH_BODIES)
44
- request.body = params.delete('data') if params.has_key?('data')
45
- request.url(path, params)
67
+ response = conn.send(action) do |request|
68
+ case action.to_sym
69
+ when *(HTTP_METHODS - METHODS_WITH_BODIES)
70
+ request.body = params.data if params.has_key?('data')
71
+ if params.has_key?('encoder')
72
+ request.params.params_encoder(params.encoder)
73
+ end
74
+ request.url(self.path, params.to_hash)
46
75
  when *METHODS_WITH_BODIES
47
- request.path = path
76
+ request.url(self.path, connection_options[:query] || {})
48
77
  request.body = extract_data_from_params(params) unless params.empty?
49
78
  end
50
79
  end
51
- response.body
80
+ ResponseWrapper.new(response, api)
52
81
  end
53
82
 
54
83
  private
@@ -58,10 +87,5 @@ module BitBucket
58
87
  return params
59
88
  end
60
89
 
61
- def _extract_mime_type(params, options) # :nodoc:
62
- options['resource'] = params['resource'] ? params.delete('resource') : ''
63
- options['mime_type'] = params['resource'] ? params.delete('mime_type') : ''
64
- end
65
-
66
90
  end # Request
67
91
  end # BitBucket
@@ -0,0 +1,68 @@
1
+ # encoding: utf-8
2
+
3
+ module BitBucket
4
+ class Response
5
+
6
+ # Represents http response header
7
+ class Header < Struct.new(:env)
8
+ include BitBucket::Constants
9
+
10
+ SUCCESSFUL_STATUSES = 200..299
11
+
12
+ def loaded?
13
+ !!env
14
+ end
15
+
16
+ # Requests are limited to API v3 to 5000 per hour.
17
+ def ratelimit_limit
18
+ loaded? ? env[:response_headers][RATELIMIT_LIMIT] : nil
19
+ end
20
+
21
+ def ratelimit_remaining
22
+ loaded? ? env[:response_headers][RATELIMIT_REMAINING] : nil
23
+ end
24
+
25
+ def cache_control
26
+ loaded? ? env[:response_headers][CACHE_CONTROL] : nil
27
+ end
28
+
29
+ def content_type
30
+ loaded? ? env[:response_headers][CONTENT_TYPE] : nil
31
+ end
32
+
33
+ def content_length
34
+ loaded? ? env[:response_headers][CONTENT_LENGTH] : nil
35
+ end
36
+
37
+ def etag
38
+ loaded? ? env[:response_headers][ETAG] : nil
39
+ end
40
+
41
+ def date
42
+ loaded? ? env[:response_headers][DATE] : nil
43
+ end
44
+
45
+ def location
46
+ loaded? ? env[:response_headers][LOCATION] : nil
47
+ end
48
+
49
+ def server
50
+ loaded? ? env[:response_headers][SERVER] : nil
51
+ end
52
+
53
+ def status
54
+ loaded? ? env[:status] : nil
55
+ end
56
+
57
+ def success?
58
+ SUCCESSFUL_STATUSES.include? status
59
+ end
60
+
61
+ # Returns raw body
62
+ def body
63
+ loaded? ? env[:body] : nil
64
+ end
65
+
66
+ end # Header
67
+ end # Response
68
+ end # BitBucket
@@ -0,0 +1,157 @@
1
+ # encoding: utf-8
2
+
3
+ module BitBucket
4
+
5
+ # A class responsible for proxing to faraday response
6
+ class ResponseWrapper
7
+ extend Forwardable
8
+ include Pagination
9
+ include Enumerable
10
+
11
+ attr_reader :response
12
+
13
+ attr_reader :current_api
14
+
15
+ attr_reader :env
16
+
17
+ def_delegators :body, :empty?, :size, :include?, :length, :to_a, :first, :flatten, :include?, :keys, :[]
18
+
19
+ def initialize(response, current_api)
20
+ @response = response
21
+ @current_api = current_api
22
+ @env = response.env
23
+ end
24
+
25
+ # Overwrite methods to hash keys
26
+ #
27
+ ['id', 'type', 'fork'].each do |method_name|
28
+ define_method(method_name) do
29
+ self.body.fetch(method_name.to_s)
30
+ end
31
+ end
32
+
33
+ # Request url
34
+ #
35
+ def url
36
+ response.env[:url].to_s
37
+ end
38
+
39
+ def body=(value)
40
+ @body = value
41
+ @env[:body] = value
42
+ end
43
+
44
+ # Response raw body
45
+ #
46
+ def body
47
+ @body ? @body : response.body
48
+ end
49
+
50
+ # Response status
51
+ #
52
+ def status
53
+ response.status
54
+ end
55
+
56
+ def success?
57
+ response.success?
58
+ end
59
+
60
+ def redirect?
61
+ status.to_i >= 300 && status.to_i < 400
62
+ end
63
+
64
+ def client_error?
65
+ status.to_i >= 400 && status.to_i < 500
66
+ end
67
+
68
+ def server_error?
69
+ status.to_i >= 500 && status.to_i < 600
70
+ end
71
+
72
+ # Return response headers
73
+ #
74
+ def headers
75
+ BitBucket::Response::Header.new(env)
76
+ end
77
+
78
+ # Lookup an attribute from the body if hash, otherwise behave like array index.
79
+ # Convert any key to string before calling.
80
+ #
81
+ def [](key)
82
+ if self.body.is_a?(Array)
83
+ self.body[key]
84
+ else
85
+ self.body.send(:"#{key}")
86
+ end
87
+ end
88
+
89
+ # Return response body as string
90
+ #
91
+ def to_s
92
+ body.to_s
93
+ end
94
+
95
+ # Convert the ResponseWrapper into a Hash
96
+ #
97
+ def to_hash
98
+ body.to_hash
99
+ end
100
+
101
+ # Convert the ResponseWrapper into an Array
102
+ #
103
+ def to_ary
104
+ body.to_ary
105
+ end
106
+
107
+ # Iterate over each resource inside the body
108
+ #
109
+ def each
110
+ body_parts = self.body.respond_to?(:each) ? self.body : [self.body]
111
+ return body_parts.to_enum unless block_given?
112
+ body_parts.each { |part| yield(part) }
113
+ end
114
+
115
+ # Check if body has an attribute
116
+ #
117
+ def has_key?(key)
118
+ self.body.is_a?(Hash) && self.body.has_key?(key)
119
+ end
120
+
121
+ # Coerce any method calls for body attributes
122
+ #
123
+ def method_missing(method_name, *args, &block)
124
+ if self.has_key?(method_name.to_s)
125
+ self.[](method_name, &block)
126
+ else
127
+ super
128
+ end
129
+ end
130
+
131
+ # Check if method is defined on the body
132
+ #
133
+ def respond_to?(method_name)
134
+ if self.has_key?(method_name.to_s)
135
+ true
136
+ else
137
+ super
138
+ end
139
+ end
140
+
141
+ # Print only response body
142
+ #
143
+ def inspect
144
+ "#<#{self.class.name} @body=\"#{self.body}\">"
145
+ end
146
+
147
+ # Compare the wrapper with other wrapper for equality
148
+ #
149
+ def ==(other)
150
+ return false unless other.is_a?(self.class)
151
+ return false unless (other.respond_to?(:env) && other.respond_to?(:body))
152
+ self.env == other.env && self.body == other.body
153
+ end
154
+ alias eql? ==
155
+
156
+ end # ResponseWrapper
157
+ end # BitBucket
@@ -3,9 +3,14 @@
3
3
  module BitBucket
4
4
  module Result
5
5
  include BitBucket::Constants
6
+ include Pagination
6
7
 
7
8
  # TODO Add result counts method to check total items looking at result links
8
9
 
10
+ def paginated?
11
+ loaded? ? !@env[:body][PARAM_PAGE].nil? : false
12
+ end
13
+
9
14
  def ratelimit_limit
10
15
  loaded? ? @env[:response_headers][RATELIMIT_LIMIT] : nil
11
16
  end
@@ -59,82 +64,5 @@ module BitBucket
59
64
  !!@env
60
65
  end
61
66
 
62
- # Return page links
63
- def links
64
- @@links = BitBucket::PageLinks.new(@env[:response_headers])
65
- end
66
-
67
- # Iterator like each for response pages. If there are no pages to
68
- # iterate over this method will return nothing.
69
- def each_page
70
- yield self.body
71
- while page_iterator.has_next?
72
- yield next_page
73
- end
74
- end
75
-
76
- # Retrives the result of the first page. Returns <tt>nil</tt> if there is
77
- # no first page - either because you are already on the first page
78
- # or there are no pages at all in the result.
79
- def first_page
80
- first_request = page_iterator.first
81
- self.instance_eval { @env = first_request.env } if first_request
82
- self.body
83
- end
84
-
85
- # Retrives the result of the next page. Returns <tt>nil</tt> if there is
86
- # no next page or no pages at all.
87
- def next_page
88
- next_request = page_iterator.next
89
- self.instance_eval { @env = next_request.env } if next_request
90
- self.body
91
- end
92
-
93
- # Retrives the result of the previous page. Returns <tt>nil</tt> if there is
94
- # no previous page or no pages at all.
95
- def prev_page
96
- prev_request = page_iterator.prev
97
- self.instance_eval { @env = prev_request.env } if prev_request
98
- self.body
99
- end
100
- alias :previous_page :prev_page
101
-
102
- # Retrives the result of the last page. Returns <tt>nil</tt> if there is
103
- # no last page - either because you are already on the last page,
104
- # there is only one page or there are no pages at all in the result.
105
- def last_page
106
- last_request = page_iterator.last
107
- self.instance_eval { @env = last_request.env } if last_request
108
- self.body
109
- end
110
-
111
- # Retrives a specific result for a page given page number.
112
- # The <tt>page_number</tt> parameter is not validate, hitting a page
113
- # that does not exist will return BitBucket API error. Consequently, if
114
- # there is only one page, this method returns nil
115
- def page(page_number)
116
- request = page_iterator.get_page(page_number)
117
- self.instance_eval { @env = request.env } if request
118
- self.body
119
- end
120
-
121
- # Returns <tt>true</tt> if there is another page in the result set,
122
- # otherwise <tt>false</tt>
123
- def has_next_page?
124
- page_iterator.has_next?
125
- end
126
-
127
- # Repopulates objects for new values
128
- def reset
129
- nil
130
- end
131
-
132
- private
133
-
134
- # Internally used page iterator
135
- def page_iterator # :nodoc:
136
- @@page_iterator = BitBucket::PageIterator.new(@env)
137
- end
138
-
139
67
  end # Result
140
68
  end # BitBucket
@@ -1,12 +1,10 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module BitBucket
4
- class Users < API
5
- extend AutoloadHelper
4
+ class Client::Users < API
5
+ @version = '1.0'
6
6
 
7
- # Load all the modules after initializing Repos to avoid superclass mismatch
8
- autoload_all 'bitbucket_rest_api/users',
9
- :Account => 'account'
7
+ require_all 'bitbucket_rest_api/users', 'account'
10
8
 
11
9
 
12
10
  # Creates new Users API
@@ -15,9 +13,7 @@ module BitBucket
15
13
  end
16
14
 
17
15
  # Access to Users::Account API
18
- def account
19
- @account ||= ApiFactory.new 'Users::Account'
20
- end
16
+ namespace :account
21
17
 
22
18
 
23
19
  end # Users
@@ -2,22 +2,27 @@
2
2
 
3
3
  module BitBucket
4
4
  module Validations
5
+ # A mixin to help validate presence of non-empty values
5
6
  module Presence
6
7
 
7
- # Ensures that essential arguments are present before request is made
8
+ # Ensure that esential arguments are present before request is made.
8
9
  #
9
- def _validate_presence_of(*params)
10
- params.each do |param|
11
- raise ArgumentError, "parameter cannot be nil" if param.nil?
12
- end
13
- end
10
+ # == Parameters
11
+ # Hash/Array of arguments to be checked against nil and empty string
12
+ #
13
+ # == Example
14
+ # assert_presence_of user: '...', repo: '...'
15
+ # assert_presence_of user, repo
16
+ #
17
+ def assert_presence_of(*args)
18
+ hash = args.last.is_a?(::Hash) ? args.pop : {}
14
19
 
20
+ errors = hash.select { |key, val| val.to_s.empty? }
21
+ raise Github::Error::Validations.new(errors) unless errors.empty?
15
22
 
16
- # Check if user or repository parameters are passed
17
- #
18
- def _validate_user_repo_params(user_name, repo_name)
19
- raise ArgumentError, "[user] parameter cannot be nil" if user_name.nil?
20
- raise ArgumentError, "[repo] parameter cannot be nil" if repo_name.nil?
23
+ args.each do |arg|
24
+ raise ArgumentError, "parameter cannot be nil" if arg.nil?
25
+ end
21
26
  end
22
27
 
23
28
  end # Presence
@@ -2,13 +2,12 @@
2
2
 
3
3
  module BitBucket
4
4
  module Validations
5
- extend AutoloadHelper
6
5
 
7
- autoload_all 'bitbucket_rest_api/validations',
8
- :Presence => 'presence',
9
- :Token => 'token',
10
- :Format => 'format',
11
- :Required => 'required'
6
+ BitBucket::require_all 'bitbucket_rest_api/validations',
7
+ 'presence',
8
+ 'token',
9
+ 'format',
10
+ 'required'
12
11
 
13
12
  include Presence
14
13
  include Format
@@ -18,6 +17,7 @@ module BitBucket
18
17
  VALID_API_KEYS = [
19
18
  'page',
20
19
  'per_page',
20
+ 'auto_pagination',
21
21
  'jsonp_callback'
22
22
  ]
23
23
 
@@ -3,8 +3,8 @@
3
3
  module BitBucket
4
4
  module VERSION
5
5
  MAJOR = 0
6
- MINOR = 1
7
- PATCH = 6
6
+ MINOR = 3
7
+ PATCH = 0
8
8
 
9
9
  STRING = [MAJOR, MINOR, PATCH].compact.join('.')
10
10
  end