tinybucket 0.1.7 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.rubocop.yml +2 -1
  4. data/Gemfile +4 -4
  5. data/README.md +48 -20
  6. data/Rakefile +7 -0
  7. data/lib/tinybucket.rb +7 -4
  8. data/lib/tinybucket/api/base_api.rb +2 -19
  9. data/lib/tinybucket/api/branch_restrictions_api.rb +35 -11
  10. data/lib/tinybucket/api/comments_api.rb +38 -4
  11. data/lib/tinybucket/api/commits_api.rb +60 -10
  12. data/lib/tinybucket/api/diff_api.rb +22 -0
  13. data/lib/tinybucket/api/helper/api_helper.rb +0 -11
  14. data/lib/tinybucket/api/helper/commits_helper.rb +7 -0
  15. data/lib/tinybucket/api/pull_requests_api.rb +79 -22
  16. data/lib/tinybucket/api/repo_api.rb +37 -17
  17. data/lib/tinybucket/api/repos_api.rb +13 -6
  18. data/lib/tinybucket/api/team_api.rb +54 -29
  19. data/lib/tinybucket/api/user_api.rb +43 -23
  20. data/lib/tinybucket/api_factory.rb +2 -4
  21. data/lib/tinybucket/client.rb +39 -20
  22. data/lib/tinybucket/config.rb +1 -1
  23. data/lib/tinybucket/connection.rb +3 -3
  24. data/lib/tinybucket/enumerator.rb +44 -0
  25. data/lib/tinybucket/error.rb +2 -0
  26. data/lib/tinybucket/error/conflict.rb +6 -0
  27. data/lib/tinybucket/error/not_found.rb +6 -0
  28. data/lib/tinybucket/error/service_error.rb +8 -4
  29. data/lib/tinybucket/iterator.rb +77 -0
  30. data/lib/tinybucket/model/base.rb +6 -6
  31. data/lib/tinybucket/model/branch_restriction.rb +27 -0
  32. data/lib/tinybucket/model/comment.rb +32 -6
  33. data/lib/tinybucket/model/commit.rb +63 -9
  34. data/lib/tinybucket/model/concerns.rb +1 -0
  35. data/lib/tinybucket/model/concerns/enumerable.rb +18 -0
  36. data/lib/tinybucket/model/error_response.rb +16 -1
  37. data/lib/tinybucket/model/page.rb +25 -49
  38. data/lib/tinybucket/model/profile.rb +56 -8
  39. data/lib/tinybucket/model/pull_request.rb +114 -18
  40. data/lib/tinybucket/model/repository.rb +177 -36
  41. data/lib/tinybucket/model/team.rb +70 -10
  42. data/lib/tinybucket/request.rb +2 -0
  43. data/lib/tinybucket/response.rb +1 -1
  44. data/lib/tinybucket/response/handler.rb +21 -0
  45. data/lib/tinybucket/version.rb +1 -1
  46. data/spec/fixtures/repositories/test_owner/test_repo/commit/1/approve/post.json +16 -0
  47. data/spec/lib/tinybucket/api/branch_restrictions_api_spec.rb +1 -2
  48. data/spec/lib/tinybucket/api/comments_api_spec.rb +1 -2
  49. data/spec/lib/tinybucket/api/commits_api_spec.rb +92 -3
  50. data/spec/lib/tinybucket/api/pull_requests_api_spec.rb +34 -4
  51. data/spec/lib/tinybucket/api/repo_api_spec.rb +1 -2
  52. data/spec/lib/tinybucket/api/repos_api_spec.rb +1 -2
  53. data/spec/lib/tinybucket/api/team_api_spec.rb +1 -6
  54. data/spec/lib/tinybucket/api/user_api_spec.rb +15 -2
  55. data/spec/lib/tinybucket/api_factory_spec.rb +2 -7
  56. data/spec/lib/tinybucket/client_spec.rb +10 -25
  57. data/spec/lib/tinybucket/error/service_error_spec.rb +23 -0
  58. data/spec/lib/tinybucket/model/commit_spec.rb +27 -4
  59. data/spec/lib/tinybucket/model/page_spec.rb +0 -30
  60. data/spec/lib/tinybucket/model/profile_spec.rb +3 -3
  61. data/spec/lib/tinybucket/model/pull_request_spec.rb +11 -5
  62. data/spec/lib/tinybucket/model/repository_spec.rb +5 -5
  63. data/spec/lib/tinybucket/model/team_spec.rb +4 -4
  64. data/spec/lib/tinybucket_spec.rb +10 -27
  65. data/spec/spec_helper.rb +3 -2
  66. data/spec/support/api_response_macros.rb +2 -2
  67. metadata +12 -3
  68. data/lib/tinybucket/response/error_handler.rb +0 -14
