codenamev_bitbucket_api 0.4.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 (86) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +43 -0
  3. data/README.md +169 -0
  4. data/Rakefile +3 -0
  5. data/lib/bitbucket_rest_api/api/actions.rb +50 -0
  6. data/lib/bitbucket_rest_api/api/arguments.rb +248 -0
  7. data/lib/bitbucket_rest_api/api/config/property.rb +30 -0
  8. data/lib/bitbucket_rest_api/api/config/property_set.rb +118 -0
  9. data/lib/bitbucket_rest_api/api/config.rb +107 -0
  10. data/lib/bitbucket_rest_api/api/factory.rb +29 -0
  11. data/lib/bitbucket_rest_api/api.rb +242 -0
  12. data/lib/bitbucket_rest_api/authorization.rb +34 -0
  13. data/lib/bitbucket_rest_api/client/invitations.rb +16 -0
  14. data/lib/bitbucket_rest_api/client/issues/comments.rb +109 -0
  15. data/lib/bitbucket_rest_api/client/issues/components.rb +103 -0
  16. data/lib/bitbucket_rest_api/client/issues/milestones.rb +103 -0
  17. data/lib/bitbucket_rest_api/client/issues.rb +214 -0
  18. data/lib/bitbucket_rest_api/client/repos/changesets.rb +55 -0
  19. data/lib/bitbucket_rest_api/client/repos/following.rb +40 -0
  20. data/lib/bitbucket_rest_api/client/repos/keys.rb +88 -0
  21. data/lib/bitbucket_rest_api/client/repos/pull_requests/comments.rb +42 -0
  22. data/lib/bitbucket_rest_api/client/repos/pull_requests/commits.rb +24 -0
  23. data/lib/bitbucket_rest_api/client/repos/pull_requests.rb +199 -0
  24. data/lib/bitbucket_rest_api/client/repos/services.rb +104 -0
  25. data/lib/bitbucket_rest_api/client/repos/sources.rb +32 -0
  26. data/lib/bitbucket_rest_api/client/repos.rb +224 -0
  27. data/lib/bitbucket_rest_api/client/user.rb +96 -0
  28. data/lib/bitbucket_rest_api/client/users/account.rb +54 -0
  29. data/lib/bitbucket_rest_api/client/users.rb +14 -0
  30. data/lib/bitbucket_rest_api/client.rb +54 -0
  31. data/lib/bitbucket_rest_api/compatibility.rb +23 -0
  32. data/lib/bitbucket_rest_api/configuration.rb +59 -0
  33. data/lib/bitbucket_rest_api/connection.rb +61 -0
  34. data/lib/bitbucket_rest_api/constants.rb +50 -0
  35. data/lib/bitbucket_rest_api/core_ext/array.rb +17 -0
  36. data/lib/bitbucket_rest_api/core_ext/hash.rb +56 -0
  37. data/lib/bitbucket_rest_api/core_ext/ordered_hash.rb +107 -0
  38. data/lib/bitbucket_rest_api/deprecation.rb +39 -0
  39. data/lib/bitbucket_rest_api/error/bad_request.rb +12 -0
  40. data/lib/bitbucket_rest_api/error/client_error.rb +20 -0
  41. data/lib/bitbucket_rest_api/error/forbidden.rb +12 -0
  42. data/lib/bitbucket_rest_api/error/internal_server_error.rb +12 -0
  43. data/lib/bitbucket_rest_api/error/invalid_options.rb +18 -0
  44. data/lib/bitbucket_rest_api/error/not_found.rb +12 -0
  45. data/lib/bitbucket_rest_api/error/required_params.rb +18 -0
  46. data/lib/bitbucket_rest_api/error/service_error.rb +19 -0
  47. data/lib/bitbucket_rest_api/error/service_unavailable.rb +12 -0
  48. data/lib/bitbucket_rest_api/error/unauthorized.rb +12 -0
  49. data/lib/bitbucket_rest_api/error/unknown_value.rb +18 -0
  50. data/lib/bitbucket_rest_api/error/unprocessable_entity.rb +12 -0
  51. data/lib/bitbucket_rest_api/error/validations.rb +18 -0
  52. data/lib/bitbucket_rest_api/error.rb +35 -0
  53. data/lib/bitbucket_rest_api/ext/faraday.rb +38 -0
  54. data/lib/bitbucket_rest_api/middleware.rb +31 -0
  55. data/lib/bitbucket_rest_api/normalizer.rb +27 -0
  56. data/lib/bitbucket_rest_api/null_encoder.rb +25 -0
  57. data/lib/bitbucket_rest_api/page_iterator.rb +90 -0
  58. data/lib/bitbucket_rest_api/page_links.rb +33 -0
  59. data/lib/bitbucket_rest_api/paged_request.rb +29 -0
  60. data/lib/bitbucket_rest_api/pagination.rb +97 -0
  61. data/lib/bitbucket_rest_api/parameter_filter.rb +32 -0
  62. data/lib/bitbucket_rest_api/params_hash.rb +100 -0
  63. data/lib/bitbucket_rest_api/request/basic_auth.rb +33 -0
  64. data/lib/bitbucket_rest_api/request/jsonize.rb +51 -0
  65. data/lib/bitbucket_rest_api/request/oauth.rb +51 -0
  66. data/lib/bitbucket_rest_api/request/verbs.rb +53 -0
  67. data/lib/bitbucket_rest_api/request.rb +91 -0
  68. data/lib/bitbucket_rest_api/response/header.rb +68 -0
  69. data/lib/bitbucket_rest_api/response/helpers.rb +21 -0
  70. data/lib/bitbucket_rest_api/response/jsonize.rb +30 -0
  71. data/lib/bitbucket_rest_api/response/mashify.rb +24 -0
  72. data/lib/bitbucket_rest_api/response/raise_error.rb +31 -0
  73. data/lib/bitbucket_rest_api/response/xmlize.rb +26 -0
  74. data/lib/bitbucket_rest_api/response.rb +28 -0
  75. data/lib/bitbucket_rest_api/response_wrapper.rb +157 -0
  76. data/lib/bitbucket_rest_api/result.rb +68 -0
  77. data/lib/bitbucket_rest_api/users.rb +20 -0
  78. data/lib/bitbucket_rest_api/utils/url.rb +56 -0
  79. data/lib/bitbucket_rest_api/validations/format.rb +24 -0
  80. data/lib/bitbucket_rest_api/validations/presence.rb +30 -0
  81. data/lib/bitbucket_rest_api/validations/required.rb +24 -0
  82. data/lib/bitbucket_rest_api/validations/token.rb +43 -0
  83. data/lib/bitbucket_rest_api/validations.rb +25 -0
  84. data/lib/bitbucket_rest_api/version.rb +11 -0
  85. data/lib/bitbucket_rest_api.rb +136 -0
  86. metadata +238 -0
