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,38 +1,92 @@
1
1
  module Tinybucket
2
2
  module Model
3
+ # Commit Resource
4
+ #
5
+ # @see https://confluence.atlassian.com/bitbucket/commits-or-commit-resource-389775478.html
6
+ # Commit Resource - Bitbucket Cloud REST API document
7
+ #
8
+ # @!attribute [rw] hash
9
+ # @return [String]
10
+ # @!attribute [rw] links
11
+ # @return [Hash]
12
+ # @!attribute [rw] repository
13
+ # @return [Hash]
14
+ # @!attribute [rw] author
15
+ # @return [Hash]
16
+ # @!attribute [rw] parents
17
+ # @return [Array]
18
+ # @!attribute [rw] date
19
+ # @return [String]
20
+ # @!attribute [rw] message
21
+ # @return [String]
22
+ # @!attribute [rw] participants
23
+ # @return [Array]
24
+ # @!attribute [rw] uuid
25
+ # @return [NillClass]
26
+ # @!attribute [rw] type
27
+ # @return [String]
3
28
  class Commit < Base
4
29
  include Tinybucket::Model::Concerns::RepositoryKeys
5
- include Tinybucket::Model::Concerns::Reloadable
6
30
  include Tinybucket::Constants
7
31
 
8
32
  acceptable_attributes \
9
33
  :hash, :links, :repository, :author, :parents, :date,
10
- :message, :participants, :uuid
34
+ :message, :participants, :uuid, :type
11
35
 
36
+ # Get comments which associate with this commit.
37
+ #
38
+ # @param options [Hash]
39
+ # @return [Tinybucket::Enumerator] enumerator to enumerate comments
40
+ # as {Tinybucket::Model::Comment} instance.
12
41
  def comments(options = {})
13
- comments_api(options).list(options)
42
+ enumerator(
43
+ comments_api,
44
+ :list,
45
+ options
46
+ ) { |m| block_given? ? yield(m) : m }
14
47
  end
15
48
 
49
+ # Get the specific commit comment which associate with this commit.
50
+ #
51
+ # @param comment_id [String] comment id
52
+ # @param options [Hash]
53
+ # @return [Tinybucket::Model::Comment]
16
54
  def comment(comment_id, options = {})
17
- comments_api(options).find(comment_id, options)
55
+ comments_api.find(comment_id, options)
56
+ end
57
+
58
+ # Give approval on this commit.
59
+ #
60
+ # @param options [Hash]
61
+ # @return [true, false]
62
+ def approve(options = {})
63
+ commit_api.approve(hash, options)
64
+ end
65
+
66
+ # Revoke approval on this commit.
67
+ #
68
+ # @param options [Hash]
69
+ # @return [true, false]
70
+ def unapprove(options = {})
71
+ commit_api.unapprove(hash, options)
18
72
  end
19
73
 
20
74
  private
21
75
 
22
- def comments_api(options)
76
+ def comments_api
23
77
  raise ArgumentError, MISSING_REPOSITORY_KEY unless repo_keys?
24
78
 
25
- api = create_api('Comments', repo_keys, options)
79
+ api = create_api('Comments', repo_keys)
26
80
  api.commented_to = self
27
81
  api
28
82
  end
29
83
 
30
- def commit_api(options)
31
- create_api 'Commits', repo_keys, options
84
+ def commit_api
85
+ create_api('Commits', repo_keys)
32
86
  end
33
87
 
34
88
  def load_model
35
- commit_api({}).find(hash)
89
+ commit_api.find(hash)
36
90
  end
37
91
  end
38
92
  end
@@ -5,6 +5,7 @@ module Tinybucket
5
5
 
6
6
  [
7
7
  :AcceptableAttributes,
8
+ :Enumerable,
8
9
  :RepositoryKeys,
9
10
  :Reloadable
10
11
  ].each do |mod_name|
@@ -0,0 +1,18 @@
1
+ module Tinybucket
2
+ module Model
3
+ module Concerns
4
+ module Enumerable
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ protected
9
+
10
+ def enumerator(api_client, method, *args, &block)
11
+ iter = Tinybucket::Iterator.new(api_client, method, *args)
12
+ Tinybucket::Enumerator.new(iter, block)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,6 +1,21 @@
1
1
  module Tinybucket
2
2
  module Model