@@ -1,9 +1,7 @@
1
1
  module Tinybucket
2
2
  class ApiFactory
3
3
  class << self
4
- def create_instance(klass_name, config, options)
5
- options.symbolize_keys!
6
-
4
+ def create_instance(klass_name)
7
5
  klass =
8
6
  begin
9
7
  name = "#{klass_name}Api".intern
@@ -14,7 +12,7 @@ module Tinybucket
14
12
  raise ArgumentError, 'must provide klass to be instantiated'
15
13
  end
16
14
 
17
- klass.new config, options
15
+ klass.new
18
16
  end
19
17
  end
20
18
  end
@@ -1,14 +1,6 @@
1
1
  module Tinybucket
2
2
  class Client
3
- include ActiveSupport::Configurable
4
-
5
- def initialize(options = {})
6
- options.each_pair do |key, value|
7
- config.send("#{key}=", value)
8
- end
9
-
10
- yield(config) if block_given?
11
- end
3
+ include ::Tinybucket::Model::Concerns::Enumerable
12
4
 
13
5
  # Get Repositories
14
6
  #
@@ -25,7 +17,8 @@ module Tinybucket
25
17
  # @overload repos(options)
26
18
  # get public repositories.
27
19
  # @option options [Hash] a hash with options
28
- # @return Tinybucket::Model::Page model instance.
20
+ # @return [Tinybucket::Enumerator] enumerator to enumerate repositories
21
+ # as [Tinybucket::Model::Repository]
29
22
  def repos(*args)
30
23
  case args.size
31
24
  when 0
@@ -46,25 +39,36 @@ module Tinybucket
46
39
  end
47
40
  end
48
41
 
42
+ # Get the repository
43
+ #
44
+ # @param owner [String] repository owner name.
45
+ # @param repo_slug [String] repository slug. (about {https://confluence.atlassian.com/bitbucket/repositories-endpoint-423626330.html#repositoriesEndpoint-Overview
46
+ # repo_slug})
47
+ # @return [Tinybucket::Model::Repository]
49
48
  def repo(owner, repo_slug)
50
49
  m = Tinybucket::Model::Repository.new({})
51
50
  m.repo_owner = owner
52
51
  m.repo_slug = repo_slug
53
- m.api_config = config.dup
54
52
  m
55
53
  end
56
54
 
55
+ # Get the team
56
+ #
57
+ # @param teamname [String] the team name.
58
+ # @return [Tinybucket::Model::Team]
57
59
  def team(teamname)
58
60
  m = Tinybucket::Model::Team.new({})
59
61
  m.username = teamname
60
- m.api_config = config.dup
61
62
  m
62
63
  end
63
64
 
65
+ # Get the user profile
66
+ #
67
+ # @param username [String] the user name.
68
+ # @return [Tinybucket::Model::Profile]
64
69
  def user(username)
65
70
  m = Tinybucket::Model::Profile.new({})
66
71
  m.username = username
67
- m.api_config = config.dup
68
72
  m
69
73
  end
70
74
 
@@ -74,8 +78,11 @@ module Tinybucket
74
78
  options = args.empty? ? {} : args.first
75
79
  raise ArgumentError unless options.is_a?(Hash)
76
80
 
77
- @repos ||= create_instance('Repos', options)
78
- @repos.list(options)
81
+ enumerator(
82
+ repos_api,
83
+ :list,
84
+ options
85
+ )
79
86
  end
80
87
 
81
88
  def owners_repos(*args)
@@ -83,13 +90,25 @@ module Tinybucket
83
90
  options = (args.size == 2) ? args[1] : {}
84
91
  raise ArgumentError unless options.is_a?(Hash)
85
92
 
