reenhanced_bitbucket_api 0.1.6
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.
- checksums.yaml +7 -0
- data/LICENSE.txt +43 -0
- data/README.md +169 -0
- data/Rakefile +3 -0
- data/lib/bitbucket_rest_api/api/actions.rb +50 -0
- data/lib/bitbucket_rest_api/api.rb +120 -0
- data/lib/bitbucket_rest_api/api_factory.rb +30 -0
- data/lib/bitbucket_rest_api/authorization.rb +34 -0
- data/lib/bitbucket_rest_api/client.rb +58 -0
- data/lib/bitbucket_rest_api/compatibility.rb +23 -0
- data/lib/bitbucket_rest_api/configuration.rb +101 -0
- data/lib/bitbucket_rest_api/connection.rb +96 -0
- data/lib/bitbucket_rest_api/constants.rb +58 -0
- data/lib/bitbucket_rest_api/core_ext/array.rb +17 -0
- data/lib/bitbucket_rest_api/core_ext/hash.rb +56 -0
- data/lib/bitbucket_rest_api/core_ext/ordered_hash.rb +107 -0
- data/lib/bitbucket_rest_api/deprecation.rb +39 -0
- data/lib/bitbucket_rest_api/error/bad_request.rb +12 -0
- data/lib/bitbucket_rest_api/error/client_error.rb +20 -0
- data/lib/bitbucket_rest_api/error/forbidden.rb +12 -0
- data/lib/bitbucket_rest_api/error/internal_server_error.rb +12 -0
- data/lib/bitbucket_rest_api/error/invalid_options.rb +18 -0
- data/lib/bitbucket_rest_api/error/not_found.rb +12 -0
- data/lib/bitbucket_rest_api/error/required_params.rb +18 -0
- data/lib/bitbucket_rest_api/error/service_error.rb +19 -0
- data/lib/bitbucket_rest_api/error/service_unavailable.rb +12 -0
- data/lib/bitbucket_rest_api/error/unauthorized.rb +12 -0
- data/lib/bitbucket_rest_api/error/unknown_value.rb +18 -0
- data/lib/bitbucket_rest_api/error/unprocessable_entity.rb +12 -0
- data/lib/bitbucket_rest_api/error/validations.rb +18 -0
- data/lib/bitbucket_rest_api/error.rb +35 -0
- data/lib/bitbucket_rest_api/invitations.rb +15 -0
- data/lib/bitbucket_rest_api/issues/comments.rb +118 -0
- data/lib/bitbucket_rest_api/issues/components.rb +106 -0
- data/lib/bitbucket_rest_api/issues/milestones.rb +107 -0
- data/lib/bitbucket_rest_api/issues.rb +230 -0
- data/lib/bitbucket_rest_api/normalizer.rb +27 -0
- data/lib/bitbucket_rest_api/parameter_filter.rb +32 -0
- data/lib/bitbucket_rest_api/repos/changesets.rb +54 -0
- data/lib/bitbucket_rest_api/repos/following.rb +39 -0
- data/lib/bitbucket_rest_api/repos/keys.rb +87 -0
- data/lib/bitbucket_rest_api/repos/services.rb +103 -0
- data/lib/bitbucket_rest_api/repos/sources.rb +31 -0
- data/lib/bitbucket_rest_api/repos.rb +238 -0
- data/lib/bitbucket_rest_api/request/basic_auth.rb +31 -0
- data/lib/bitbucket_rest_api/request/jsonize.rb +46 -0
- data/lib/bitbucket_rest_api/request/oauth.rb +51 -0
- data/lib/bitbucket_rest_api/request.rb +67 -0
- data/lib/bitbucket_rest_api/response/helpers.rb +21 -0
- data/lib/bitbucket_rest_api/response/jsonize.rb +30 -0
- data/lib/bitbucket_rest_api/response/mashify.rb +24 -0
- data/lib/bitbucket_rest_api/response/raise_error.rb +31 -0
- data/lib/bitbucket_rest_api/response/xmlize.rb +26 -0
- data/lib/bitbucket_rest_api/response.rb +28 -0
- data/lib/bitbucket_rest_api/result.rb +140 -0
- data/lib/bitbucket_rest_api/user.rb +101 -0
- data/lib/bitbucket_rest_api/users/account.rb +53 -0
- data/lib/bitbucket_rest_api/users.rb +24 -0
- data/lib/bitbucket_rest_api/utils/url.rb +56 -0
- data/lib/bitbucket_rest_api/validations/format.rb +24 -0
- data/lib/bitbucket_rest_api/validations/presence.rb +25 -0
- data/lib/bitbucket_rest_api/validations/required.rb +24 -0
- data/lib/bitbucket_rest_api/validations/token.rb +43 -0
- data/lib/bitbucket_rest_api/validations.rb +25 -0
- data/lib/bitbucket_rest_api/version.rb +11 -0
- data/lib/bitbucket_rest_api.rb +91 -0
- metadata +338 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'faraday'
|
4
|
+
|
5
|
+
module BitBucket
|
6
|
+
class Response::Helpers < Response
|
7
|
+
|
8
|
+
def on_complete(env)
|
9
|
+
env[:body].class.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
|
10
|
+
include BitBucket::Result
|
11
|
+
|
12
|
+
def env
|
13
|
+
@env
|
14
|
+
end
|
15
|
+
|
16
|
+
RUBY_EVAL
|
17
|
+
env[:body].instance_eval { @env = env }
|
18
|
+
end
|
19
|
+
|
20
|
+
end # Response::Helpers
|
21
|
+
end # BitBucket
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'faraday'
|
4
|
+
|
5
|
+
module BitBucket
|
6
|
+
class Response::Jsonize < Response
|
7
|
+
dependency 'multi_json'
|
8
|
+
|
9
|
+
define_parser do |body|
|
10
|
+
if MultiJson.respond_to?(:load)
|
11
|
+
MultiJson.load body
|
12
|
+
else
|
13
|
+
MultiJson.decode body
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def parse(body)
|
18
|
+
case body
|
19
|
+
when ''
|
20
|
+
nil
|
21
|
+
when 'true'
|
22
|
+
true
|
23
|
+
when 'false'
|
24
|
+
false
|
25
|
+
else
|
26
|
+
self.class.parser.call body
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end # Response::Jsonize
|
30
|
+
end # BitBucket
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'faraday'
|
4
|
+
|
5
|
+
module BitBucket
|
6
|
+
class Response::Mashify < Response
|
7
|
+
dependency 'hashie/mash'
|
8
|
+
|
9
|
+
define_parser do |body|
|
10
|
+
::Hashie::Mash.new body
|
11
|
+
end
|
12
|
+
|
13
|
+
def parse(body)
|
14
|
+
case body
|
15
|
+
when Hash
|
16
|
+
self.class.parser.call body
|
17
|
+
when Array
|
18
|
+
body.map { |item| item.is_a?(Hash) ? self.class.parser.call(item) : item }
|
19
|
+
else
|
20
|
+
body
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end # Response::Mashify
|
24
|
+
end # BitBucket
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'faraday'
|
4
|
+
require 'bitbucket_rest_api/error'
|
5
|
+
|
6
|
+
module BitBucket
|
7
|
+
class Response::RaiseError < Faraday::Response::Middleware
|
8
|
+
|
9
|
+
def on_complete(env)
|
10
|
+
case env[:status].to_i
|
11
|
+
when 400
|
12
|
+
raise BitBucket::Error::BadRequest.new(env)
|
13
|
+
when 401
|
14
|
+
raise BitBucket::Error::Unauthorized.new(env)
|
15
|
+
when 403
|
16
|
+
raise BitBucket::Error::Forbidden.new(env)
|
17
|
+
when 404
|
18
|
+
raise BitBucket::Error::NotFound.new(env)
|
19
|
+
when 422
|
20
|
+
raise BitBucket::Error::UnprocessableEntity.new(env)
|
21
|
+
when 500
|
22
|
+
raise BitBucket::Error::InternalServerError.new(env)
|
23
|
+
when 503
|
24
|
+
raise BitBucket::Error::ServiceUnavailable.new(env)
|
25
|
+
when 400...600
|
26
|
+
raise BitBucket::Error::ServiceError.new(env)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end # Response::RaiseError
|
31
|
+
end # BitBucket
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'faraday'
|
4
|
+
|
5
|
+
module BitBucket
|
6
|
+
class Response::Xmlize < Response
|
7
|
+
dependency 'nokogiri'
|
8
|
+
|
9
|
+
define_parser do |body|
|
10
|
+
::Nokogiri::XML body
|
11
|
+
end
|
12
|
+
|
13
|
+
def parse(body)
|
14
|
+
case body
|
15
|
+
when ''
|
16
|
+
nil
|
17
|
+
when 'true'
|
18
|
+
true
|
19
|
+
when 'false'
|
20
|
+
false
|
21
|
+
else
|
22
|
+
self.class.parser.call body
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end # Response::Xmlize
|
26
|
+
end # BitBucket
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'faraday'
|
4
|
+
|
5
|
+
module BitBucket
|
6
|
+
# Contains methods and attributes that act on the response returned from the
|
7
|
+
# request
|
8
|
+
class Response < Faraday::Response::Middleware
|
9
|
+
CONTENT_TYPE = 'Content-Type'.freeze
|
10
|
+
|
11
|
+
class << self
|
12
|
+
attr_accessor :parser
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.define_parser(&block)
|
16
|
+
@parser = block
|
17
|
+
end
|
18
|
+
|
19
|
+
def response_type(env)
|
20
|
+
env[:response_headers][CONTENT_TYPE].to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
def parse_response?(env)
|
24
|
+
env[:body].respond_to? :to_str
|
25
|
+
end
|
26
|
+
|
27
|
+
end # Response
|
28
|
+
end # BitBucket
|
@@ -0,0 +1,140 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module BitBucket
|
4
|
+
module Result
|
5
|
+
include BitBucket::Constants
|
6
|
+
|
7
|
+
# TODO Add result counts method to check total items looking at result links
|
8
|
+
|
9
|
+
def ratelimit_limit
|
10
|
+
loaded? ? @env[:response_headers][RATELIMIT_LIMIT] : nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def ratelimit_remaining
|
14
|
+
loaded? ? @env[:response_headers][RATELIMIT_REMAINING] : nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def cache_control
|
18
|
+
loaded? ? @env[:response_headers][CACHE_CONTROL] : nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def content_type
|
22
|
+
loaded? ? @env[:response_headers][CONTENT_TYPE] : nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def content_length
|
26
|
+
loaded? ? @env[:response_headers][CONTENT_LENGTH] : nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def etag
|
30
|
+
loaded? ? @env[:response_headers][ETAG] : nil
|
31
|
+
end
|
32
|
+
|
33
|
+
def date
|
34
|
+
loaded? ? @env[:response_headers][DATE] : nil
|
35
|
+
end
|
36
|
+
|
37
|
+
def location
|
38
|
+
loaded? ? @env[:response_headers][LOCATION] : nil
|
39
|
+
end
|
40
|
+
|
41
|
+
def server
|
42
|
+
loaded? ? @env[:response_headers][SERVER] : nil
|
43
|
+
end
|
44
|
+
|
45
|
+
def status
|
46
|
+
loaded? ? @env[:status] : nil
|
47
|
+
end
|
48
|
+
|
49
|
+
def success?
|
50
|
+
(200..299).include? status
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns raw body
|
54
|
+
def body
|
55
|
+
loaded? ? @env[:body] : nil
|
56
|
+
end
|
57
|
+
|
58
|
+
def loaded?
|
59
|
+
!!@env
|
60
|
+
end
|
61
|
+
|
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
|
+
end # Result
|
140
|
+
end # BitBucket
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module BitBucket
|
4
|
+
class User < API
|
5
|
+
|
6
|
+
|
7
|
+
DEFAULT_USER_OPTIONS = {
|
8
|
+
"first_name" => "",
|
9
|
+
"last_name" => "",
|
10
|
+
"avatar" => ""
|
11
|
+
# TODO: can this filed be modified?
|
12
|
+
# "resource_uri" => ""
|
13
|
+
}.freeze
|
14
|
+
|
15
|
+
# Creates new User API
|
16
|
+
def initialize(options = { })
|
17
|
+
super(options)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Gets the basic information associated with an account and
|
21
|
+
# a list of all of the repositories owned by the user.
|
22
|
+
# See https://confluence.atlassian.com/display/BITBUCKET/user+Endpoint#userEndpoint-GETauserprofile
|
23
|
+
#
|
24
|
+
# = Examples
|
25
|
+
# bitbucket = BitBucket.new
|
26
|
+
# bitbucket.user_api.profile
|
27
|
+
#
|
28
|
+
def profile
|
29
|
+
get_request("/user")
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
# Update a user
|
34
|
+
|
35
|
+
# = Parameters
|
36
|
+
# * <tt>:first_name</tt> Optional string
|
37
|
+
# * <tt>:last_name</tt> Optional string
|
38
|
+
# * <tt>:avatar</tt> Optional string
|
39
|
+
# * <tt>:resource_uri</tt> Optional string
|
40
|
+
#
|
41
|
+
# = Examples
|
42
|
+
#
|
43
|
+
# bitbucket = BitBucket.new
|
44
|
+
# bitbucket.user_api.update :first_name => 'first-name', :last_name => 'last-name'
|
45
|
+
#
|
46
|
+
|
47
|
+
def update( params={ })
|
48
|
+
normalize! params
|
49
|
+
filter! DEFAULT_USER_OPTIONS, params
|
50
|
+
|
51
|
+
put_request("/user", DEFAULT_USER_OPTIONS.merge(params))
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
# GET a list of user privileges
|
57
|
+
def privileges
|
58
|
+
get_request("/user/privileges")
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
|
63
|
+
# GET a list of repositories an account follows
|
64
|
+
# Gets the details of the repositories that the individual or team account follows.
|
65
|
+
# This call returns the full data about the repositories including
|
66
|
+
# if the repository is a fork of another repository.
|
67
|
+
# An account always "follows" its own repositories.
|
68
|
+
def follows
|
69
|
+
get_request("/user/follows")
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
# GET a list of repositories visible to an account
|
74
|
+
# Gets the details of the repositories that the user owns
|
75
|
+
# or has at least read access to.
|
76
|
+
# Use this if you're looking for a full list of all of the repositories associated with a user.
|
77
|
+
def repositories
|
78
|
+
get_request("/user/repositories")
|
79
|
+
end
|
80
|
+
|
81
|
+
alias :repos :repositories
|
82
|
+
|
83
|
+
|
84
|
+
|
85
|
+
# GET a list of repositories the account is following
|
86
|
+
# Gets a list of the repositories the account follows.
|
87
|
+
# This is the same list that appears on the Following tab on your account dashboard.
|
88
|
+
def overview
|
89
|
+
get_request("/user/repositories/overview")
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
|
94
|
+
# GET the list of repositories on the dashboard
|
95
|
+
# Gets the repositories list from the account's dashboard.
|
96
|
+
def dashboard
|
97
|
+
get_request("/user/repositories/dashboard")
|
98
|
+
end
|
99
|
+
|
100
|
+
end # User
|
101
|
+
end # BitBucket
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module BitBucket
|
4
|
+
class Users::Account < API
|
5
|
+
|
6
|
+
# API about users/account , please refer to
|
7
|
+
# https://confluence.atlassian.com/display/BITBUCKET/account+Resource
|
8
|
+
#
|
9
|
+
|
10
|
+
|
11
|
+
# GET the account profile
|
12
|
+
#
|
13
|
+
def profile(accountname)
|
14
|
+
response = get_request("/users/#{accountname}")
|
15
|
+
end
|
16
|
+
|
17
|
+
# GET the account plan
|
18
|
+
def plan(accountname)
|
19
|
+
response = get_request("/users/#{accountname}/plan")
|
20
|
+
end
|
21
|
+
|
22
|
+
# GET the emails
|
23
|
+
def emails(accountname)
|
24
|
+
response = get_request("/users/#{accountname}/emails")
|
25
|
+
end
|
26
|
+
|
27
|
+
# GET the followers
|
28
|
+
def followers(accountname)
|
29
|
+
response = get_request("/users/#{accountname}/followers")
|
30
|
+
end
|
31
|
+
|
32
|
+
# GET the events
|
33
|
+
def events(accountname)
|
34
|
+
response = get_request("/users/#{accountname}/events")
|
35
|
+
end
|
36
|
+
|
37
|
+
#GET the keys
|
38
|
+
def keys(accountname)
|
39
|
+
response = get_request("/users/#{accountname}/ssh-keys")
|
40
|
+
end
|
41
|
+
|
42
|
+
#POST a new key
|
43
|
+
# params should be in format {key: "", label:""}
|
44
|
+
def new_key(accountname, params)
|
45
|
+
response = post_request("/users/#{accountname}/ssh-keys/", params)
|
46
|
+
end
|
47
|
+
|
48
|
+
#DELETE a key
|
49
|
+
def delete_key(accountname, key_id)
|
50
|
+
response = delete_request("/users/#{accountname}/ssh-keys/#{key_id}")
|
51
|
+
end
|
52
|
+
end # Users::Account
|
53
|
+
end # BitBucket
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module BitBucket
|
4
|
+
class Users < API
|
5
|
+
extend AutoloadHelper
|
6
|
+
|
7
|
+
# Load all the modules after initializing Repos to avoid superclass mismatch
|
8
|
+
autoload_all 'bitbucket_rest_api/users',
|
9
|
+
:Account => 'account'
|
10
|
+
|
11
|
+
|
12
|
+
# Creates new Users API
|
13
|
+
def initialize(options = { })
|
14
|
+
super(options)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Access to Users::Account API
|
18
|
+
def account
|
19
|
+
@account ||= ApiFactory.new 'Users::Account'
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
end # Users
|
24
|
+
end # BitBucket
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
3
|
+
module BitBucket
|
4
|
+
module Utils
|
5
|
+
module Url
|
6
|
+
extend self
|
7
|
+
|
8
|
+
DEFAULT_QUERY_SEP = /[&;] */n
|
9
|
+
|
10
|
+
KEY_VALUE_SEP = '='.freeze
|
11
|
+
|
12
|
+
def escape(s) CGI.escape s.to_s end
|
13
|
+
|
14
|
+
def unescape(s) CGI.unescape s.to_s end
|
15
|
+
|
16
|
+
def build_query(params)
|
17
|
+
params.map { |k, v|
|
18
|
+
if v.class == Array
|
19
|
+
build_query(v.map { |x| [k, x] })
|
20
|
+
else
|
21
|
+
v.nil? ? escape(k) : "#{escape(k)}=#{escape(v)}"
|
22
|
+
end
|
23
|
+
}.join("&")
|
24
|
+
end
|
25
|
+
|
26
|
+
def parse_query(query_string)
|
27
|
+
return '' if query_string.nil? || query_string.empty?
|
28
|
+
params = {}
|
29
|
+
|
30
|
+
query_string.split(DEFAULT_QUERY_SEP).each do |part|
|
31
|
+
k, v = part.split(KEY_VALUE_SEP, 2).map { |el| unescape(el) }
|
32
|
+
|
33
|
+
if cur = params[k]
|
34
|
+
if cur.class == Array
|
35
|
+
params[k] << v
|
36
|
+
else
|
37
|
+
params[k] = [cur, v]
|
38
|
+
end
|
39
|
+
else
|
40
|
+
params[k] = v
|
41
|
+
end
|
42
|
+
end
|
43
|
+
params
|
44
|
+
end
|
45
|
+
|
46
|
+
def parse_query_for_param(query_string, name)
|
47
|
+
parse_query(query_string).each do |key, val|
|
48
|
+
return val.first if (name == key) && val.is_a?(Array)
|
49
|
+
return val if (name == key)
|
50
|
+
end
|
51
|
+
return nil
|
52
|
+
end
|
53
|
+
|
54
|
+
end # Url
|
55
|
+
end # Utils
|
56
|
+
end # BitBucket
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module BitBucket
|
4
|
+
module Validations
|
5
|
+
module Format
|
6
|
+
|
7
|
+
# Ensures that value for a given key is of the correct form whether
|
8
|
+
# matching regular expression or set of predefined values.
|
9
|
+
#
|
10
|
+
def assert_valid_values(permitted, params)
|
11
|
+
params.each do |k, v|
|
12
|
+
next unless permitted.keys.include?(k)
|
13
|
+
if permitted[k].is_a?(Array) && !permitted[k].include?(params[k])
|
14
|
+
raise BitBucket::Error::UnknownValue.new(k,v, permitted[k].join(', '))
|
15
|
+
|
16
|
+
elsif permitted[k].is_a?(Regexp) && !(permitted[k] =~ params[k])
|
17
|
+
raise BitBucket::Error::UnknownValue.new(k,v, permitted[k])
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end # Format
|
23
|
+
end # Validations
|
24
|
+
end # BitBucket
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module BitBucket
|
4
|
+
module Validations
|
5
|
+
module Presence
|
6
|
+
|
7
|
+
# Ensures that essential arguments are present before request is made
|
8
|
+
#
|
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
|
14
|
+
|
15
|
+
|
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?
|
21
|
+
end
|
22
|
+
|
23
|
+
end # Presence
|
24
|
+
end # Validations
|
25
|
+
end # BitBucket
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module BitBucket
|
4
|
+
module Validations
|
5
|
+
module Required
|
6
|
+
|
7
|
+
# Validate all keys present in a provided hash against required set,
|
8
|
+
# on mismatch raise BitBucket::Error::RequiredParams
|
9
|
+
# Note that keys need to be in the same format i.e. symbols or strings,
|
10
|
+
# otherwise the comparison will fail.
|
11
|
+
#
|
12
|
+
def assert_required_keys(required, provided)
|
13
|
+
result = required.all? do |key|
|
14
|
+
provided.has_deep_key? key
|
15
|
+
end
|
16
|
+
if !result
|
17
|
+
raise BitBucket::Error::RequiredParams.new(provided, required)
|
18
|
+
end
|
19
|
+
result
|
20
|
+
end
|
21
|
+
|
22
|
+
end # Required
|
23
|
+
end # Validations
|
24
|
+
end # BitBucket
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# TODO: Set token required calls
|
4
|
+
|
5
|
+
module BitBucket
|
6
|
+
module Validations
|
7
|
+
module Token
|
8
|
+
|
9
|
+
TOKEN_REQUIRED = [
|
10
|
+
'get /user',
|
11
|
+
'get /user/emails',
|
12
|
+
'get /user/followers',
|
13
|
+
'get /user/following',
|
14
|
+
'get /user/keys',
|
15
|
+
'get /user/repos',
|
16
|
+
'patch /user',
|
17
|
+
'post /user/emails',
|
18
|
+
'post /user/keys',
|
19
|
+
'post /user/repos'
|
20
|
+
]
|
21
|
+
|
22
|
+
TOKEN_REQUIRED_REGEXP = [
|
23
|
+
/repos\/.*\/.*\/comments/,
|
24
|
+
]
|
25
|
+
|
26
|
+
# Ensures that required authentication token is present before
|
27
|
+
# request is sent.
|
28
|
+
#
|
29
|
+
def validates_token_for(method, path)
|
30
|
+
return true unless TOKEN_REQUIRED.grep("#{method} #{path}").empty?
|
31
|
+
|
32
|
+
token_required = false
|
33
|
+
TOKEN_REQUIRED_REGEXP.each do |regex|
|
34
|
+
if "#{method} #{path}" =~ regex
|
35
|
+
token_required = true
|
36
|
+
end
|
37
|
+
end
|
38
|
+
return token_required
|
39
|
+
end
|
40
|
+
|
41
|
+
end # Token
|
42
|
+
end # Validations
|
43
|
+
end # BitBucket
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module BitBucket
|
4
|
+
module Validations
|
5
|
+
extend AutoloadHelper
|
6
|
+
|
7
|
+
autoload_all 'bitbucket_rest_api/validations',
|
8
|
+
:Presence => 'presence',
|
9
|
+
:Token => 'token',
|
10
|
+
:Format => 'format',
|
11
|
+
:Required => 'required'
|
12
|
+
|
13
|
+
include Presence
|
14
|
+
include Format
|
15
|
+
include Token
|
16
|
+
include Required
|
17
|
+
|
18
|
+
VALID_API_KEYS = [
|
19
|
+
'page',
|
20
|
+
'per_page',
|
21
|
+
'jsonp_callback'
|
22
|
+
]
|
23
|
+
|
24
|
+
end # Validation
|
25
|
+
end # BitBucket
|