summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Davydov <antondavydov.o@gmail.com>2016-03-01 15:36:50 +0300
committerRémy Coutable <remy@rymai.me>2016-04-18 14:47:50 +0200
commit073c3d15c71a0f877b62c7d3d7417a9721da1dba (patch)
tree83dd1a990857e54ebd91f6ef3f6494e51cdd0f47
parent06952aaf24633550f57fd54b70d27732509935c2 (diff)
downloadgitlab-ce-073c3d15c71a0f877b62c7d3d7417a9721da1dba.tar.gz
Initial implementation if license template selector and /licenses/:key API endpoint
-rw-r--r--Gemfile3
-rw-r--r--Gemfile.lock3
-rw-r--r--app/assets/javascripts/api.js.coffee13
-rw-r--r--app/assets/javascripts/blob/blob_license_selector.js.coffee24
-rw-r--r--app/assets/stylesheets/pages/editor.scss9
-rw-r--r--app/controllers/projects/blob_controller.rb9
-rw-r--r--app/helpers/projects_helper.rb7
-rw-r--r--app/views/projects/blob/_editor.html.haml11
-rw-r--r--app/views/projects/empty.html.haml6
-rw-r--r--lib/api/api.rb1
-rw-r--r--lib/api/licenses.rb27
-rw-r--r--spec/requests/api/licenses_spec.rb46
12 files changed, 156 insertions, 3 deletions
diff --git a/Gemfile b/Gemfile
index 199ef65d922..ca4157cf47d 100644
--- a/Gemfile
+++ b/Gemfile
@@ -190,6 +190,9 @@ gem 'babosa', '~> 1.0.2'
# Sanitizes SVG input
gem "loofah", "~> 2.0.3"
+# Working with license
+gem 'licensee', "~> 7.0.0"
+
# Protect against bruteforcing
gem "rack-attack", '~> 4.3.1'
diff --git a/Gemfile.lock b/Gemfile.lock
index ad7d7c18559..2a6faeff2f4 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -452,6 +452,8 @@ GEM
addressable (~> 2.3)
letter_opener (1.1.2)
launchy (~> 2.2)
+ licensee (7.0.0)
+ rugged (~> 0.23)
listen (3.0.5)
rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9)
@@ -957,6 +959,7 @@ DEPENDENCIES
jquery-ui-rails (~> 5.0.0)
kaminari (~> 0.16.3)
letter_opener (~> 1.1.2)
+ licensee (~> 7.0.0)
loofah (~> 2.0.3)
mail_room (~> 0.6.1)
method_source (~> 0.8)
diff --git a/app/assets/javascripts/api.js.coffee b/app/assets/javascripts/api.js.coffee
index f3ed9a66715..f4757658d54 100644
--- a/app/assets/javascripts/api.js.coffee
+++ b/app/assets/javascripts/api.js.coffee
@@ -5,6 +5,7 @@
group_projects_path: "/api/:version/groups/:id/projects.json"
projects_path: "/api/:version/projects.json"
labels_path: "/api/:version/projects/:id/labels"
+ license_path: "/api/:version/licenses/:key"
group: (group_id, callback) ->
url = Api.buildUrl(Api.group_path)
@@ -92,6 +93,18 @@
).done (projects) ->
callback(projects)
+ # Return text for specific license
+ licenseText: (key, fullname, callback) ->
+ url = Api.buildUrl(Api.license_path)
+ url = url.replace(':key', key)
+
+ $.ajax(
+ url: url
+ data:
+ fullname: fullname
+ ).done (projects) ->
+ callback(projects)
+
buildUrl: (url) ->
url = gon.relative_url_root + url if gon.relative_url_root?
return url.replace(':version', gon.api_version)
diff --git a/app/assets/javascripts/blob/blob_license_selector.js.coffee b/app/assets/javascripts/blob/blob_license_selector.js.coffee
new file mode 100644
index 00000000000..b43c1ec2bb5
--- /dev/null
+++ b/app/assets/javascripts/blob/blob_license_selector.js.coffee
@@ -0,0 +1,24 @@
+class @BlobLicenseSelector
+ licenseRegex: /^(.+\/)?(licen[sc]e|copying)($|\.)/i
+
+ constructor: (editor)->
+ self = this
+ @licenseSelector = $('.js-license-selector')
+ @toggleLicenseSelector($('#file_name').val())
+
+ $('#file_name').on 'input', ->
+ self.toggleLicenseSelector($(this).val())
+
+ $('select.license-select').select2(
+ width: 'resolve'
+ dropdownAutoWidth: true
+ placeholder: 'Choose a license template'
+ ).on 'change', (e) ->
+ Api.licenseText $(this).val(), $(this).data('fullname'), (data) ->
+ editor.setValue(data, -1)
+
+ toggleLicenseSelector: (fileName) =>
+ if @licenseRegex.test(fileName)
+ @licenseSelector.show()
+ else
+ @licenseSelector.hide()
diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss
index 0f0592a0ab8..8981f070a20 100644
--- a/app/assets/stylesheets/pages/editor.scss
+++ b/app/assets/stylesheets/pages/editor.scss
@@ -26,6 +26,10 @@
line-height: 42px;
padding-top: 7px;
padding-bottom: 7px;
+
+ .pull-right {
+ height: 20px;
+ }
}
.editor-ref {
@@ -53,4 +57,9 @@
.select2 {
float: right;
}
+
+ .encoding-selector,
+ .license-selector {
+ display: inline-block;
+ }
}
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index cd8b2911674..6960562d15f 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -122,6 +122,15 @@ class Projects::BlobController < Projects::ApplicationController
end
def editor_variables
+ @licenses = {
+ 'Popular' => Licensee::License.all(featured: true).map!{ |license| [license.name, license.key] },
+ 'Other' => Licensee::License.all(featured: false).map!{ |license| [license.name, license.key] }
+ }
+
+ unless @repository.empty?
+ @current_license_key = Licensee.license(@repository.path).try(:key)
+ end
+
@target_branch = params[:target_branch]
@file_path =
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 7e00aacceaa..0b0cb658b17 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -306,6 +306,13 @@ module ProjectsHelper
namespace_project_new_blob_path(@project.namespace, @project, tree_join(ref), file_name: 'README.md')
end
+ def new_license_path
+ ref = @repository.root_ref if @repository
+ ref ||= 'master'
+
+ namespace_project_new_blob_path(@project.namespace, @project, tree_join(ref), file_name: 'LICENSE')
+ end
+
def last_push_event
if current_user
current_user.recent_push(@project.id)
diff --git a/app/views/projects/blob/_editor.html.haml b/app/views/projects/blob/_editor.html.haml
index f8b6fa253c4..8ebbc91f81d 100644
--- a/app/views/projects/blob/_editor.html.haml
+++ b/app/views/projects/blob/_editor.html.haml
@@ -13,7 +13,11 @@
required: true, class: 'form-control new-file-name'
.pull-right
- = select_tag :encoding, options_for_select([ "base64", "text" ], "text"), class: 'select2'
+ .license-selector.js-license-selector.hide
+ = select_tag :license_type, grouped_options_for_select(@licenses, @current_license_key), include_blank: true, class: 'select2 license-select', data: { fullname: @repository.project.creator.name }
+
+ .encoding-selector
+ = select_tag :encoding, options_for_select([ "base64", "text" ], "text"), class: 'select2'
.file-content.code
%pre.js-edit-mode-pane#editor #{params[:content] || local_assigns[:blob_data]}
@@ -22,3 +26,8 @@
.center
%h2
%i.icon-spinner.icon-spin
+
+:javascript
+ window.onload = function() {
+ new BlobLicenseSelector(blob.editor)
+ }
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index 6ad7b05155a..2eb79703304 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -14,8 +14,10 @@
%p
If you already have files you can push them using command line instructions below.
%p
- Otherwise you can start with
- = link_to "adding README", new_readme_path, class: 'underlined-link'
+ Otherwise you can start with adding
+ = link_to "README", new_readme_path, class: 'underlined-link'
+ or
+ = link_to "LICENSE", new_license_path, class: 'underlined-link'
file to this project.
- if can?(current_user, :push_code, @project)
diff --git a/lib/api/api.rb b/lib/api/api.rb
index 7d65145176b..cc1004f8005 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -57,5 +57,6 @@ module API
mount Builds
mount Variables
mount Runners
+ mount Licenses
end
end
diff --git a/lib/api/licenses.rb b/lib/api/licenses.rb
new file mode 100644
index 00000000000..7fffbef84e4
--- /dev/null
+++ b/lib/api/licenses.rb
@@ -0,0 +1,27 @@
+module API
+ # Licenses API
+ class Licenses < Grape::API
+ YEAR_TEMPLATE_REGEX = /(\[|<|{)(year|yyyy)(\]|>|})/
+ FULLNAME_TEMPLATE_REGEX = /\[fullname\]/
+
+ # Get text for specific license
+ #
+ # Parameters:
+ # key (required) - The key of a license
+ # fullname - Reository owner fullname
+ # Example Request:
+ # GET /licenses/mit
+ get 'licenses/:key', requirements: { key: /[\w.-]*/ } do
+ env['api.format'] = :txt
+ license = Licensee::License.find(params[:key]).try(:text)
+
+ if license
+ license
+ .gsub(YEAR_TEMPLATE_REGEX, Time.now.year.to_s)
+ .gsub(FULLNAME_TEMPLATE_REGEX, params[:fullname])
+ else
+ error!('License not found', 404)
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/licenses_spec.rb b/spec/requests/api/licenses_spec.rb
new file mode 100644
index 00000000000..f0f8b041f69
--- /dev/null
+++ b/spec/requests/api/licenses_spec.rb
@@ -0,0 +1,46 @@
+require 'spec_helper'
+
+describe API::API, api: true do
+ include ApiHelpers
+ describe 'GET /licenses/:key' do
+ before(:each) do
+ get api("/licenses/#{license_type}?fullname=Anton")
+ end
+
+ context 'for mit license name' do
+ let(:license_type){ 'mit' }
+
+ it 'returns MIT license text and replases template values' do
+ expect(response.body).to include('Copyright (c) 2016 Anton')
+ expect(response.body).to include('Copyright (c) 2016')
+ end
+ end
+
+ context 'for gnu license name' do
+ let(:license_type){ 'gpl-3.0' }
+
+ it 'returns GNU license text and replases template values' do
+ expect(response.body).to include('GNU GENERAL PUBLIC LICENSE')
+ expect(response.body).to include('Copyright (C) 2016')
+ end
+ end
+
+ context 'for apache license name' do
+ let(:license_type){ 'apache-2.0' }
+
+ it 'returns Apache license text and replases template values' do
+ expect(response.body).to include('Apache License')
+ expect(response.body).to include('Copyright 2016')
+ end
+ end
+
+ context 'for mythic license name' do
+ let(:license_type){ 'muth-over9000' }
+
+ it 'returns string with error' do
+ expect(response).to have_http_status(404)
+ expect(response.body).to eq 'License not found'
+ end
+ end
+ end
+end