86
- @user ||= create_instance('User', options)
87
- @user.username = owner
88
- @user.repos(options)
93
+ enumerator(
94
+ user_api(owner),
95
+ :repos,
96
+ options
97
+ )
98
+ end
99
+
100
+ def repos_api
101
+ create_instance('Repos')
102
+ end
103
+
104
+ def user_api(owner)
105
+ api = create_instance('User')
106
+ api.username = owner
107
+ api
89
108
  end
90
109
 
91
- def create_instance(name, options)
92
- ApiFactory.create_instance(name, config, options)
110
+ def create_instance(name)
111
+ ApiFactory.create_instance(name)
93
112
  end
94
113
  end
95
114
  end
@@ -1,6 +1,6 @@
1
1
  module Tinybucket
2
2
  class Config
3
3
  include ActiveSupport::Configurable
4
- config_accessor :logger
4
+ config_accessor :logger, :oauth_token, :oauth_secret
5
5
  end
6
6
  end
@@ -32,8 +32,8 @@ module Tinybucket
32
32
  def default_middleware(_options)
33
33
  proc do |conn|
34
34
  oauth_secrets = {
35
- consumer_key: config(:oauth_token),
36
- consumer_secret: config(:oauth_secret)
35
+ consumer_key: Tinybucket.config.oauth_token,
36
+ consumer_secret: Tinybucket.config.oauth_secret
37
37
  }
38
38
 
39
39
  conn.request :multipart
@@ -42,7 +42,7 @@ module Tinybucket
42
42
 
43
43
  conn.response :follow_oauth_redirects, oauth_secrets
44
44
  conn.response :json, content_type: /\bjson$/
45
- conn.use Tinybucket::Response::ErrorHandler
45
+ conn.use Tinybucket::Response::Handler
46
46
  conn.use :instrumentation
47
47
 
48
48
  conn.adapter Faraday.default_adapter
@@ -0,0 +1,44 @@
1
+ module Tinybucket
2
+ class Enumerator < ::Enumerator
3
+ # Constructor
4
+ #
5
+ # This method create a enumerator to enumerate each items of iterator.
6
+ #
7
+ # @note This method return Lazy Enumerator if run on ruby 2.0.0 later.
8
+ #
9
+ # @param iterator [Tinybucket::Iterator] iterator instance.
10
+ # @param block [Proc] a proc object to handle each item.
11
+ def initialize(iterator, block)
12
+ @iterator = iterator
13
+
14
+ super() do |y|
15
+ loop do
16
+ m = y.yield(@iterator.next)
17
+ m = block.call(m) if block
18
+ m
19
+ end
20
+ end
21
+
22
+ lazy if lazy_enumerable?
23
+ end
24
+
25
+ # Get collection size.
26
+ #
27
+ # @see Tinybucket::Iterator#size
28
+ #
29
+ # @return [Fixnum, NillClass] collection size.
30
+ def size
31
+ @iterator.size
32
+ end
33
+
34
+ private
35
+
36
+ def lazy_enumerable?
37
+ ruby_major_version >= 2
38
+ end
39
+
40
+ def ruby_major_version
41
+ RUBY_VERSION.split('.')[0].to_i
42
+ end
43
+ end
44
+ end
@@ -4,5 +4,7 @@ module Tinybucket
4
4
 
5
5
  autoload :BaseError
6
6
  autoload :ServiceError
7
+ autoload :Conflict
8
+ autoload :NotFound
7
9
  end
8
10
  end
@@ -0,0 +1,6 @@
1
+ module Tinybucket
2
+ module Error
3
+ class Conflict < ServiceError
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Tinybucket
2
+ module Error
3
+ class NotFound < ServiceError
4
+ end
5
+ end
6
+ end
@@ -2,18 +2,22 @@ module Tinybucket
2
2
  module Error
3
3
  class ServiceError < BaseError
4
4
  attr_accessor :http_headers
5
+ attr_reader :http_method, :request_url, :status_code, :response_body
5
6
 
6
7
  def initialize(env)
7
8
  super generate_message(env)
8
9
  @http_headers = env[:response_headers]
9
10
  end
10
11
 
12
+ private
13
+
11
14
  def generate_message(env)
12
- http_method = env[:method].to_s.upcase
13
- url = env[:url].to_s
14
- status = env[:status]
15
+ @http_method = env[:method].to_s.upcase
16
+ @request_url = env[:url].to_s
17
+ @status_code = env[:status]
18
+ @response_body = env[:body]
15
19
 