@@ -0,0 +1,12 @@
1
+ # encoding: utf-8
2
+
3
+ module BitBucket #:nodoc
4
+ # Raised when BitBucket returns the HTTP status code 401
5
+ module Error
6
+ class Unauthorized < BitBucketError
7
+ def initialize(env)
8
+ super(env)
9
+ end
10
+ end
11
+ end # Error
12
+ end # BitBucket
@@ -0,0 +1,18 @@
1
+ # encoding: utf-8
2
+
3
+ module BitBucket #:nodoc
4
+ # Raised when invalid options are passed to a request body
5
+ module Error
6
+ class UnknownValue < ClientError
7
+ def initialize(key, value, permitted)
8
+ super(
9
+ generate_message(
10
+ :problem => "Wrong value of '#{value}' for the parameter: #{key} provided for this request.",
11
+ :summary => "BitBucket gem checks the request parameters passed to ensure that bitbucket api is not hit unnecessairly and fails fast.",
12
+ :resolution => "Permitted values are: #{permitted}, make sure these are the ones you are using"
13
+ )
14
+ )
15
+ end
16
+ end
17
+ end # Error
18
+ end # BitBucket
@@ -0,0 +1,12 @@
1
+ # encoding: utf-8
2
+
3
+ module BitBucket #:nodoc
4
+ # Raised when BitBucket returns the HTTP status code 422
5
+ module Error
6
+ class UnprocessableEntity < BitBucketError
7
+ def initialize(env)
8
+ super(env)
9
+ end
10
+ end
11
+ end # Error
12
+ end # BitBucket
@@ -0,0 +1,18 @@
1
+ # encoding: utf-8
2
+
3
+ module BitBucket #:nodoc
4
+ # Raised when passed parameters are missing or contain wrong values.
5
+ module Error
6
+ class Validations < ClientError
7
+ def initialize(errors)
8
+ super(
9
+ generate_message(
10
+ :problem => '',
11
+ :summary => '',
12
+ :resolution => ''
13
+ )
14
+ )
15
+ end
16
+ end
17
+ end # Error
18
+ end # BitBucket
@@ -0,0 +1,35 @@
1
+ # encoding: utf-8
2
+
3
+ module BitBucket
4
+ module Error
5
+ class BitBucketError < StandardError
6
+ attr_reader :response_message, :response_headers
7
+
8
+ def initialize(message)
9
+ super message
10
+ @response_message = message
11
+ end
12
+
13
+ # def inspect
14
+ # %(#<#{self.class}>)
15
+ # end
16
+ end
17
+ end # Error
18
+ end # BitBucket
19
+
20
+ %w[
21
+ service_error
22
+ not_found
23
+ forbidden
24
+ bad_request
25
+ unauthorized
26
+ service_unavailable
27
+ internal_server_error
28
+ unprocessable_entity
29
+ client_error
30
+ invalid_options
31
+ required_params
32
+ unknown_value
33
+ ].each do |error|
34
+ require "bitbucket_rest_api/error/#{error}"
35
+ end
@@ -0,0 +1,38 @@
1
+ # encoding: utf-8
2
+
3
+ module Faraday
4
+ module Utils
5
+
6
+ class ParamsHash
7
+ def params_encoder(encoder = nil)
8
+ if encoder
9
+ @encoder = encoder
10
+ else
11
+ @encoder
12
+ end
13
+ end
14
+
15
+ def to_query(encoder = nil)
16
+ Utils.build_nested_query(self, nil, params_encoder)
17
+ end
18
+ end
19
+
20
+ def build_nested_query(value, prefix = nil, encoder = nil)
21
+ case value
22
+ when Array
23
+ value.map { |v| build_nested_query(v, "#{prefix}%5B%5D", encoder) }.join("&")
24
+ when Hash
25
+ value.map { |k, v|
26
+ processed_value = encoder ? encoder.escape(k) : escape(k)
27
+ build_nested_query(v, prefix ? "#{prefix}%5B#{processed_value}%5D" : processed_value, encoder)
28
+ }.join("&")
29
+ when NilClass
30
+ prefix
31
+ else
32
+ raise ArgumentError, "value must be a Hash" if prefix.nil?
33
+ processed_value = encoder ? encoder.escape(value) : escape(value)
34
+ "#{prefix}=#{processed_value}"
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,31 @@
1
+ # encoding: utf-8
2
+
3
+ require 'bitbucket_rest_api/response'
4
+ require 'bitbucket_rest_api/response/mashify'
5
+ require 'bitbucket_rest_api/response/jsonize'
6
+ require 'bitbucket_rest_api/response/raise_error'
7
+ require 'bitbucket_rest_api/response/header'
8
+
9
+ module BitBucket
10
+ class Middleware
11
+ def self.default(options = {})
12
+ api = options[:api]
13
+ proc do |builder|
14
+ builder.use BitBucket::Request::Jsonize
15
+ builder.use Faraday::Request::UrlEncoded
16
+ builder.use Faraday::Request::Multipart
17
+ builder.use BitBucket::Request::OAuth, {:consumer_key => api.client_id, :consumer_secret => api.client_secret, :token => api.oauth_token, :token_secret => api.oauth_secret} if api.client_id? and api.client_secret?
18
+ builder.use BitBucket::Request::BasicAuth, api.authentication if api.basic_authed?
19
+
20
+ builder.use Faraday::Response::Logger if ENV['DEBUG']
21
+ #builder.use BitBucket::Response::Helpers
22
+ unless options[:raw]
23
+ builder.use BitBucket::Response::Mashify
24
+ builder.use BitBucket::Response::Jsonize
25
+ end
26
+ builder.use BitBucket::Response::RaiseError
27
+ builder.adapter options[:adapter]
28
+ end
29
+ end
30
+ end # Middleware
31
+ end # BitBucket
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module BitBucket
4
+ # Deals with normalizing client supplied parameter keys.
5
+ module Normalizer
6
+
7
+ # Turns any keys from nested hashes including nested arrays into strings
8
+ #
9
+ def normalize!(params)
10
+ case params
11
+ when Hash
12
+ params.keys.each do |k|
13
+ params[k.to_s] = params.delete(k)
14
+ normalize!(params[k.to_s])
15
+ end
16
+ when Array
17
+ params.map! do |el|
18
+ normalize!(el)
19
+ end
20
+ else
21
+ params.to_s
22
+ end
23
+ return params
24
+ end
25
+
26
+ end # Normalizer
27
+ end # BitBucket
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ require 'faraday'
4
+
5
+ module BitBucket
6
+
7
+ # Skip encoding of the key nested parameters
8
+ module NullParamsEncoder
9
+ if defined?(Faraday::NestedParamsEncoder)
10
+ class << self
11
+ Faraday::NestedParamsEncoder.singleton_methods do |m|
12
+ define_method m, ::Faraday::NestedParamsEncoder.method(m).to_proc
13
+ end
14
+ end
15
+ end
16
+
17
+ def self.escape(s)
18
+ s.to_s
19
+ end
20
+
21
+ def self.unescape(s)
22
+ s.to_s
23
+ end
24
+ end # NullEncoder
25
+ end # BitBucket
@@ -0,0 +1,90 @@
1
+ # encoding: utf-8
2
+
3
+ require 'bitbucket_rest_api/utils/url'
4
+ require 'uri'
5
+
6
+ module BitBucket
7
+ class PageIterator
8
+ include BitBucket::Constants
9
+ include BitBucket::Utils::Url
10
+ include BitBucket::PagedRequest
11
+
12
+ # Setup attribute accesor for all the link types
13
+ ATTRIBUTES = [ META_FIRST, META_NEXT, META_PREV ]
14
+
15
+ ATTRIBUTES.each do |attr|
16
+ attr_accessor :"#{attr}_page_uri", :"#{attr}_page"
17
+ end
18
+
19
+ attr_reader :current_api
20
+
21
+ def initialize(links, current_api)
22
+ @links = links
23
+ @current_api = current_api
24
+ update_page_links @links
25
+ end
26
+
27
+ def has_next?
28
+ next_page == 0 || !next_page_uri.nil?
29
+ end
30
+
31
+ # Perform http get request for the first resource
32
+ #
33
+ def first
34
+ return nil unless first_page_uri
35
+ perform_request(first_page_uri)
36
+ end
37
+
38
+ # Perform http get request for the next resource
39
+ #
40
+ def next
41
+ return nil unless has_next?
42
+ perform_request(next_page_uri)
43
+ end
44
+
45
+ # Perform http get request for the previous resource
46
+ #
47
+ def prev
48
+ return nil unless prev_page_uri
49
+ perform_request(prev_page_uri)
50
+ end
51
+
52
+ # Returns the result for a specific page.
53
+ #
54
+ def get_page(page_number)
55
+ # Find URI that we can work with, if we cannot get the first
56
+ # page URI then there is only one page.
57
+ return nil unless first_page_uri
58
+ params = parse_query URI(first_page_uri).query
59
+ params['page'] = page_number
60
+
61
+ response = page_request URI(first_page_uri).path, params
62
+ update_page_links response.links
63
+ response
64
+ end
65
+
66
+ private
67
+
68
+ def perform_request(attribute)
69
+ page_uri = URI(attribute)
70
+ params = parse_query(page_uri.query)
71
+
72
+ if next_page and next_page >= 1
73
+ params['page'] = attribute.to_i
74
+ end
75
+
76
+ response = page_request(page_uri.path, params)
77
+ update_page_links response.links
78
+ response
79
+ end
80
+
81
+ # Wholesale update of all link attributes
82
+ def update_page_links(links) # :nodoc:
83
+ ATTRIBUTES.each do |attr|
84
+ self.send(:"#{attr}_page_uri=", links.send(:"#{attr}"))
85
+ self.send(:"#{attr}_page=", links.send(:"#{attr}"))
86
+ end
87
+ end
88
+
89
+ end # PageIterator
90
+ end # BitBucket
@@ -0,0 +1,33 @@
1
+ module BitBucket
2
+ # Determines the links in the current response to be used
3
+ # to find the links to other pages of request responses.
4
+ class PageLinks
5
+ include BitBucket::Constants
6
+
7
+ FIRST_PAGE_NUMBER = 1 # :nodoc:
8
+
9
+ # Hold the extracted values for URI from the response body
10
+ # for the next and previous page.
11
+ attr_accessor :response_dup, :first, :next, :prev
12
+
13
+ # Parses links from executed request
14
+ #
15
+ def initialize(response)
16
+ self.response_dup = response
17
+ if response.body.is_a?(Hash) and !response.body[PARAM_PAGE].nil?
18
+ self.first = path_for_page(FIRST_PAGE_NUMBER)
19
+ self.next = response.body[META_NEXT] unless response.body
20
+ self.prev = response.body[META_PREV]
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def path_for_page(page_number)
27
+ if response_dup.respond_to?(:url)
28
+ self.response_dup.url.to_s.gsub(BitBucket.endpoint, '')
29
+ end
30
+ end
31
+
32
+ end # PageLinks
33
+ end # BitBucket
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+
3
+ module BitBucket
4
+
5
+ # A module that adds http get request to response pagination
6
+ module PagedRequest
7
+ include BitBucket::Constants
8
+ include BitBucket::Normalizer
9
+
10
+ FIRST_PAGE = 1 # Default request page if none provided
11
+
12
+ NOT_FOUND = -1 # Page parameter not present
13
+
14
+ def default_page
15
+ current_api.current_page ? current_api.current_page : FIRST_PAGE
16
+ end
17
+
18
+ # Perform http get request with pagination parameters
19
+ #
20
+ def page_request(path, params={})
21
+ if params[PARAM_PAGE] && params[PARAM_PAGE] == NOT_FOUND
22
+ params[PARAM_PAGE] = default_page
23
+ end
24
+
25
+ current_api.get_request(path, ParamsHash.new(params))
26
+ end
27
+
28
+ end # PagedRequest
29
+ end # BitBucket
@@ -0,0 +1,97 @@
1
+ # encoding: utf-8
2
+ module BitBucket
3
+
4
+ # A module that decorates response with pagination helpers
5
+ module Pagination
6
+ include BitBucket::Constants
7
+
8
+ def paginated?
9
+ body.is_a?(Hash) and !body[PARAM_PAGE].nil?
10
+ end
11
+
12
+ # Return page links
13
+ def links
14
+ @links = BitBucket::PageLinks.new(self.response)
15
+ end
16
+
17
+ # Iterate over results set pages by automatically calling `next_page`
18
+ # until all pages are exhausted. Caution needs to be exercised when
19
+ # using this feature - 100 pages iteration will perform 100 API calls.
20
+ # By default this is off. You can set it on the client, individual API
21
+ # instances or just per given request.
22
+ #
23
+ def auto_paginate(auto=false)
24
+ if paginated? and (current_api.auto_pagination? || auto)
25
+ resources_bodies = []
26
+ each_page do |resource|
27
+ if resource.body.respond_to?(:values) and resource.body[:values]
28
+ resources_bodies += resource.body[:values].collect {|value| ::Hashie::Mash.new(value) }
29
+ else
30
+ resources_bodies += Array(resource.body)
31
+ end
32
+ end
33
+ self.body = resources_bodies
34
+ end
35
+ self
36
+ end
37
+
38
+ # Iterator like each for response pages. If there are no pages to
39
+ # iterate over this method will return current page.
40
+ def each_page
41
+ yield self
42
+ while page_iterator.has_next?
43
+ yield next_page
44
+ end
45
+ end
46
+
47
+ # Retrives the result of the first page. Returns <tt>nil</tt> if there is
48
+ # no first page - either because you are already on the first page
49
+ # or there are no pages at all in the result.
50
+ def first_page
51
+ first_request = page_iterator.first
52
+ self.instance_eval { @env = first_request.env } if first_request
53
+ first_request
54
+ end
55
+
56
+ # Retrives the result of the next page. Returns <tt>nil</tt> if there is
57
+ # no next page or no pages at all.
58
+ def next_page
59
+ next_request = page_iterator.next
60
+ self.instance_eval { @env = next_request.env } if next_request
61
+ next_request
62
+ end
63
+
64
+ # Retrives the result of the previous page. Returns <tt>nil</tt> if there is
65
+ # no previous page or no pages at all.
66
+ def prev_page
67
+ prev_request = page_iterator.prev
68
+ self.instance_eval { @env = prev_request.env } if prev_request
69
+ prev_request
70
+ end
71
+ alias :previous_page :prev_page
72
+
73
+ # Retrives a specific result for a page given page number.
74
+ # The <tt>page_number</tt> parameter is not validate, hitting a page
75
+ # that does not exist will return BitBucket API error. Consequently, if
76
+ # there is only one page, this method returns nil
77
+ def page(page_number)
78
+ request = page_iterator.get_page(page_number)
79
+ self.instance_eval { @env = request.env } if request
80
+ request
81
+ end
82
+
83
+ # Returns <tt>true</tt> if there is another page in the result set,
84
+ # otherwise <tt>false</tt>
85
+ def has_next_page?
86
+ page_iterator.has_next?
87
+ end
88
+
89
+ private
90
+
91
+ # Internally used page iterator
92
+ def page_iterator # :nodoc:
93
+ @page_iterator = BitBucket::PageIterator.new(links, current_api)
94
+ end
95
+
96
+ end # Pagination
97
+ end # BitBucket
@@ -0,0 +1,32 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module BitBucket
4
+ # Allows you to specify parameters keys which will be preserved
5
+ # in parameters hash and its subhashes. Any keys from the nested
6
+ # hash that do not match will be removed.
7
+ module ParameterFilter
8
+
9
+ # Removes any keys from nested hashes that don't match predefiend keys
10
+ #
11
+ def filter!(keys, params, options={:recursive => true}) # :nodoc:
12
+ case params
13
+ when Hash, ParamsHash
14
+ params.keys.each do |k, v|
15
+ unless (keys.include?(k) or BitBucket::Validations::VALID_API_KEYS.include?(k))
16
+ params.delete(k)
17
+ else
18
+ filter!(keys, params[k]) if options[:recursive]
19
+ end
20
+ end
21
+ when Array
22
+ params.map! do |el|
23
+ filter!(keys, el) if options[:recursive]
24
+ end
25
+ else
26
+ params
27
+ end
28
+ return params
29
+ end
30
+
31
+ end # Filter
32
+ end # BitBucket
@@ -0,0 +1,100 @@
1
+ # encoding: utf-8
2
+
3
+ require 'delegate'
4
+ require 'base64'
5
+
6
+ module BitBucket
7
+
8
+ # Class responsible for holding request parameters
9
+ class ParamsHash < DelegateClass(Hash)
10
+ include Normalizer
11
+
12
+ def initialize(hash)
13
+ super(normalize!(Hash[hash]))
14
+ end
15
+
16
+ # Create empty hash
17
+ #
18
+ def self.empty
19
+ new({})
20
+ end
21
+
22
+ # Extract and parse media type param
23
+ #
24
+ # [.version].param[+json]
25
+ #
26
+ def media
27
+ parse(delete('media'))
28
+ end
29
+
30
+ # Return accept header if present
31
+ #
32
+ def accept
33
+ if has_key?('accept')
34
+ delete('accept')
35
+ elsif has_key?('media')
36
+ media
37
+ else
38
+ nil
39
+ end
40
+ end
41
+
42
+ # Extract request data from parameters
43
+ #
44
+ def data
45
+ if has_key?('data') && !self['data'].nil?
46
+ return delete('data')
47
+ else
48
+ return to_hash
49
+ end
50
+ end
51
+
52
+ def encoder
53
+ if has_key?('encoder') && self['encoder']
54
+ return delete('encoder')
55
+ else
56
+ return {}
57
+ end
58
+ end
59
+
60
+ # Any client configuration options
61
+ #
62
+ def options
63
+ opts = has_key?('options') ? delete('options') : {}
64
+ headers = opts.fetch(:headers) { {} }
65
+ if value = accept
66
+ headers[:accept] = value
67
+ end
68
+ if value = delete('content_type')
69
+ headers[:content_type] = value
70
+ end
71
+ opts[:raw] = has_key?('raw') ? delete('raw') : false
72
+ opts[:headers] = headers unless headers.empty?
73
+ opts
74
+ end
75
+
76
+ # Update hash with default parameters for non existing keys
77
+ #
78
+ def merge_default(defaults)
79
+ if defaults && !defaults.empty?
80
+ defaults.each do |key, value|
81
+ self[key] = value unless self.has_key?(key)
82
+ end
83
+ end
84
+ self
85
+ end
86
+
87
+ # Base64 encode string removing newline characters
88
+ #
89
+ def strict_encode64(key)
90
+ value = self[key]
91
+ encoded = if Base64.respond_to?(:strict_encode64)
92
+ Base64.strict_encode64(value)
93
+ else
94
+ [value].pack("m0")
95
+ end
96
+ self[key] = encoded.delete("\n\r")
97
+ end
98
+
99
+ end # ParamsHash
100
+ end # BitBucket
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+
3
+ require 'faraday'
4
+ require 'base64'
5
+
6
+ module BitBucket
7
+ class Request
8
+ class BasicAuth < Faraday::Middleware
9
+ dependency 'base64'
10
+
11
+ def call(env)
12
+ unless @auth.to_s.empty?
13
+ env[:request_headers].merge!('Authorization' => "Basic #{@auth}\"")
14
+ end
15
+
16
+ @app.call env
17
+ end
18
+
19
+ def initialize(app, *args)
20
+ @app = app
21
+ credentials = ""
22
+ options = args.extract_options!
23
+ if options.has_key? :login
24
+ credentials = "#{options[:login]}:#{options[:password]}"
25
+ elsif options.has_key? :basic_auth
26
+ credentials = "#{options[:basic_auth]}"
27
+ end
28
+ @auth = Base64.encode64(credentials)
29
+ @auth.gsub!("\n", "")
30
+ end
31
+ end # BasicAuth
32
+ end # Request
33
+ end # BitBucket
@@ -0,0 +1,51 @@
1
+ # encoding: utf-8
2
+
3
+ require 'faraday'
4
+
5
+ module BitBucket
6
+ class Request::Jsonize < Faraday::Middleware
7
+
8
+ CONTENT_TYPE = 'Content-Type'.freeze
9
+ MIME_TYPE = 'application/json'.freeze
10
+
11
+ dependency 'multi_json'
12
+
13
+ def call(env)
14
+ if request_with_body?(env)
15
+ env[:request_headers][CONTENT_TYPE] ||= MIME_TYPE
16
+ env[:body] = encode_body env unless env[:body].respond_to?(:to_str)
17
+ else
18
+ # Ensure valid body for put and post requests
19
+ if [:put, :patch, :post].include? env[:method]
20
+ env[:body] = encode_body({})
21
+ end
22
+ end
23
+ @app.call env
24
+ end
25
+
26
+ def encode_body(env)
27
+ if MultiJson.respond_to?(:dump)
28
+ MultiJson.dump env[:body]
29
+ else
30
+ MultiJson.encode env[:body]
31
+ end
32
+ end
33
+
34
+ def request_with_body?(env)
35
+ type = request_type(env)
36
+ has_body?(env) and (type.empty? or type == MIME_TYPE)
37
+ end
38
+
39
+ # Don't encode bodies in string form
40
+ def has_body?(env)
41
+ body = env[:body] and !(body.respond_to?(:to_str) and body.empty?)
42
+ end
43
+
44
+ def request_type(env)
45
+ type = env[:request_headers][CONTENT_TYPE].to_s
46
+ type = type.split(';', 2).first if type.index(';')
47
+ type
48
+ end
49
+
50
+ end # Request::Jsonize
51
+ end # BitBucket