tinybucket 0.1.7 → 1.0.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 (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