16
- "#{http_method} #{url} #{status} #{env[:body]}"
20
+ "#{@http_method} #{@request_url} #{@status_code} #{@response_body}"
17
21
  end
18
22
  end
19
23
  end
@@ -0,0 +1,77 @@
1
+ module Tinybucket
2
+ # Iterator
3
+ #
4
+ # This iterator iterate items by sending request ot Bitbucket Cloud REST API.
5
+ class Iterator
6
+ # Constructor
7
+ #
8
+ # @param api_client [Tinybucket::Api::Base] an instance of Api Client class.
9
+ # @param method [Symbol] method name to invoke api_client method.
10
+ # @param args [Array<Object>] arguments to pass method call of
11
+ # api_client as arguments.
12
+ def initialize(api_client, method, *args)
13
+ @client = api_client
14
+ @method = method
15
+ @args = args
16
+
17
+ @attrs = {}
18
+ @values = []
19
+ @pos = nil
20
+ end
21
+
22
+ def next
23
+ next_value
24
+ end
25
+
26
+ # Get collection size.
27
+ #
28
+ # @note This method return {https://confluence.atlassian.com/bitbucket/version-2-423626329.html#Version2-Pagingthroughobjectcollections
29
+ # size attribute of object collection wrapper}.
30
+ # So this method may return nil.
31
+ #
32
+ # @see https://confluence.atlassian.com/bitbucket/version-2-423626329.html#Version2-Pagingthroughobjectcollections
33
+ # Paging through object collections
34
+ #
35
+ # @return [Fixnum, NillClas] collection size.
36
+ def size
37
+ load_next if next?
38
+ @attrs[:size]
39
+ end
40
+
41
+ private
42
+
43
+ def next_value
44
+ load_next if next?
45
+
46
+ @values.fetch(@pos).tap { @pos += 1 }
47
+ rescue IndexError
48
+ raise StopIteration
49
+ end
50
+
51
+ def next?
52
+ @pos.nil? || (@values.size == @pos && @attrs[:next])
53
+ end
54
+
55
+ def load_next
56
+ @pos = 0 if @pos.nil?
57
+
58
+ page = @client.send(@method, *next_params)
59
+
60
+ @attrs = page.attrs
61
+ @values.concat(page.items)
62
+ end
63
+
64
+ def next_params
65
+ params =
66
+ if @attrs.empty?
67
+ {}
68
+ else
69
+ unescaped_query = URI.unescape(URI.parse(@attrs[:next]).query)
70
+ Hash[*unescaped_query.split(/&|=/)]
71
+ end
72
+
73
+ @args[-1].merge!(params)
74
+ @args
75
+ end
76
+ end
77
+ end
@@ -3,7 +3,8 @@ module Tinybucket
3
3
  class Base
4
4
  include ::ActiveModel::Serializers::JSON
5
5
  include Concerns::AcceptableAttributes
6
- attr_accessor :api_config
6
+ include Concerns::Enumerable
7
+ include Concerns::Reloadable
7
8
 
8
9
  def self.concern_included?(concern_name)
9
10
  mod_name = "Tinybucket::Model::Concerns::#{concern_name}".constantize
@@ -12,7 +13,6 @@ module Tinybucket
12
13
 
13
14
  def initialize(json)
14
15
  self.attributes = json
15
- @api_config = {}
16
16
  @_loaded = !json.empty?
17
17
  end
18
18
 
@@ -36,12 +36,12 @@ module Tinybucket
36
36
 
37
37
  protected
38
38
 
39
- def create_api(api_key, keys, options)
39
+ def create_api(api_key, keys)
40
40
  key = ('@' + api_key.underscore).intern
41
41
  api = instance_variable_get(key)
42
42
  return api if api.present?
43
43
 
44
- api = create_instance(api_key, options)
44
+ api = create_instance(api_key)
45
45
  api.repo_owner = keys[:repo_owner]
46
46
  api.repo_slug = keys[:repo_slug]
47
47
  instance_variable_set(key, api)
@@ -49,8 +49,8 @@ module Tinybucket
49
49
  api
50
50
  end
51
51
 
