From 1a5788e2a15826fffc6ff9c283065698bcbecb55 Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Tue, 13 Oct 2015 12:33:26 +0200 Subject: [PATCH 1/4] v3: allow sorting branches by exists_on_github --- lib/travis/api/v3/queries/branches.rb | 5 ++++- spec/v3/services/branches/find_spec.rb | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/lib/travis/api/v3/queries/branches.rb b/lib/travis/api/v3/queries/branches.rb index c368fa7d..6566a1a8 100644 --- a/lib/travis/api/v3/queries/branches.rb +++ b/lib/travis/api/v3/queries/branches.rb @@ -1,6 +1,9 @@ module Travis::API::V3 class Queries::Branches < Query - sortable_by :name, last_build: "builds.started_at".freeze + sortable_by :name, + last_build: "builds.started_at".freeze, + exists_on_github: "(case when branches.exists_on_github then 1 else 2 end)".freeze + default_sort "last_build:desc" def find(repository) diff --git a/spec/v3/services/branches/find_spec.rb b/spec/v3/services/branches/find_spec.rb index e43b13e1..68a45a86 100644 --- a/spec/v3/services/branches/find_spec.rb +++ b/spec/v3/services/branches/find_spec.rb @@ -216,6 +216,28 @@ describe Travis::API::V3::Services::Branches::Find do } end + describe "sorting by exists_on_github" do + before { get("/v3/repo/#{repo.id}/branches?sort_by=exists_on_github&limit=1") } + example { expect(last_response).to be_ok } + example { expect(parsed_body["@pagination"]).to be == { + "limit" => 1, + "offset" => 0, + "count" => 1, + "is_first" => true, + "is_last" => true, + "next" => nil, + "prev" => nil, + "first" => { + "@href" => "/v3/repo/#{repo.id}/branches?sort_by=exists_on_github&limit=1", + "offset" => 0, + "limit" => 1 }, + "last" => { + "@href" => "/v3/repo/#{repo.id}/branches?sort_by=exists_on_github&limit=1", + "offset" => 0, + "limit" => 1 }} + } + end + describe "sorting by unknown sort field" do before { get("/v3/repo/#{repo.id}/branches?sort_by=name:desc,foo&limit=1") } example { expect(last_response).to be_ok } From 1d783129ced9437f592c836427ab859280257f43 Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Tue, 13 Oct 2015 12:42:03 +0200 Subject: [PATCH 2/4] v3: allow filtering branches by exists_on_github --- lib/travis/api/v3/queries/branches.rb | 9 ++++++++- lib/travis/api/v3/services/branches/find.rb | 1 + spec/v3/services/branches/find_spec.rb | 14 ++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/lib/travis/api/v3/queries/branches.rb b/lib/travis/api/v3/queries/branches.rb index 6566a1a8..6eb36728 100644 --- a/lib/travis/api/v3/queries/branches.rb +++ b/lib/travis/api/v3/queries/branches.rb @@ -1,5 +1,7 @@ module Travis::API::V3 class Queries::Branches < Query + params :exists_on_github, prefix: :branch + sortable_by :name, last_build: "builds.started_at".freeze, exists_on_github: "(case when branches.exists_on_github then 1 else 2 end)".freeze @@ -7,7 +9,12 @@ module Travis::API::V3 default_sort "last_build:desc" def find(repository) - sort repository.branches + sort filter(repository.branches) + end + + def filter(list) + list = list.where(exists_on_github: bool(exists_on_github)) unless exists_on_github.nil? + list end end end diff --git a/lib/travis/api/v3/services/branches/find.rb b/lib/travis/api/v3/services/branches/find.rb index cd618c70..34cf0ef1 100644 --- a/lib/travis/api/v3/services/branches/find.rb +++ b/lib/travis/api/v3/services/branches/find.rb @@ -1,5 +1,6 @@ module Travis::API::V3 class Services::Branches::Find < Service + params :exists_on_github, prefix: :branch paginate def run! diff --git a/spec/v3/services/branches/find_spec.rb b/spec/v3/services/branches/find_spec.rb index 68a45a86..a6a2db39 100644 --- a/spec/v3/services/branches/find_spec.rb +++ b/spec/v3/services/branches/find_spec.rb @@ -172,6 +172,20 @@ describe Travis::API::V3::Services::Branches::Find do } end + describe "filtering by exists_on_github" do + describe "false" do + before { get("/v3/repo/#{repo.id}/branches?branch.exists_on_github=false") } + example { expect(last_response).to be_ok } + example { expect(parsed_body["branches"]).to be_empty } + end + + describe "true" do + before { get("/v3/repo/#{repo.id}/branches?branch.exists_on_github=true") } + example { expect(last_response).to be_ok } + example { expect(parsed_body["branches"]).not_to be_empty } + end + end + describe "sorting by name" do before { get("/v3/repo/#{repo.id}/branches?sort_by=name&limit=1") } example { expect(last_response).to be_ok } From 949a8765508c5842d94bf2c04f270a547b2f9735 Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Tue, 13 Oct 2015 13:08:27 +0200 Subject: [PATCH 3/4] v3: allow sorting branches by them being default branch or not --- lib/travis/api/v3/queries/branches.rb | 19 ++++++++++++++++--- lib/travis/api/v3/query.rb | 23 +++++++++++++++++++---- spec/v3/services/branches/find_spec.rb | 22 ++++++++++++++++++++++ 3 files changed, 57 insertions(+), 7 deletions(-) diff --git a/lib/travis/api/v3/queries/branches.rb b/lib/travis/api/v3/queries/branches.rb index 6eb36728..48f6b5b5 100644 --- a/lib/travis/api/v3/queries/branches.rb +++ b/lib/travis/api/v3/queries/branches.rb @@ -3,13 +3,26 @@ module Travis::API::V3 params :exists_on_github, prefix: :branch sortable_by :name, - last_build: "builds.started_at".freeze, - exists_on_github: "(case when branches.exists_on_github then 1 else 2 end)".freeze + last_build: "builds.started_at".freeze, + exists_on_github: sort_condition(:exists_on_github), + default_branch: sort_condition(name: "repositories.default_branch") default_sort "last_build:desc" def find(repository) - sort filter(repository.branches) + sort(filter(repository.branches), repository: repository) + end + + def sort_by(collection, field, repository: nil, **options) + return super unless field == "default_branch".freeze + + if repository + options[:sql] = sort_condition(name: quote(repository.default_branch_name)) + else + collection = collection.joins(:repository) + end + + super(collection, field, **options) end def filter(list) diff --git a/lib/travis/api/v3/query.rb b/lib/travis/api/v3/query.rb index 488018bf..e4ea4f09 100644 --- a/lib/travis/api/v3/query.rb +++ b/lib/travis/api/v3/query.rb @@ -48,6 +48,13 @@ module Travis::API::V3 mapping.each { |key, value| sort_by[key.to_s] = prefix(value) } end + def self.sort_condition(condition) + if condition.is_a? Hash + condition = condition.map { |e| e.map { |v| prefix(v) }.join(" = ".freeze) }.join(" and ".freeze) + end + "(case when #{prefix(condition)} then 1 else 2 end)" + end + def self.sortable? !sort_by.empty? end @@ -111,14 +118,14 @@ module Travis::API::V3 value.split(?,.freeze) end - def sort(collection) + def sort(collection, **options) return collection unless sort_by = params["sort_by".freeze] || self.class.default_sort and not sort_by.empty? first = true list(sort_by).each do |field_with_order| field, order = field_with_order.split(?:.freeze, 2) order ||= "asc".freeze if sort_by? field, order - collection = sort_by(collection, field, order: order, first: first) + collection = sort_by(collection, field, order: order, first: first, **options) first = false else ignored_value("sort_by".freeze, field_with_order, reason: "not a valid sort mode".freeze) @@ -132,9 +139,9 @@ module Travis::API::V3 self.class.sort_by.include?(field) end - def sort_by(collection, field, order: nil, first: false) + def sort_by(collection, field, order: nil, first: false, sql: nil, **) raise ArgumentError, 'cannot sort by that' unless sort_by?(field, order) - actual = self.class.sort_by.fetch(field) + actual = sql || self.class.sort_by.fetch(field) line = "#{actual} #{order.upcase}" if sort_join?(collection, actual) @@ -150,6 +157,14 @@ module Travis::API::V3 !collection.reflect_on_association(field.to_sym).nil? end + def sort_condition(*args) + self.class.sort_condition(*args) + end + + def quote(value) + ActiveRecord::Base.connection.quote(value) + end + def user_condition(value) case value when String then { login: value } diff --git a/spec/v3/services/branches/find_spec.rb b/spec/v3/services/branches/find_spec.rb index a6a2db39..743a1a03 100644 --- a/spec/v3/services/branches/find_spec.rb +++ b/spec/v3/services/branches/find_spec.rb @@ -252,6 +252,28 @@ describe Travis::API::V3::Services::Branches::Find do } end + describe "sorting by default_branch" do + before { get("/v3/repo/#{repo.id}/branches?sort_by=default_branch&limit=1") } + example { expect(last_response).to be_ok } + example { expect(parsed_body["@pagination"]).to be == { + "limit" => 1, + "offset" => 0, + "count" => 1, + "is_first" => true, + "is_last" => true, + "next" => nil, + "prev" => nil, + "first" => { + "@href" => "/v3/repo/#{repo.id}/branches?sort_by=default_branch&limit=1", + "offset" => 0, + "limit" => 1 }, + "last" => { + "@href" => "/v3/repo/#{repo.id}/branches?sort_by=default_branch&limit=1", + "offset" => 0, + "limit" => 1 }} + } + end + describe "sorting by unknown sort field" do before { get("/v3/repo/#{repo.id}/branches?sort_by=name:desc,foo&limit=1") } example { expect(last_response).to be_ok } From 9edb598884d4493f555e7e750eb5a09d2d21fa6f Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Tue, 13 Oct 2015 13:09:50 +0200 Subject: [PATCH 4/4] v3: change branches default sort mode --- lib/travis/api/v3/queries/branches.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/travis/api/v3/queries/branches.rb b/lib/travis/api/v3/queries/branches.rb index 48f6b5b5..a2c8e1c3 100644 --- a/lib/travis/api/v3/queries/branches.rb +++ b/lib/travis/api/v3/queries/branches.rb @@ -7,7 +7,7 @@ module Travis::API::V3 exists_on_github: sort_condition(:exists_on_github), default_branch: sort_condition(name: "repositories.default_branch") - default_sort "last_build:desc" + default_sort "default_branch,exists_on_github,last_build:desc" def find(repository) sort(filter(repository.branches), repository: repository)