diff options
author | Douglas Barbosa Alexandre <dbalexandre@gmail.com> | 2016-08-22 15:48:31 -0300 |
---|---|---|
committer | Stan Hu <stanhu@gmail.com> | 2016-11-21 16:47:25 -0800 |
commit | e2f7f32a60a7663d12b5dae0320f640150f354e7 (patch) | |
tree | fafec7cd55481fa66d6e5757b89c507e2edf8e8b /lib/bitbucket | |
parent | f1f5863bfc5727dba4767a54a299b0cf526b025a (diff) | |
download | gitlab-ce-e2f7f32a60a7663d12b5dae0320f640150f354e7.tar.gz |
Add support for Bitbucket pagination when fetching collections
Diffstat (limited to 'lib/bitbucket')
-rw-r--r-- | lib/bitbucket/collection.rb | 21 | ||||
-rw-r--r-- | lib/bitbucket/page.rb | 36 | ||||
-rw-r--r-- | lib/bitbucket/paginator.rb | 38 |
3 files changed, 95 insertions, 0 deletions
diff --git a/lib/bitbucket/collection.rb b/lib/bitbucket/collection.rb new file mode 100644 index 00000000000..9cc8947417c --- /dev/null +++ b/lib/bitbucket/collection.rb @@ -0,0 +1,21 @@ +module Bitbucket + class Collection < Enumerator + def initialize(paginator) + super() do |yielder| + loop do + paginator.next.each { |item| yielder << item } + end + end + + lazy + end + + def method_missing(method, *args) + return super unless self.respond_to?(method) + + self.send(method, *args) do |item| + block_given? ? yield(item) : item + end + end + end +end diff --git a/lib/bitbucket/page.rb b/lib/bitbucket/page.rb new file mode 100644 index 00000000000..ad9a2baba36 --- /dev/null +++ b/lib/bitbucket/page.rb @@ -0,0 +1,36 @@ +module Bitbucket + class Page + attr_reader :attrs, :items + + def initialize(raw, type) + @attrs = parse_attrs(raw) + @items = parse_values(raw, representation_class(type)) + end + + def next? + attrs.fetch(:next, false) + end + + def next + attrs.fetch(:next) + end + + private + + def parse_attrs(raw) + attrs = %w(size page pagelen next previous) + attrs.map { |attr| { attr.to_sym => raw[attr] } }.reduce(&:merge) + end + + def parse_values(raw, representation_class) + return [] if raw['values'].nil? || !raw['values'].is_a?(Array) + + raw['values'].map { |hash| representation_class.new(hash) } + end + + def representation_class(type) + class_name = "Bitbucket::Representation::#{type.to_s.camelize}" + class_name.constantize + end + end +end diff --git a/lib/bitbucket/paginator.rb b/lib/bitbucket/paginator.rb new file mode 100644 index 00000000000..a1672d9eaa1 --- /dev/null +++ b/lib/bitbucket/paginator.rb @@ -0,0 +1,38 @@ +module Bitbucket + class Paginator + PAGE_LENGTH = 50 # The minimum length is 10 and the maximum is 100. + + def initialize(connection, url, type) + @connection = connection + @type = type + @url = url + @page = nil + + connection.query(pagelen: PAGE_LENGTH, sort: :created_on) + end + + def next + raise StopIteration unless has_next_page? + + @page = fetch_next_page + @page.items + end + + private + + attr_reader :connection, :page, :url, :type + + def has_next_page? + page.nil? || page.next? + end + + def page_url + page.nil? ? url : page.next + end + + def fetch_next_page + parsed_response = connection.get(page_url) + Page.new(parsed_response, type) + end + end +end |