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,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