summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/finders/template_finder.rb37
-rw-r--r--app/helpers/blob_helper.rb29
-rw-r--r--lib/api/templates.rb13
-rw-r--r--lib/gitlab/template/base_template.rb8
-rw-r--r--spec/factories/projects.rb27
-rw-r--r--spec/finders/template_finder_spec.rb48
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