52
- def create_instance(klass_name, options)
53
- ApiFactory.create_instance(klass_name, api_config, options)
52
+ def create_instance(klass_name)
53
+ ApiFactory.create_instance(klass_name)
54
54
  end
55
55
 
56
56
  def logger
@@ -1,14 +1,41 @@
1
1
  module Tinybucket
2
2
  module Model
3
+ # BranchRestriction
4
+ #
5
+ # @see https://confluence.atlassian.com/bitbucket/branch-restrictions-resource-387449181.html
6
+ # branch-restrictions Resource - Bitbucket Cloud REST API document
7
+ #
8
+ # @!attribute [rw] groups
9
+ # @return [Array]
10
+ # @!attribute [rw] id
11
+ # @return [Fixnum]
12
+ # @!attribute [rw] kind
13
+ # @return [String]
14
+ # @!attribute [rw] links
15
+ # @return [Hash]
16
+ # @!attribute [rw] pattern
17
+ # @return [String]
18
+ # @!attribute [rw] users
19
+ # @return [Array]
20
+ # @!attribute [rw] uuid
21
+ # @return [NillClass]
3
22
  class BranchRestriction < Base
4
23
  include Tinybucket::Model::Concerns::RepositoryKeys
5
24
 
6
25
  acceptable_attributes :groups, :id, :kind, :links, :pattern, :users, :uuid
7
26
 
27
+ # Update this branch restriction
28
+ #
29
+ # @todo to be implemented
30
+ # @raise [NotImplementedError] to be implemented.
8
31
  def update(_params)
9
32
  raise NotImplementedError
10
33
  end
11
34
 
35
+ # Delete this branch restriction
36
+ #
37
+ # @todo to be implemented
38
+ # @raise [NotImplementedError] to be implemented.
12
39
  def destroy
13
40
  raise NotImplementedError
14
41
  end
@@ -1,32 +1,58 @@
1
1
  module Tinybucket
2
2
  module Model
3
+ # Comment
4
+ #
5
+ # @see https://confluence.atlassian.com/bitbucket/pullrequests-resource-423626332.html#pullrequestsResource-GETalistofapullrequestcomments
6
+ # Comment resource - Bitbucket Cloud REST API document
7
+ #
8
+ # @!attribute [rw] links
9
+ # @return [Hash]
10
+ # @!attribute [rw] id
11
+ # @return [Fixnum]
12
+ # @!attribute [rw] parent
13
+ # @return [Hash]
14
+ # @!attribute [rw] filename
15
+ # @return [String]
16
+ # @!attribute [rw] content
17
+ # @return [Hash]
18
+ # @!attribute [rw] user
19
+ # @return [Hash]
20
+ # @!attribute [rw] inline
21
+ # @return [Hash]
22
+ # @!attribute [rw] created_on
23
+ # @return [String]
24
+ # @!attribute [rw] updated_on
25
+ # @return [String]
26
+ # @!attribute [rw] uuid
27
+ # @return [NillClass]
3
28
  class Comment < Base
4
29
  include Tinybucket::Model::Concerns::RepositoryKeys
5
- include Tinybucket::Model::Concerns::Reloadable
6
30
 
7
31
  acceptable_attributes \
8
32
  :links, :id, :parent, :filename, :content, :user, :inline, \
9
33
  :created_on, :updated_on, :uuid
10
34
 
35
+ # @!attribute [rw] commented_to
36
+ # @return [Tinybucket::Model::PullRequest, Tinybucket::Model::Commit]
11
37
  attr_accessor :commented_to
12
38
 
13
39
  private
14
40
 
15
41
  def commit_api
16
- create_api('Comments', repo_keys, options)
42
+ create_api('Comments', repo_keys)
17
43
  end
18
44
 
19
- def pull_request_api(options)
20
- create_api('PullRequests', repo_keys, options)
45
+ def pull_request_api
46
+ create_api('PullRequests', repo_keys)
21
47
  end
22
48
 
23
49
  def load_model
24
50
  api =
25
51
  case commented_to
26
52
  when Tinybucket::Model::Commit
27
- commit_api({})
53
+ commit_api
28
54
  when Tinybucket::Model::PullRequest
29
- pull_request_api({})
55
+ pull_request_api
30
56
  else
31
57
  raise ArgumentError, 'commented_to was invalid'
32
58
  end