3
- class ErrorResponse < Base
3
+ # ErrorResponse
4
+ #
5
+ # @see https://confluence.atlassian.com/bitbucket/version-2-423626329.html#Version2-Standardizederrorresponses
6
+ # Standardized error responses - Bitbucket Cloud REST API document
7
+ #
8
+ # @!attribute [rw] message
9
+ # @return [String]
10
+ # @!attribute [rw] fields
11
+ # @return [Hash]
12
+ # @!attribute [rw] detail
13
+ # @return [String]
14
+ # @!attribute [rw] id
15
+ # @return [String]
16
+ # @!attribute [rw] uuid
17
+ # @return [NillClass]
18
+ class ErrorResponse
4
19
  acceptable_attributes :message, :fields, :detail, :id, :uuid
5
20
  end
6
21
  end
@@ -1,66 +1,42 @@
1
1
  module Tinybucket
2
2
  module Model
3
+ # Page
4
+ #
5
+ # @see https://confluence.atlassian.com/bitbucket/version-2-423626329.html#Version2-Pagingthroughobjectcollections
6
+ # Paging through object collections - Bitbucket Cloud REST API document
7
+ #
8
+ # @!attribute [r] attrs
9
+ # This attribute is a Hash object which contains
10
+ # 'size', 'page', 'pagelen', 'next', 'previous' key/value pairs.
11
+ # @return [Hash]
12
+ # @!attribute [r] items
13
+ # This attribute is a array of model instance created with
14
+ # 'values' attribute in json.
3
15
  class Page
4
- # attr_reader :size, :page, :pagelen, :next, :previous
5
16
  attr_reader :attrs
6
17
  attr_reader :items
7
- attr_writer :next_proc
8
18
 
19
+ # Initialize with json and Model class.
20
+ #
21
+ # @param json [Hash]
22
+ # @param item_klass [Class]
9
23
  def initialize(json, item_klass)
10
- @attrs = {}
11
- %w(size page pagelen next previous).each do |attr|
12
- @attrs[attr.intern] = json[attr]
13
- end
14
-
15
- @items = if json['values'].present? && json['values'].is_a?(Array)
16
- json['values'].map { |hash| item_klass.new(hash) }
17
- else
18
- []
19
- end
20
- end
21
-
22
- def size
23
- @attrs[:size]
24
- end
25
-
26
- def each(options = {})
27
- loop do
28
- start = (@attrs[:page] - 1) * @attrs[:pagelen]
29
-
30
- @items.each_with_index do |m, i|
31
- pos = start + i
32
- yield(m, pos)
33
-
34
- raise StopIteration if \
35
- (!options[:limit].nil? && pos == (options[:limit] - 1))
36
- end
37
-
38
- break unless next_page?
39
-
40
- load_next
41
- end
42
-
43
- rescue StopIteration
44
- return
24
+ @attrs = parse_attrs(json)
25
+ @items = parse_values(json, item_klass)
45
26
  end
46
27
 
47
28
  private
48
29
 
49
- def next_page?
50
- @attrs[:next].present?
30
+ def parse_attrs(json)
31
+ %w(size page pagelen next previous).map do |attr|
32
+ { attr.to_sym => json[attr] }
33
+ end.reduce(&:merge)
51
34
  end
52
35
 
53
- def load_next
54
- raise StopIteration if @attrs[:next].nil? || @next_proc.nil?
55
-
56
- unescaped_query = URI.unescape(URI.parse(@attrs[:next]).query)
57
- query = Hash[*unescaped_query.split(/&|=/)]
58
- list = @next_proc.call(query)
59
-
60
- raise StopIteration if list.items.empty?
36
+ def parse_values(json, item_klass)
37
+ return [] if json['values'].nil? || !json['values'].is_a?(Array)
61
38
 
62
- @attrs = list.attrs
63
- @items = list.items
39
+ json['values'].map { |hash| item_klass.new(hash) }
64
40
  end
65
41
  end
66
42
  end
@@ -1,36 +1,84 @@
1
1
  module Tinybucket
2
2
  module Model
3
+ # Profile
4
+ #
5
+ # @see https://confluence.atlassian.com/bitbucket/users-endpoint-423626336.html#usersEndpoint-GETtheuserprofile
6
+ # users Endpoint - Bitbucket Cloud REST API document
7
+ #
8
+ # @!attribute [rw] username
9
+ # @return [String]
10
+ # @!attribute [rw] kind
11
+ # @return [NillClass]
12
+ # @!attribute [rw] website
13
+ # @return [String]
14
+ # @!attribute [rw] display_name
15
+ # @return [String]
16
+ # @!attribute [rw] links
17
+ # @return [Hash]
18
+ # @!attribute [rw] created_on
19
+ # @return [String]
20
+ # @!attribute [rw] location
21
+ # @return [String]
22
+ # @!attribute [rw] type
23
+ # @return [String]
24
+ # @!attribute [rw] uuid
25
+ # @return [String]
3
26
  class Profile < Base
