Commit d7adcdc9 authored by Nick Thomas's avatar Nick Thomas

Merge remote-tracking branch 'upstream/master' into ce-to-ee-2017-07-06

parents 5613e1b2 200f9ba8
...@@ -301,10 +301,6 @@ module Ci ...@@ -301,10 +301,6 @@ module Ci
artifacts_metadata? artifacts_metadata?
end end
def downloadable_single_artifacts_file?
artifacts_metadata? && artifacts_file.file_storage?
end
def artifacts_metadata? def artifacts_metadata?
artifacts? && artifacts_metadata.exists? artifacts? && artifacts_metadata.exists?
end end
......
- path_to_file = file_project_job_artifacts_path(@project, @build, path: file.path) if @build.downloadable_single_artifacts_file? - path_to_file = file_project_job_artifacts_path(@project, @build, path: file.path)
%tr.tree-item{ 'data-link' => path_to_file } %tr.tree-item{ 'data-link' => path_to_file }
- blob = file.blob - blob = file.blob
%td.tree-item-file-name %td.tree-item-file-name
= tree_icon('file', blob.mode, blob.name) = tree_icon('file', blob.mode, blob.name)
%span.str-truncated %span.str-truncated
- if path_to_file = link_to file.name, path_to_file
= link_to file.name, path_to_file
- else
= file.name
%td %td
= number_to_human_size(blob.size, precision: 2) = number_to_human_size(blob.size, precision: 2)
---
title: Improve the performance of the project list API
merge_request: 12679
author:
---
title: All artifacts are now browsable
merge_request:
author:
...@@ -573,12 +573,20 @@ module API ...@@ -573,12 +573,20 @@ module API
class ProjectWithAccess < Project class ProjectWithAccess < Project
expose :permissions do expose :permissions do
expose :project_access, using: Entities::ProjectAccess do |project, options| expose :project_access, using: Entities::ProjectAccess do |project, options|
project.project_members.find_by(user_id: options[:current_user].id) if options.key?(:project_members)
(options[:project_members] || []).find { |member| member.source_id == project.id }
else
project.project_members.find_by(user_id: options[:current_user].id)
end
end end
expose :group_access, using: Entities::GroupAccess do |project, options| expose :group_access, using: Entities::GroupAccess do |project, options|
if project.group if project.group
project.group.group_members.find_by(user_id: options[:current_user].id) if options.key?(:group_members)
(options[:group_members] || []).find { |member| member.source_id == project.namespace_id }
else
project.group.group_members.find_by(user_id: options[:current_user].id)
end
end end
end end
end end
......
...@@ -71,6 +71,7 @@ module API ...@@ -71,6 +71,7 @@ module API
optional :with_merge_requests_enabled, type: Boolean, default: false, desc: 'Limit by enabled merge requests feature' optional :with_merge_requests_enabled, type: Boolean, default: false, desc: 'Limit by enabled merge requests feature'
end end
<<<<<<< HEAD
params :create_params do params :create_params do
optional :namespace_id, type: Integer, desc: 'Namespace ID for the new project. Default to the user namespace.' optional :namespace_id, type: Integer, desc: 'Namespace ID for the new project. Default to the user namespace.'
optional :import_url, type: String, desc: 'URL from which the project is imported' optional :import_url, type: String, desc: 'URL from which the project is imported'
...@@ -91,6 +92,32 @@ module API ...@@ -91,6 +92,32 @@ module API
options[:with] = Entities::BasicProjectDetails if params[:simple] options[:with] = Entities::BasicProjectDetails if params[:simple]
present paginate(projects), options present paginate(projects), options
=======
def present_projects(options = {})
projects = ProjectsFinder.new(current_user: current_user, params: project_finder_params).execute
projects = reorder_projects(projects)
projects = projects.with_statistics if params[:statistics]
projects = projects.with_issues_enabled if params[:with_issues_enabled]
projects = projects.with_merge_requests_enabled if params[:with_merge_requests_enabled]
if current_user
projects = projects.includes(:route, :taggings, namespace: :route)
project_members = current_user.project_members
group_members = current_user.group_members
end
options = options.reverse_merge(
with: current_user ? Entities::ProjectWithAccess : Entities::BasicProjectDetails,
statistics: params[:statistics],
project_members: project_members,
group_members: group_members,
current_user: current_user
)
options[:with] = Entities::BasicProjectDetails if params[:simple]
present paginate(projects), options
end
>>>>>>> upstream/master
end end
end end
......
...@@ -143,32 +143,6 @@ describe Ci::Build, :models do ...@@ -143,32 +143,6 @@ describe Ci::Build, :models do
end end
end end
describe '#downloadable_single_artifacts_file?' do
let(:build) { create(:ci_build, :artifacts, artifacts_file_store: store) }
subject { build.downloadable_single_artifacts_file? }
before do
expect_any_instance_of(Ci::Build).to receive(:artifacts_metadata?).and_call_original
end
context 'artifacts are stored locally' do
let(:store) { ObjectStoreUploader::LOCAL_STORE }
it { is_expected.to be_truthy }
end
context 'artifacts are stored remotely' do
let(:store) { ObjectStoreUploader::REMOTE_STORE }
before do
stub_artifacts_object_storage
end
it { is_expected.to be_falsey }
end
end
describe '#artifacts_expired?' do describe '#artifacts_expired?' do
subject { build.artifacts_expired? } subject { build.artifacts_expired? }
......
...@@ -52,6 +52,24 @@ describe API::Projects do ...@@ -52,6 +52,24 @@ describe API::Projects do
end end
end end
shared_examples_for 'projects response without N + 1 queries' do
it 'avoids N + 1 queries' do
control_count = ActiveRecord::QueryRecorder.new do
get api('/projects', current_user)
end.count
if defined?(additional_project)
additional_project
else
create(:empty_project, :public)
end
expect do
get api('/projects', current_user)
end.not_to exceed_query_limit(control_count + 8)
end
end
let!(:public_project) { create(:empty_project, :public, name: 'public_project') } let!(:public_project) { create(:empty_project, :public, name: 'public_project') }
before do before do
project project
...@@ -62,9 +80,13 @@ describe API::Projects do ...@@ -62,9 +80,13 @@ describe API::Projects do
context 'when unauthenticated' do context 'when unauthenticated' do
it_behaves_like 'projects response' do it_behaves_like 'projects response' do
let(:filter) { {} } let(:filter) { { search: project.name } }
let(:current_user) { user }
let(:projects) { [project] }
end
it_behaves_like 'projects response without N + 1 queries' do
let(:current_user) { nil } let(:current_user) { nil }
let(:projects) { [public_project] }
end end
end end
...@@ -75,6 +97,21 @@ describe API::Projects do ...@@ -75,6 +97,21 @@ describe API::Projects do
let(:projects) { [public_project, project, project2, project3] } let(:projects) { [public_project, project, project2, project3] }
end end
it_behaves_like 'projects response without N + 1 queries' do
let(:current_user) { user }
end
context 'when some projects are in a group' do
before do
create(:empty_project, :public, group: create(:group))
end
it_behaves_like 'projects response without N + 1 queries' do
let(:current_user) { user }
let(:additional_project) { create(:empty_project, :public, group: create(:group)) }
end
end
it 'includes the project labels as the tag_list' do it 'includes the project labels as the tag_list' do
get api('/projects', user) get api('/projects', user)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment