diff options
author | Nick Thomas <nick@gitlab.com> | 2018-08-14 22:29:59 +0100 |
---|---|---|
committer | Nick Thomas <nick@gitlab.com> | 2018-08-15 07:38:18 +0100 |
commit | d3490f6998b13a6f74af9b6f35a28c115a25143e (patch) | |
tree | fded45a6210b94d9ca772cc13529078c6dccaa63 | |
parent | ffd164d27f674b554fdffbffa828a9715c93ee60 (diff) | |
download | gitlab-ce-d3490f6998b13a6f74af9b6f35a28c115a25143e.tar.gz |
Introduce a LicenseTemplate model and LicenseTemplateFinder helper
-rw-r--r-- | app/finders/license_template_finder.rb | 36 | ||||
-rw-r--r-- | app/models/license_template.rb | 53 | ||||
-rw-r--r-- | spec/finders/license_template_finder_spec.rb | 49 | ||||
-rw-r--r-- | spec/models/license_template_spec.rb | 59 |
4 files changed, 197 insertions, 0 deletions
diff --git a/app/finders/license_template_finder.rb b/app/finders/license_template_finder.rb new file mode 100644 index 00000000000..fad33f0eca2 --- /dev/null +++ b/app/finders/license_template_finder.rb @@ -0,0 +1,36 @@ +# LicenseTemplateFinder +# +# Used to find license templates, which may come from a variety of external +# sources +# +# Arguments: +# popular: boolean. When set to true, only "popular" licenses are shown. When +# false, all licenses except popular ones are shown. When nil (the +# default), *all* licenses will be shown. +class LicenseTemplateFinder + attr_reader :params + + def initialize(params = {}) + @params = params + end + + def execute + Licensee::License.all(featured: popular_only?).map do |license| + LicenseTemplate.new( + id: license.key, + name: license.name, + nickname: license.nickname, + category: (license.featured? ? :Popular : :Other), + content: license.content, + url: license.url, + meta: license.meta + ) + end + end + + private + + def popular_only? + params.fetch(:popular, nil) + end +end diff --git a/app/models/license_template.rb b/app/models/license_template.rb new file mode 100644 index 00000000000..0ad75b27827 --- /dev/null +++ b/app/models/license_template.rb @@ -0,0 +1,53 @@ +class LicenseTemplate + PROJECT_TEMPLATE_REGEX = + %r{[\<\{\[] + (project|description| + one\sline\s.+\swhat\sit\sdoes\.) # matching the start and end is enough here + [\>\}\]]}xi.freeze + YEAR_TEMPLATE_REGEX = /[<{\[](year|yyyy)[>}\]]/i.freeze + FULLNAME_TEMPLATE_REGEX = + %r{[\<\{\[] + (fullname|name\sof\s(author|copyright\sowner)) + [\>\}\]]}xi.freeze + + attr_reader :id, :name, :category, :nickname, :url, :meta + + alias_method :key, :id + + def initialize(id:, name:, category:, content:, nickname: nil, url: nil, meta: {}) + @id = id + @name = name + @category = category + @content = content + @nickname = nickname + @url = url + @meta = meta + end + + def popular? + category == :Popular + end + alias_method :featured?, :popular? + + # Returns the text of the license + def content + if @content.respond_to?(:call) + @content = @content.call + else + @content + end + end + + # Populate placeholders in the LicenseTemplate content + def resolve!(project_name: nil, fullname: nil, year: Time.now.year.to_s) + # Ensure the string isn't shared with any other instance of LicenseTemplate + new_content = content.dup + new_content.gsub!(YEAR_TEMPLATE_REGEX, year) if year.present? + new_content.gsub!(PROJECT_TEMPLATE_REGEX, project_name) if project_name.present? + new_content.gsub!(FULLNAME_TEMPLATE_REGEX, fullname) if fullname.present? + + @content = new_content + + self + end +end diff --git a/spec/finders/license_template_finder_spec.rb b/spec/finders/license_template_finder_spec.rb new file mode 100644 index 00000000000..a97903103c9 --- /dev/null +++ b/spec/finders/license_template_finder_spec.rb @@ -0,0 +1,49 @@ +require 'spec_helper' + +describe LicenseTemplateFinder do + describe '#execute' do + subject(:result) { described_class.new(params).execute } + + let(:categories) { categorised_licenses.keys } + let(:categorised_licenses) { result.group_by(&:category) } + + context 'popular: true' do + let(:params) { { popular: true } } + + it 'only returns popular licenses' do + expect(categories).to contain_exactly(:Popular) + expect(categorised_licenses[:Popular]).to be_present + end + end + + context 'popular: false' do + let(:params) { { popular: false } } + + it 'only returns unpopular licenses' do + expect(categories).to contain_exactly(:Other) + expect(categorised_licenses[:Other]).to be_present + end + end + + context 'popular: nil' do + let(:params) { { popular: nil } } + + it 'returns all licenses known by the Licensee gem' do + from_licensee = Licensee::License.all.map { |l| l.key } + + expect(result.map(&:id)).to match_array(from_licensee) + end + + it 'correctly copies all attributes' do + licensee = Licensee::License.all.first + found = result.find { |r| r.key == licensee.key } + + aggregate_failures do + %i[key name content nickname url meta featured?].each do |k| + expect(found.public_send(k)).to eq(licensee.public_send(k)) + end + end + end + end + end +end diff --git a/spec/models/license_template_spec.rb b/spec/models/license_template_spec.rb new file mode 100644 index 00000000000..c633e1908d4 --- /dev/null +++ b/spec/models/license_template_spec.rb @@ -0,0 +1,59 @@ +require 'spec_helper' + +describe LicenseTemplate do + describe '#content' do + it 'calls a proc exactly once if provided' do + lazy = build_template(-> { 'bar' }) + content = lazy.content + + expect(content).to eq('bar') + expect(content.object_id).to eq(lazy.content.object_id) + + content.replace('foo') + expect(lazy.content).to eq('foo') + end + + it 'returns a string if provided' do + lazy = build_template('bar') + + expect(lazy.content).to eq('bar') + end + end + + describe '#resolve!' do + let(:content) do + <<~TEXT + Pretend License + + [project] + + Copyright (c) [year] [fullname] + TEXT + end + + let(:expected) do + <<~TEXT + Pretend License + + Foo Project + + Copyright (c) 1985 Nick Thomas + TEXT + end + + let(:template) { build_template(content) } + + it 'updates placeholders in a copy of the template content' do + expect(template.content.object_id).to eq(content.object_id) + + template.resolve!(project_name: "Foo Project", fullname: "Nick Thomas", year: "1985") + + expect(template.content).to eq(expected) + expect(template.content.object_id).not_to eq(content.object_id) + end + end + + def build_template(content) + described_class.new(id: 'foo', name: 'foo', category: :Other, content: content) + end +end |