diff options
| -rw-r--r-- | app/finders/template_finder.rb | 37 | ||||
| -rw-r--r-- | app/helpers/blob_helper.rb | 29 | ||||
| -rw-r--r-- | lib/api/templates.rb | 13 | ||||
| -rw-r--r-- | lib/gitlab/template/base_template.rb | 8 | ||||
| -rw-r--r-- | spec/factories/projects.rb | 27 | ||||
| -rw-r--r-- | spec/finders/template_finder_spec.rb | 48 |
6 files changed, 139 insertions, 23 deletions
diff --git a/app/finders/template_finder.rb b/app/finders/template_finder.rb new file mode 100644 index 00000000000..ea0251bffb6 --- /dev/null +++ b/app/finders/template_finder.rb @@ -0,0 +1,37 @@ +class TemplateFinder + VENDORED_TEMPLATES = { + dockerfiles: ::Gitlab::Template::DockerfileTemplate, + gitignores: ::Gitlab::Template::GitignoreTemplate, + gitlab_ci_ymls: ::Gitlab::Template::GitlabCiYmlTemplate + }.freeze + + class << self + def build(type, params = {}) + if type == :licenses + LicenseTemplateFinder.new(params) + else + new(type, params) + end + end + end + + attr_reader :type, :params + + attr_reader :vendored_templates + private :vendored_templates + + def initialize(type, params = {}) + @type = type + @params = params + + @vendored_templates = VENDORED_TEMPLATES.fetch(type) + end + + def execute + if params[:name] + vendored_templates.find(params[:name]) + else + vendored_templates.all + end + end +end diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index 00ebafd177b..96f7415ae98 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -158,32 +158,35 @@ module BlobHelper end def licenses_for_select - return @licenses_for_select if defined?(@licenses_for_select) - - grouped_licenses = LicenseTemplateFinder.new.execute.group_by(&:category) - categories = grouped_licenses.keys - - @licenses_for_select = categories.each_with_object({}) do |category, hash| - hash[category] = grouped_licenses[category].map do |license| - { name: license.name, id: license.id } - end - end + @licenses_for_select ||= template_dropdown_names(TemplateFinder.build(:licenses).execute) end def ref_project @ref_project ||= @target_project || @project end + def template_dropdown_names(items) + grouped = items.group_by(&:category) + categories = grouped.keys + + categories.each_with_object({}) do |category, hash| + hash[category] = grouped[category].map do |item| + { name: item.name, id: item.id } + end + end + end + private :template_dropdown_names + def gitignore_names - @gitignore_names ||= Gitlab::Template::GitignoreTemplate.dropdown_names + @gitignore_names ||= template_dropdown_names(TemplateFinder.build(:gitignores).execute) end def gitlab_ci_ymls - @gitlab_ci_ymls ||= Gitlab::Template::GitlabCiYmlTemplate.dropdown_names(params[:context]) + @gitlab_ci_ymls ||= template_dropdown_names(TemplateFinder.build(:gitlab_ci_ymls).execute) end def dockerfile_names - @dockerfile_names ||= Gitlab::Template::DockerfileTemplate.dropdown_names + @dockerfile_names ||= template_dropdown_names(TemplateFinder.build(:dockerfiles).execute) end def blob_editor_paths diff --git a/lib/api/templates.rb b/lib/api/templates.rb index 927baaea652..7bf0e0f5934 100644 --- a/lib/api/templates.rb +++ b/lib/api/templates.rb @@ -4,15 +4,12 @@ module API GLOBAL_TEMPLATE_TYPES = { gitignores: { - klass: Gitlab::Template::GitignoreTemplate, gitlab_version: 8.8 }, gitlab_ci_ymls: { - klass: Gitlab::Template::GitlabCiYmlTemplate, gitlab_version: 8.9 }, dockerfiles: { - klass: Gitlab::Template::DockerfileTemplate, gitlab_version: 8.15 } }.freeze @@ -36,7 +33,7 @@ module API popular = declared(params)[:popular] popular = to_boolean(popular) if popular.present? - templates = LicenseTemplateFinder.new(popular: popular).execute + templates = TemplateFinder.build(:licenses, popular: popular).execute present paginate(::Kaminari.paginate_array(templates)), with: ::API::Entities::License end @@ -49,7 +46,7 @@ module API requires :name, type: String, desc: 'The name of the template' end get "templates/licenses/:name", requirements: { name: /[\w\.-]+/ } do - templates = LicenseTemplateFinder.new.execute + templates = TemplateFinder.build(:licenses).execute template = templates.find { |template| template.key == params[:name] } not_found!('License') unless template.present? @@ -63,7 +60,6 @@ module API end GLOBAL_TEMPLATE_TYPES.each do |template_type, properties| - klass = properties[:klass] gitlab_version = properties[:gitlab_version] desc 'Get the list of the available template' do @@ -74,7 +70,7 @@ module API use :pagination end get "templates/#{template_type}" do - templates = ::Kaminari.paginate_array(klass.all) + templates = ::Kaminari.paginate_array(TemplateFinder.new(template_type).execute) present paginate(templates), with: Entities::TemplatesList end @@ -86,7 +82,8 @@ module API requires :name, type: String, desc: 'The name of the template' end get "templates/#{template_type}/:name" do - new_template = klass.find(declared(params)[:name]) + finder = TemplateFinder.build(template_type, name: declared(params)[:name]) + new_template = finder.execute render_response(template_type, new_template) end diff --git a/lib/gitlab/template/base_template.rb b/lib/gitlab/template/base_template.rb index 7393574ac13..3770f3f250b 100644 --- a/lib/gitlab/template/base_template.rb +++ b/lib/gitlab/template/base_template.rb @@ -1,14 +1,18 @@ module Gitlab module Template class BaseTemplate - def initialize(path, project = nil) + attr_reader :category + + def initialize(path, project = nil, category: nil) @path = path + @category = category @finder = self.class.finder(project) end def name File.basename(@path, self.class.extension) end + alias_method :id, :name def content @finder.read(@path) @@ -62,7 +66,7 @@ module Gitlab directory = category_directory(category) files = finder(project).list_files_for(directory) - files.map { |f| new(f, project) }.sort + files.map { |f| new(f, project, category: category) }.sort end def category_directory(category) diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index 1215b04913e..17e457c04a5 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -130,6 +130,33 @@ FactoryBot.define do end end + # Build a custom repository by specifying a hash of `filename => content` in + # the transient `files` attribute. Each file will be created in its own + # commit, operating against the master branch. So, the following call: + # + # create(:project, :custom_repo, files: { 'foo/a.txt' => 'foo', 'b.txt' => bar' }) + # + # will create a repository containing two files, and two commits, in master + trait :custom_repo do + transient do + files {} + end + + after :create do |project, evaluator| + raise "Failed to create repository!" unless project.create_repository + + evaluator.files.each do |filename, content| + project.repository.create_file( + project.creator, + filename, + content, + message: "Automatically created file #{filename}", + branch_name: 'master' + ) + end + end + end + # Test repository - https://gitlab.com/gitlab-org/gitlab-test trait :repository do test_repo diff --git a/spec/finders/template_finder_spec.rb b/spec/finders/template_finder_spec.rb new file mode 100644 index 00000000000..1d399e8194f --- /dev/null +++ b/spec/finders/template_finder_spec.rb @@ -0,0 +1,48 @@ +require 'spec_helper' + +describe TemplateFinder do + using RSpec::Parameterized::TableSyntax + + describe '#build' do + where(:type, :expected_class) do + :dockerfiles | described_class + :gitignores | described_class + :gitlab_ci_ymls | described_class + :licenses | ::LicenseTemplateFinder + end + + with_them do + subject { described_class.build(type) } + + it { is_expected.to be_a(expected_class) } + end + end + + describe '#execute' do + where(:type, :vendored_name) do + :dockerfiles | 'Binary' + :gitignores | 'Actionscript' + :gitlab_ci_ymls | 'Android' + end + + with_them do + it 'returns all vendored templates when no name is specified' do + result = described_class.new(type).execute + + expect(result).to include(have_attributes(name: vendored_name)) + end + + it 'returns only the specified vendored template when a name is specified' do + result = described_class.new(type, name: vendored_name).execute + + expect(result).to have_attributes(name: vendored_name) + end + + it 'returns nil when an unknown name is specified' do + result = described_class.new(type, name: 'unknown').execute + + expect(result).to be_nil + end + end + end +end |
