diff --git a/app/controllers/projects/settings/repository_controller.rb b/app/controllers/projects/settings/repository_controller.rb index 9bb71de9f83d60988af1e19e478c8e8667e15b25..5410b56b45770ef2f1c749f84b120e596346b8c7 100644 --- a/app/controllers/projects/settings/repository_controller.rb +++ b/app/controllers/projects/settings/repository_controller.rb @@ -3,6 +3,8 @@ module Projects module Settings class RepositoryController < Projects::ApplicationController + include Gitlab::Utils::StrongMemoize + layout 'project_settings' before_action :authorize_admin_project! before_action :define_variables, only: [:create_deploy_token] @@ -87,18 +89,30 @@ def define_variables @deploy_keys = DeployKeysPresenter.new(@project, current_user: current_user) define_deploy_token_variables + tag_names + branch_names define_protected_refs remote_mirror end + def tag_names + @project.repository.tag_names + end + strong_memoize_attr :tag_names + + def branch_names + @project.repository.branch_names + end + strong_memoize_attr :branch_names + # rubocop: disable CodeReuse/ActiveRecord def define_protected_refs @protected_branches = fetch_protected_branches(@project).preload_access_levels @protected_tags = @project.protected_tags.preload_access_levels.order(:name).page(pagination_params[:page]) @protected_branch = @project.protected_branches.new @protected_tag = @project.protected_tags.new + @protected_tags_count = @protected_tags.reduce(0) { |sum, tag| sum + tag.matching(tag_names).size } - @protected_tags_count = @protected_tags.reduce(0) { |sum, tag| sum + tag.matching(@project.repository.tag_names).size } load_gon_index end # rubocop: enable CodeReuse/ActiveRecord @@ -139,11 +153,11 @@ def project_params_attributes end def protectable_tags_for_dropdown - { open_tags: ProtectableDropdown.new(@project, :tags).hash } + { open_tags: ProtectableDropdown.new(@project, :tags, ref_names: tag_names).array } end def protectable_branches_for_dropdown - { open_branches: ProtectableDropdown.new(@project, :branches).hash } + { open_branches: ProtectableDropdown.new(@project, :branches, ref_names: branch_names).array } end def define_deploy_token_variables diff --git a/app/models/protectable_dropdown.rb b/app/models/protectable_dropdown.rb index 855876f2ec905874346878af13c366ccc54c2d74..7e5c760bbbc684277a4d1ead1770605d5cc7380d 100644 --- a/app/models/protectable_dropdown.rb +++ b/app/models/protectable_dropdown.rb @@ -7,11 +7,12 @@ class ProtectableDropdown tags: :tag_names }.freeze - def initialize(project, ref_type) + def initialize(project, ref_type, ref_names: nil) raise ArgumentError, "invalid ref type `#{ref_type}`" unless ref_type.in?(REF_TYPES) @project = project @ref_type = ref_type + @ref_names = ref_names.presence || get_ref_names end # Tags/branches which are yet to be individually protected @@ -21,13 +22,15 @@ def protectable_ref_names @protectable_ref_names ||= ref_names - non_wildcard_protected_ref_names end - def hash + def array protectable_ref_names.map { |ref_name| { text: ref_name, id: ref_name, title: ref_name } } end private - def ref_names + attr_reader :ref_names + + def get_ref_names @project.repository.public_send(ref_name_method) # rubocop:disable GitlabSecurity/PublicSend end diff --git a/app/views/projects/protected_tags/shared/_protected_tag.html.haml b/app/views/projects/protected_tags/shared/_protected_tag.html.haml index a801dc1d65d11f94f2632411c373bc014591a2af..f855ca5424aaa8420c0c4b4e37f12a8a25b9ea36 100644 --- a/app/views/projects/protected_tags/shared/_protected_tag.html.haml +++ b/app/views/projects/protected_tags/shared/_protected_tag.html.haml @@ -6,7 +6,7 @@ = gl_badge_tag s_('ProtectedTags|default'), variant: :info, class: 'gl-ml-2' %td{ data: { label: s_('ProtectedBranch|Last commit') }, class: '!gl-align-middle' } - if protected_tag.wildcard? - - matching_tags = protected_tag.matching(repository.tag_names) + - matching_tags = protected_tag.matching(@tag_names) = link_to pluralize(matching_tags.count, "matching tag"), project_protected_tag_path(@project, protected_tag) - else - if commit = protected_tag.commit diff --git a/app/views/protected_branches/shared/_protected_branch.html.haml b/app/views/protected_branches/shared/_protected_branch.html.haml index 06ee3c26811abbe66925cd74730f558ad23c8657..7e213fe152b4b8ca49f0635319b8c7e7224bd546 100644 --- a/app/views/protected_branches/shared/_protected_branch.html.haml +++ b/app/views/protected_branches/shared/_protected_branch.html.haml @@ -12,7 +12,7 @@ = gl_badge_tag s_('ProtectedBranch|default'), variant: :info - if protected_branch.wildcard? - - matching_branches = protected_branch.matching(repository.branch_names) + - matching_branches = protected_branch.matching(@branch_names) = link_to pluralize(matching_branches.count, "matching branch"), namespace_project_protected_branch_path(@project.namespace, @project, protected_branch) - elsif !protected_branch.commit %span.gl-text-subtle= s_('ProtectedBranch|Branch does not exist.') diff --git a/spec/models/protectable_dropdown_spec.rb b/spec/models/protectable_dropdown_spec.rb index a256f9e0ab16cab79b7c3b22e96510618fdd31c8..ed26c27e0cb3c688fe684a45da60282da6566c92 100644 --- a/spec/models/protectable_dropdown_spec.rb +++ b/spec/models/protectable_dropdown_spec.rb @@ -70,8 +70,8 @@ end end - describe '#hash' do - subject { dropdown.hash } + describe '#array' do + subject { dropdown.array } context 'for branches' do let(:ref_type) { :branches } diff --git a/spec/requests/projects/settings/repository_controller_spec.rb b/spec/requests/projects/settings/repository_controller_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..ff04e43c4959eeab1fef3a464f8aa8700aeea356 --- /dev/null +++ b/spec/requests/projects/settings/repository_controller_spec.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Projects::Settings::RepositoryController, feature_category: :source_code_management do + let_it_be(:project) { create(:project, :repository) } + let_it_be(:user) { create(:user, maintainer_of: project) } + + before do + sign_in(user) + end + + describe 'GET #show' do + before do + allow(Project).to receive(:find_by_full_path).and_return(project) + end + + it 'renders the show template successfully' do + get project_settings_repository_path(project) + + expect(response).to have_gitlab_http_status(:ok) + expect(response).to render_template(:show) + end + + it 'memoizes tag_names call' do + expect(project.repository).to receive(:tag_names).once.and_call_original + + get project_settings_repository_path(project) + end + + it 'memoizes branch_names call' do + expect(project.repository).to receive(:branch_names).once.and_call_original + + get project_settings_repository_path(project) + end + end +end