4
- include Tinybucket::Model::Concerns::Reloadable
5
-
6
27
  acceptable_attributes \
7
28
  :username, :kind, :website, :display_name,
8
29
  :links, :created_on, :location, :type, :uuid
9
30
 
31
+ # Get this user's followers
32
+ #
33
+ # @param options [Hash]
34
+ # @return [Tinybucket::Enumerator] enumerator to enumerate followers
35
+ # as {Tinybucket::Model::Profile} instance.
10
36
  def followers(options = {})
11
- user_api(options).followers(options)
37
+ enumerator(
38
+ user_api,
39
+ :followers,
40
+ options
41
+ ) { |m| block_given? ? yield(m) : m }
12
42
  end
13
43
 
44
+ # Get users which this user is following
45
+ #
46
+ # @param options [Hash]
47
+ # @return [Tinybucket::Enumerator] an enumerator to enumerate followings
48
+ # as {Tinybucket::Model::Profile} instance.
14
49
  def following(options = {})
15
- user_api(options).following(options)
50
+ enumerator(
51
+ user_api,
52
+ :following,
53
+ options
54
+ ) { |m| block_given? ? yield(m) : m }
16
55
  end
17
56
 
57
+ # Get this user's repositories
58
+ #
59
+ # @param options [Hash]
60
+ # @return [Tinybucket::Enumerator] an enumerator to enumerate repositories
61
+ # as {Tinybucket::Model::Repository} instance.
18
62
  def repos(options = {})
19
- user_api(options).repos(options)
63
+ enumerator(
64
+ user_api,
65
+ :repos,
66
+ options
67
+ ) { |m| block_given? ? yield(m) : m }
20
68
  end
21
69
 
22
70
  private
23
71
 
24
- def user_api(options)
72
+ def user_api
25
73
  return @user if @user
26
74
 
27
- @user = create_instance 'User', options
75
+ @user = create_instance('User')
28
76
  @user.username = username
29
77
  @user
30
78
  end
31
79
 
32
80
  def load_model
33
- user_api({}).profile
81
+ user_api.profile
34
82
  end
35
83
  end
36
84
  end
@@ -1,71 +1,167 @@
1
1
  module Tinybucket
2
2
  module Model
3
+ # PullRequest
4
+ #
5
+ # @see https://confluence.atlassian.com/bitbucket/pullrequests-resource-423626332.html#pullrequestsResource-Overview
6
+ # pullrequest resource - Bitbucket Cloud REST API document
7
+ #
8
+ # @!attribute [rw] state
9
+ # @return [String]
10
+ # @!attribute [rw] description
11
+ # @return [String]
12
+ # @!attribute [rw] links
13
+ # @return [Hash]
14
+ # @!attribute [rw] title
15
+ # @return [String]
16
+ # @!attribute [rw] task_count
17
+ # @return [Fixnum]
18
+ # @!attribute [rw] comment_count
19
+ # @return [Fixnum]
20
+ # @!attribute [rw] close_source_branch
21
+ # @return [true, false]
22
+ # @!attribute [rw] destination
23
+ # @return [Hash]
24
+ # @!attribute [rw] reason
25
+ # @return [String]
26
+ # @!attribute [rw] id
27
+ # @return [Fixnum]
28
+ # @!attribute [rw] source
29
+ # @return [Hash]
30
+ # @!attribute [rw] created_on
31
+ # @return [String]
32
+ # @!attribute [rw] author
33
+ # @return [Hash]
34
+ # @!attribute [rw] updated_on
35
+ # @return [String]
36
+ # @!attribute [rw] merge_commit
37
+ # @return [Hash]
38
+ # @!attribute [rw] closed_by
39
+ # @return [Hash]
40
+ # @!attribute [rw] reviewers
41
+ # @return [Array]
42
+ # @!attribute [rw] participants
43
+ # @return [Array]
44
+ # @!attribute [rw] uuid
45
+ # @return [NillClass]
46
+ # @!attribute [rw] type
47
+ # @return [String]
3
48
  class PullRequest < Base
4
49
  include Tinybucket::Model::Concerns::RepositoryKeys
5
- include Tinybucket::Model::Concerns::Reloadable
6
50
  include Tinybucket::Constants
7
51
 
8
52
  acceptable_attributes \
9
- :state, :description, :links, :title, :close_source_branch,
10
- :destination, :reason, :id, :source, :created_on, :author, :updated_on,
11
- :merge_commit, :closed_by, :reviewers, :participants, :uuid
12
-
53
+ :state, :description, :links, :title, :task_count, :comment_count,
54
+ :close_source_branch, :destination, :reason, :id, :source,
55
+ :created_on, :author, :updated_on, :merge_commit, :closed_by,
56
+ :reviewers, :participants, :uuid, :type
57
+
58
+ # Create a new pull request.
59
+ #
60
+ # @todo to be implemented.
61
+ # @raise [NotImplementedError] to be implemented.
13
62
  def create(_params)
14
63
  raise NotImplementedError
15
64
  end
16
65
 
66
+ # Update this pull request.
67
+ #
68
+ # @todo to be implemented.
69
+ # @raise [NotImplementedError] to be implemented.
17
70
  def update(_params)
18
71
  raise NotImplementedError
19
72
  end
20
73
 
74
+ # Decline or reject this pull request.
75
+ #
76
+ # @param options [Hash]
77
+ # @return [true,false]
21
78
  def decline(options = {})
22
- pull_request_api(options).decline(id, options)
79
+ pull_request_api.decline(id, options)
23
80
  end
24
81
 
82
+ # Give approval on this pull request.
83
+ #
84
+ # @param options [Hash]
85
+ # @return [true, false]
25
86
  def approve(options = {})
26
- pull_request_api(options).approve(id, options)
87
+ pull_request_api.approve(id, options)
27
88
  end
28
89
 
90
+ # Revoke approval on this pull request.
91
+ #
92
+ # @param options [Hash]
93
+ # @return [true, false]
29
94
  def unapprove(options = {})
30
- pull_request_api(options).unapprove(id, options)
95
+ pull_request_api.unapprove(id, options)
31
96
  end
32
97
 
98
+ # Get commits associated with this pull request.
99
+ #
100
+ # @param options [Hash]
101
+ # @return [Tinybucket::Enumerator] enumerator to enumerate commits
102
+ # as {Tinybucket::Model::Commit} instance.
33
103
  def commits(options = {})
34
- pull_request_api(options).commits(id, options)
104
+ enumerator(
105
+ pull_request_api,
106
+ :commits,
107
+ id,
108
+ options
109
+ ) { |m| block_given? ? yield(m) : m }
35
110
  end
36
111
 
112
+ # Get comments on this pull request.
113
+ #
114
+ # @param options [Hash]
115
+ # @return [Tinybucket::Enumerator] enumerator to enumerate comments
116
+ # as {Tinybucket::Model::Comment} instance.
37
117
  def comments(options = {})
38
- comment_api(options).list(options)
118
+ enumerator(
119
+ comment_api,
120
+ :list,
121
+ options
122
+ ) { |m| block_given? ? yield(m) : m }
39
123
  end
40
124
 
125
+ # Get the specific comment on this pull request.
126
+ #
127
+ # @param options [Hash]
128
+ # @return [Tinybucket::Model::Comment]
41
129
  def comment(comment_id, options = {})
42
- comment_api(options).find(comment_id, options)
130
+ comment_api.find(comment_id, options)
43
131
  end
44
132
 
133
+ # Get the diff for this pull request.
134
+ #
135
+ # @param options [Hash]
136
+ # @return [String] diff as raw text.
45
137
  def diff(options = {})
46
- pull_request_api(options).diff(id, options)
138
+ pull_request_api.diff(id, options)
47
139
  end
48
140
 
141
+ # Accept and merge this pull request.
142
+ #
143
+ # @param options [Hash]
144
+ # @return [true, false]
49
145
  def merge(options = {})
50
- pull_request_api(options).merge(id, options)
146
+ pull_request_api.merge(id, options)
51
147
  end
52
148
 
53
149
  private
54
150
 
55
- def comment_api(options)
56
- api = create_api('Comments', repo_keys, options)
151
+ def comment_api
152
+ api = create_api('Comments', repo_keys)
57
153
  api.commented_to = self
58
154
  api
59
155
  end
60
156
 
61
- def pull_request_api(options)
157
+ def pull_request_api
62
158
  raise ArgumentError, MISSING_REPOSITORY_KEY unless repo_keys?
63
159
 
64
- create_api('PullRequests', repo_keys, options)
160
+ create_api('PullRequests', repo_keys)
65
161
  end
66
162
 
67
163
  def load_model
68
- pull_request_api({}).find(id)
164
+ pull_request_api.find(id)
69
165
  end
70
166
  end
71
167
  end