summaryrefslogtreecommitdiff
path: root/lib/bitbucket
diff options
context:
space:
mode:
authorDouglas Barbosa Alexandre <dbalexandre@gmail.com>2016-08-22 15:48:31 -0300
committerStan Hu <stanhu@gmail.com>2016-11-21 16:47:25 -0800
commite2f7f32a60a7663d12b5dae0320f640150f354e7 (patch)
treefafec7cd55481fa66d6e5757b89c507e2edf8e8b /lib/bitbucket
parentf1f5863bfc5727dba4767a54a299b0cf526b025a (diff)
downloadgitlab-ce-e2f7f32a60a7663d12b5dae0320f640150f354e7.tar.gz
Add support for Bitbucket pagination when fetching collections
Diffstat (limited to 'lib/bitbucket')
-rw-r--r--lib/bitbucket/collection.rb21
-rw-r--r--lib/bitbucket/page.rb36
-rw-r--r--lib/bitbucket/paginator.rb38
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