licensee 9.10.1 → 9.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/licensee/commands/diff.rb +2 -7
- data/lib/licensee/content_helper.rb +169 -78
- data/lib/licensee/license.rb +5 -4
- data/lib/licensee/license_field.rb +1 -1
- data/lib/licensee/matchers/cabal.rb +1 -1
- data/lib/licensee/matchers/cargo.rb +1 -1
- data/lib/licensee/matchers/copyright.rb +2 -2
- data/lib/licensee/matchers/cran.rb +3 -3
- data/lib/licensee/matchers/dist_zilla.rb +1 -1
- data/lib/licensee/matchers/gemspec.rb +5 -5
- data/lib/licensee/matchers/matcher.rb +1 -1
- data/lib/licensee/matchers/npm_bower.rb +1 -1
- data/lib/licensee/matchers/reference.rb +1 -1
- data/lib/licensee/matchers/spdx.rb +1 -1
- data/lib/licensee/project_files/license_file.rb +7 -7
- data/lib/licensee/project_files/readme_file.rb +3 -3
- data/lib/licensee/projects/github_project.rb +1 -1
- data/lib/licensee/version.rb +1 -1
- data/spec/fixtures/detect.json +2 -2
- data/spec/fixtures/license-hashes.json +36 -0
- data/spec/licensee/commands/detect_spec.rb +1 -1
- data/spec/licensee/content_helper_spec.rb +131 -32
- data/spec/licensee/license_spec.rb +1 -1
- data/spec/licensee/matchers/dice_matcher_spec.rb +2 -2
- data/spec/licensee/project_files/license_file_spec.rb +1 -1
- data/spec/spec_helper.rb +10 -5
- data/spec/vendored_license_spec.rb +19 -2
- data/vendor/choosealicense.com/_data/meta.yml +0 -4
- data/vendor/choosealicense.com/_licenses/afl-3.0.txt +0 -1
- data/vendor/choosealicense.com/_licenses/agpl-3.0.txt +0 -1
- data/vendor/choosealicense.com/_licenses/apache-2.0.txt +0 -1
- data/vendor/choosealicense.com/_licenses/artistic-2.0.txt +0 -1
- data/vendor/choosealicense.com/_licenses/bsd-2-clause.txt +8 -6
- data/vendor/choosealicense.com/_licenses/bsd-3-clause-clear.txt +0 -1
- data/vendor/choosealicense.com/_licenses/bsd-3-clause.txt +11 -9
- data/vendor/choosealicense.com/_licenses/bsl-1.0.txt +0 -1
- data/vendor/choosealicense.com/_licenses/cc-by-4.0.txt +0 -1
- data/vendor/choosealicense.com/_licenses/cc-by-sa-4.0.txt +0 -1
- data/vendor/choosealicense.com/_licenses/cc0-1.0.txt +0 -1
- data/vendor/choosealicense.com/_licenses/ecl-2.0.txt +0 -1
- data/vendor/choosealicense.com/_licenses/epl-1.0.txt +0 -1
- data/vendor/choosealicense.com/_licenses/epl-2.0.txt +0 -1
- data/vendor/choosealicense.com/_licenses/eupl-1.1.txt +0 -1
- data/vendor/choosealicense.com/_licenses/eupl-1.2.txt +0 -1
- data/vendor/choosealicense.com/_licenses/gpl-2.0.txt +0 -1
- data/vendor/choosealicense.com/_licenses/gpl-3.0.txt +1 -2
- data/vendor/choosealicense.com/_licenses/isc.txt +0 -1
- data/vendor/choosealicense.com/_licenses/lgpl-2.1.txt +0 -1
- data/vendor/choosealicense.com/_licenses/lgpl-3.0.txt +1 -2
- data/vendor/choosealicense.com/_licenses/lppl-1.3c.txt +0 -1
- data/vendor/choosealicense.com/_licenses/mit.txt +0 -1
- data/vendor/choosealicense.com/_licenses/mpl-2.0.txt +0 -1
- data/vendor/choosealicense.com/_licenses/ms-pl.txt +0 -1
- data/vendor/choosealicense.com/_licenses/ms-rl.txt +0 -1
- data/vendor/choosealicense.com/_licenses/ncsa.txt +0 -1
- data/vendor/choosealicense.com/_licenses/ofl-1.1.txt +0 -1
- data/vendor/choosealicense.com/_licenses/osl-3.0.txt +0 -1
- data/vendor/choosealicense.com/_licenses/postgresql.txt +2 -3
- data/vendor/choosealicense.com/_licenses/unlicense.txt +0 -1
- data/vendor/choosealicense.com/_licenses/upl-1.0.txt +0 -1
- data/vendor/choosealicense.com/_licenses/wtfpl.txt +0 -1
- data/vendor/choosealicense.com/_licenses/zlib.txt +0 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 613429f0350489c8dbdbdc80973d2557ad655efd2b89786096f290cf52632344
|
4
|
+
data.tar.gz: 87fca6ceddb6972dd946720355e6efb2661793d671ff92ce8934e281affa6ad5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7bcb1c30bdebf4cad0a84ef7fd9dd4afe922ba8acac1a9124bdd96dc64d4ef736787f1b70c4ab0d01c3c05ba3547300caa3c882b2d99ea15117f72335f56b0a5
|
7
|
+
data.tar.gz: bb2f30c4f70a4610f55a530c36b65852270558b8b36342b1fe8ad1113afa4dca711214545b3abbeb19cdba8d7e2d05643b0e138c8964a5b3f51106ce8c1bf3db
|
@@ -39,14 +39,9 @@ class LicenseeCLI < Thor
|
|
39
39
|
|
40
40
|
def license_to_diff
|
41
41
|
return options[:license_to_diff] if options[:license_to_diff]
|
42
|
-
return project.license_file if remote?
|
42
|
+
return project.license_file if remote? || STDIN.tty? && project.license_file
|
43
43
|
|
44
44
|
@license_to_diff ||= begin
|
45
|
-
if STDIN.tty?
|
46
|
-
error 'You must pipe license contents to the command via STDIN'
|
47
|
-
exit 1
|
48
|
-
end
|
49
|
-
|
50
45
|
Licensee::ProjectFiles::LicenseFile.new(STDIN.read, 'LICENSE')
|
51
46
|
end
|
52
47
|
end
|
@@ -58,7 +53,7 @@ class LicenseeCLI < Thor
|
|
58
53
|
if options[:license]
|
59
54
|
error "#{options[:license]} is not a valid license"
|
60
55
|
else
|
61
|
-
error '
|
56
|
+
error 'Usage: provide a license to diff against with --license (spdx name)'
|
62
57
|
end
|
63
58
|
|
64
59
|
error "Valid licenses: #{Licensee::License.all(hidden: true).map(&:key).join(', ')}"
|
@@ -4,17 +4,88 @@ require 'digest'
|
|
4
4
|
module Licensee
|
5
5
|
module ContentHelper
|
6
6
|
DIGEST = Digest::SHA1
|
7
|
-
|
8
|
-
|
7
|
+
START_REGEX = /\A\s*/.freeze
|
8
|
+
END_OF_TERMS_REGEX = /^[\s#*_]*end of terms and conditions\s*$/i.freeze
|
9
9
|
ALT_TITLE_REGEX = License::ALT_TITLE_REGEX
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
10
|
+
REGEXES = {
|
11
|
+
hrs: /^\s*[=\-\*]{3,}\s*$/,
|
12
|
+
all_rights_reserved: /#{START_REGEX}all rights reserved\.?$/i,
|
13
|
+
whitespace: /\s+/,
|
14
|
+
markdown_headings: /#{START_REGEX}#+/,
|
15
|
+
version: /#{START_REGEX}version.*$/i,
|
16
|
+
span_markup: /[_*~]+(.*?)[_*~]+/,
|
17
|
+
link_markup: /\[(.+?)\]\(.+?\)/,
|
18
|
+
block_markup: /^\s*>/,
|
19
|
+
border_markup: /^[\*-](.*?)[\*-]$/,
|
20
|
+
comment_markup: %r{^\s*?[/\*]{1,2}},
|
21
|
+
url: %r{#{START_REGEX}https?://[^ ]+\n},
|
22
|
+
bullet: /\n\n\s*(?:[*-]|\(?[\da-z]{1,2}[)\.])\s+/i,
|
23
|
+
developed_by: /#{START_REGEX}developed by:.*?\n\n/im,
|
24
|
+
quote_begin: /[`'"‘“]/,
|
25
|
+
quote_end: /[`'"’”]/
|
26
|
+
}.freeze
|
27
|
+
NORMALIZATIONS = {
|
28
|
+
lists: { from: /^\s*(?:\d\.|\*)\s+([^\n])/, to: '- \1' },
|
29
|
+
https: { from: /http:/, to: 'https:' },
|
30
|
+
ampersands: { from: '&', to: 'and' },
|
31
|
+
dashes: { from: /(?<!^)([—–-]+)(?!$)/, to: '-' },
|
32
|
+
quotes: {
|
33
|
+
from: /#{REGEXES[:quote_begin]}+([\w -]*?\w)#{REGEXES[:quote_end]}+/,
|
34
|
+
to: '"\1"'
|
35
|
+
}
|
36
|
+
}.freeze
|
37
|
+
|
38
|
+
# Legally equivalent words that schould be ignored for comparison
|
39
|
+
# See https://spdx.org/spdx-license-list/matching-guidelines
|
40
|
+
VARIETAL_WORDS = {
|
41
|
+
'acknowledgment' => 'acknowledgement',
|
42
|
+
'analogue' => 'analog',
|
43
|
+
'analyse' => 'analyze',
|
44
|
+
'artefact' => 'artifact',
|
45
|
+
'authorisation' => 'authorization',
|
46
|
+
'authorised' => 'authorized',
|
47
|
+
'calibre' => 'caliber',
|
48
|
+
'cancelled' => 'canceled',
|
49
|
+
'capitalisations' => 'capitalizations',
|
50
|
+
'catalogue' => 'catalog',
|
51
|
+
'categorise' => 'categorize',
|
52
|
+
'centre' => 'center',
|
53
|
+
'emphasised' => 'emphasized',
|
54
|
+
'favour' => 'favor',
|
55
|
+
'favourite' => 'favorite',
|
56
|
+
'fulfil' => 'fulfill',
|
57
|
+
'fulfilment' => 'fulfillment',
|
58
|
+
'initialise' => 'initialize',
|
59
|
+
'judgment' => 'judgement',
|
60
|
+
'labelling' => 'labeling',
|
61
|
+
'labour' => 'labor',
|
62
|
+
'licence' => 'license',
|
63
|
+
'maximise' => 'maximize',
|
64
|
+
'modelled' => 'modeled',
|
65
|
+
'modelling' => 'modeling',
|
66
|
+
'offence' => 'offense',
|
67
|
+
'optimise' => 'optimize',
|
68
|
+
'organisation' => 'organization',
|
69
|
+
'organise' => 'organize',
|
70
|
+
'practise' => 'practice',
|
71
|
+
'programme' => 'program',
|
72
|
+
'realise' => 'realize',
|
73
|
+
'recognise' => 'recognize',
|
74
|
+
'signalling' => 'signaling',
|
75
|
+
'sub-license' => 'sublicense',
|
76
|
+
'sub license' => 'sublicense',
|
77
|
+
'utilisation' => 'utilization',
|
78
|
+
'whilst' => 'while',
|
79
|
+
'wilful' => 'wilfull',
|
80
|
+
'non-commercial' => 'noncommercial',
|
81
|
+
'cent' => 'percent',
|
82
|
+
'owner' => 'holder'
|
83
|
+
}.freeze
|
84
|
+
STRIP_METHODS = %i[
|
85
|
+
hrs markdown_headings borders title version url copyright
|
86
|
+
block_markup span_markup link_markup
|
87
|
+
all_rights_reserved developed_by end_of_terms whitespace
|
88
|
+
].freeze
|
18
89
|
|
19
90
|
# A set of each word in the license, without duplicates
|
20
91
|
def wordset
|
@@ -60,35 +131,21 @@ module Licensee
|
|
60
131
|
# content with attribution first to detect attribuion in LicenseFile
|
61
132
|
def content_without_title_and_version
|
62
133
|
@content_without_title_and_version ||= begin
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
strip_version(string).strip
|
134
|
+
@_content = nil
|
135
|
+
ops = %i[hrs comments markdown_headings title version]
|
136
|
+
ops.each { |op| strip(op) }
|
137
|
+
_content
|
68
138
|
end
|
69
139
|
end
|
70
140
|
|
71
|
-
# Content without title, version, copyright, whitespace, or insturctions
|
72
|
-
#
|
73
|
-
# wrap - Optional width to wrap the content
|
74
|
-
#
|
75
|
-
# Returns a string
|
76
141
|
def content_normalized(wrap: nil)
|
77
|
-
return unless content
|
78
|
-
|
79
142
|
@content_normalized ||= begin
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
string, _partition, _instructions = string.partition(END_OF_TERMS_REGEX)
|
87
|
-
string = normalize_lists(string)
|
88
|
-
string = normalize_quotes(string)
|
89
|
-
string = normalize_https(string)
|
90
|
-
string = strip_markup(string)
|
91
|
-
strip_whitespace(string)
|
143
|
+
@_content = content_without_title_and_version.downcase
|
144
|
+
|
145
|
+
(NORMALIZATIONS.keys + %i[spelling bullets]).each { |op| normalize(op) }
|
146
|
+
STRIP_METHODS.each { |op| strip(op) }
|
147
|
+
|
148
|
+
_content
|
92
149
|
end
|
93
150
|
|
94
151
|
if wrap.nil?
|
@@ -98,15 +155,24 @@ module Licensee
|
|
98
155
|
end
|
99
156
|
end
|
100
157
|
|
158
|
+
# Backwards compatibalize constants to avoid a breaking change
|
159
|
+
def self.const_missing(const)
|
160
|
+
key = const.to_s.downcase.gsub('_regex', '').to_sym
|
161
|
+
REGEXES[key] || super
|
162
|
+
end
|
163
|
+
|
101
164
|
# Wrap text to the given line length
|
102
165
|
def self.wrap(text, line_width = 80)
|
103
166
|
return if text.nil?
|
104
167
|
|
105
168
|
text = text.clone
|
169
|
+
text.gsub!(REGEXES[:bullet]) { |m| "\n#{m}\n" }
|
106
170
|
text.gsub!(/([^\n])\n([^\n])/, '\1 \2')
|
107
171
|
|
108
172
|
text = text.split("\n").collect do |line|
|
109
|
-
if line
|
173
|
+
if line =~ REGEXES[:hrs]
|
174
|
+
line
|
175
|
+
elsif line.length > line_width
|
110
176
|
line.gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n").strip
|
111
177
|
else
|
112
178
|
line
|
@@ -121,79 +187,104 @@ module Licensee
|
|
121
187
|
end
|
122
188
|
|
123
189
|
def self.title_regex
|
124
|
-
|
125
|
-
|
190
|
+
@title_regex ||= begin
|
191
|
+
licenses = Licensee::License.all(hidden: true, psuedo: false)
|
192
|
+
titles = licenses.map(&:title_regex)
|
126
193
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
194
|
+
# Title regex must include the version to support matching within
|
195
|
+
# families, but for sake of normalization, we can be less strict
|
196
|
+
without_versions = licenses.map do |license|
|
197
|
+
next if license.title == license.name_without_version
|
131
198
|
|
132
|
-
|
133
|
-
|
134
|
-
|
199
|
+
Regexp.new Regexp.escape(license.name_without_version), 'i'
|
200
|
+
end
|
201
|
+
titles.concat(without_versions.compact)
|
135
202
|
|
136
|
-
|
203
|
+
/#{START_REGEX}\(?(?:the )?#{Regexp.union titles}.*?$/i
|
204
|
+
end
|
137
205
|
end
|
138
206
|
|
139
207
|
private
|
140
208
|
|
141
|
-
|
142
|
-
|
209
|
+
# rubocop:disable Naming/MemoizedInstanceVariableName
|
210
|
+
def _content
|
211
|
+
@_content ||= content.to_s.dup.strip
|
143
212
|
end
|
213
|
+
# rubocop:enable Naming/MemoizedInstanceVariableName
|
144
214
|
|
145
|
-
def
|
146
|
-
|
147
|
-
end
|
215
|
+
def strip(regex_or_sym)
|
216
|
+
return unless _content
|
148
217
|
|
149
|
-
|
150
|
-
|
218
|
+
if regex_or_sym.is_a?(Symbol)
|
219
|
+
meth = "strip_#{regex_or_sym}"
|
220
|
+
return send(meth) if respond_to?(meth, true)
|
221
|
+
|
222
|
+
unless REGEXES[regex_or_sym]
|
223
|
+
raise ArgumentError, "#{regex_or_sym} is an invalid regex reference"
|
224
|
+
end
|
225
|
+
|
226
|
+
regex_or_sym = REGEXES[regex_or_sym]
|
227
|
+
end
|
228
|
+
|
229
|
+
@_content = _content.gsub(regex_or_sym, ' ').squeeze(' ').strip
|
151
230
|
end
|
152
231
|
|
153
|
-
|
154
|
-
|
155
|
-
|
232
|
+
def strip_title
|
233
|
+
while _content =~ ContentHelper.title_regex
|
234
|
+
strip(ContentHelper.title_regex)
|
235
|
+
end
|
156
236
|
end
|
157
237
|
|
158
|
-
|
159
|
-
|
160
|
-
strip(string, MARKDOWN_HEADING_REGEX)
|
238
|
+
def strip_borders
|
239
|
+
normalize(REGEXES[:border_markup], '\1')
|
161
240
|
end
|
162
241
|
|
163
|
-
def
|
164
|
-
|
242
|
+
def strip_comments
|
243
|
+
lines = _content.split("\n")
|
244
|
+
return if lines.count == 1
|
245
|
+
return unless lines.all? { |line| line =~ REGEXES[:comment_markup] }
|
246
|
+
|
247
|
+
strip(:comment_markup)
|
165
248
|
end
|
166
249
|
|
167
|
-
def
|
168
|
-
|
250
|
+
def strip_copyright
|
251
|
+
regex = Matchers::Copyright::REGEX
|
252
|
+
strip(regex) while _content =~ regex
|
169
253
|
end
|
170
254
|
|
171
|
-
def
|
172
|
-
|
255
|
+
def strip_end_of_terms
|
256
|
+
body, _partition, _instructions = _content.partition(END_OF_TERMS_REGEX)
|
257
|
+
@_content = body
|
173
258
|
end
|
174
259
|
|
175
|
-
def
|
176
|
-
|
260
|
+
def strip_span_markup
|
261
|
+
normalize(REGEXES[:span_markup], '\1')
|
177
262
|
end
|
178
263
|
|
179
|
-
def
|
180
|
-
|
264
|
+
def strip_link_markup
|
265
|
+
normalize(REGEXES[:link_markup], '\1')
|
181
266
|
end
|
182
267
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
268
|
+
def normalize(from_or_key, to = nil)
|
269
|
+
operation = { from: from_or_key, to: to } if to
|
270
|
+
operation ||= NORMALIZATIONS[from_or_key]
|
271
|
+
|
272
|
+
if operation
|
273
|
+
@_content = _content.gsub operation[:from], operation[:to]
|
274
|
+
elsif respond_to?("normalize_#{from_or_key}", true)
|
275
|
+
send("normalize_#{from_or_key}")
|
276
|
+
else
|
277
|
+
raise ArgumentError, "#{from_or_key} is an invalid normalization"
|
278
|
+
end
|
189
279
|
end
|
190
280
|
|
191
|
-
def
|
192
|
-
|
281
|
+
def normalize_spelling
|
282
|
+
normalize(/\b#{Regexp.union(VARIETAL_WORDS.keys)}\b/, VARIETAL_WORDS)
|
193
283
|
end
|
194
284
|
|
195
|
-
def
|
196
|
-
|
285
|
+
def normalize_bullets
|
286
|
+
normalize(REGEXES[:bullet], "\n\n* ")
|
287
|
+
normalize(/\)\s+\(/, ')(')
|
197
288
|
end
|
198
289
|
end
|
199
290
|
end
|
data/lib/licensee/license.rb
CHANGED
@@ -23,6 +23,7 @@ module Licensee
|
|
23
23
|
output = licenses.dup
|
24
24
|
output.reject!(&:hidden?) unless options[:hidden]
|
25
25
|
output.reject!(&:pseudo_license?) unless options[:pseudo]
|
26
|
+
output.sort_by!(&:key)
|
26
27
|
return output if options[:featured].nil?
|
27
28
|
|
28
29
|
output.select { |l| l.featured? == options[:featured] }
|
@@ -95,8 +96,8 @@ module Licensee
|
|
95
96
|
'bsd-3-clause-clear' => /(?:clear bsd|bsd 3-clause(?: clear)?)/i
|
96
97
|
}.freeze
|
97
98
|
|
98
|
-
SOURCE_PREFIX = %r{https?://(?:www\.)?}i
|
99
|
-
SOURCE_SUFFIX = %r{(?:\.html?|\.txt|\/)(?:\?[^\s]*)?}i
|
99
|
+
SOURCE_PREFIX = %r{https?://(?:www\.)?}i.freeze
|
100
|
+
SOURCE_SUFFIX = %r{(?:\.html?|\.txt|\/)(?:\?[^\s]*)?}i.freeze
|
100
101
|
|
101
102
|
HASH_METHODS = %i[
|
102
103
|
key spdx_id meta url rules fields other? gpl? lgpl? cc?
|
@@ -145,11 +146,11 @@ module Licensee
|
|
145
146
|
title_regex ||= begin
|
146
147
|
string = name.downcase.sub('*', 'u')
|
147
148
|
string.sub!(/\Athe /i, '')
|
148
|
-
string.sub!(/ license\z/i, '')
|
149
149
|
string.sub!(/,? version /, ' ')
|
150
150
|
string.sub!(/v(\d+\.\d+)/, '\1')
|
151
151
|
string = Regexp.escape(string)
|
152
|
-
string = string.sub(/
|
152
|
+
string = string.sub(/\\ licen[sc]e/i, '(?:\ licen[sc]e)?')
|
153
|
+
string = string.sub(/\\ (\d+\\.\d+)/, ',?\s+(?:version\ |v(?:\. )?)?\1')
|
153
154
|
string = string.sub(/\bgnu\\ /, '(?:GNU )?')
|
154
155
|
Regexp.new string, 'i'
|
155
156
|
end
|
@@ -3,7 +3,7 @@ module Licensee
|
|
3
3
|
class Cabal < Licensee::Matchers::Package
|
4
4
|
# While we could parse the cabal file, prefer
|
5
5
|
# a lenient regex for speed and security. Moar parsing moar problems.
|
6
|
-
LICENSE_REGEX = /^\s*license\s*\:\s*([a-z\-0-9\.]+)\s*$/ix
|
6
|
+
LICENSE_REGEX = /^\s*license\s*\:\s*([a-z\-0-9\.]+)\s*$/ix.freeze
|
7
7
|
|
8
8
|
private
|
9
9
|
|
@@ -5,12 +5,12 @@ module Licensee
|
|
5
5
|
|
6
6
|
# rubocop:disable Metrics/LineLength
|
7
7
|
COPYRIGHT_SYMBOLS = Regexp.union([/copyright/i, /\(c\)/i, "\u00A9", "\xC2\xA9"])
|
8
|
-
REGEX =
|
8
|
+
REGEX = /#{ContentHelper::START_REGEX}(?:portions )?(\s*#{COPYRIGHT_SYMBOLS}.*$)+$/i.freeze
|
9
9
|
# rubocop:enable Metrics/LineLength
|
10
10
|
|
11
11
|
def match
|
12
12
|
# Note: must use content, and not content_normalized here
|
13
|
-
if
|
13
|
+
if file.content.strip =~ /#{REGEX}+\z/i
|
14
14
|
Licensee::License.find('no-license')
|
15
15
|
end
|
16
16
|
rescue Encoding::CompatibilityError
|
@@ -5,9 +5,9 @@ module Licensee
|
|
5
5
|
|
6
6
|
# While we could parse the DESCRIPTION file, prefer
|
7
7
|
# a lenient regex for speed and security. Moar parsing moar problems.
|
8
|
-
LICENSE_FIELD_REGEX = /^license:\s*(.+)/i
|
9
|
-
PLUS_FILE_LICENSE_REGEX = /\s*\+\s*file\s+LICENSE$/i
|
10
|
-
GPL_VERSION_REGEX = /^GPL(?:-([23])|\s*\(\s*>=\s*([23])\s*\))$/i
|
8
|
+
LICENSE_FIELD_REGEX = /^license:\s*(.+)/i.freeze
|
9
|
+
PLUS_FILE_LICENSE_REGEX = /\s*\+\s*file\s+LICENSE$/i.freeze
|
10
|
+
GPL_VERSION_REGEX = /^GPL(?:-([23])|\s*\(\s*>=\s*([23])\s*\))$/i.freeze
|
11
11
|
|
12
12
|
private
|
13
13
|
|