licensee 9.14.1 → 9.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE.md +1 -1
- data/bin/licensee +1 -1
- data/lib/licensee.rb +1 -1
- data/lib/licensee/commands/detect.rb +2 -4
- data/lib/licensee/commands/diff.rb +1 -3
- data/lib/licensee/content_helper.rb +23 -27
- data/lib/licensee/hash_helper.rb +1 -1
- data/lib/licensee/license.rb +28 -14
- data/lib/licensee/matchers/copyright.rb +2 -7
- data/lib/licensee/matchers/cran.rb +1 -1
- data/lib/licensee/matchers/dice.rb +1 -1
- data/lib/licensee/project_files/license_file.rb +29 -22
- data/lib/licensee/project_files/project_file.rb +2 -4
- data/lib/licensee/project_files/readme_file.rb +1 -1
- data/lib/licensee/projects/fs_project.rb +1 -3
- data/lib/licensee/projects/git_project.rb +6 -4
- data/lib/licensee/projects/project.rb +11 -10
- data/lib/licensee/version.rb +1 -1
- data/licensee.gemspec +5 -4
- data/spec/fixture_spec.rb +2 -2
- data/spec/fixtures/bsd-3-authorowner/LICENSE +27 -0
- data/spec/fixtures/cc-by-sa-mdlinks/License.md +173 -0
- data/spec/fixtures/cc-by-sa-nocclicensor/License.md +425 -0
- data/spec/fixtures/detect.json +5 -5
- data/spec/fixtures/eupl-cal2017/LICENSE.txt +274 -0
- data/spec/fixtures/fixtures.yml +45 -25
- data/spec/fixtures/license-hashes.json +39 -38
- data/spec/fixtures/pixar-modified-apache/LICENSE.txt +174 -0
- data/spec/integration_spec.rb +46 -6
- data/spec/licensee/commands/detect_spec.rb +2 -2
- data/spec/licensee/content_helper_spec.rb +14 -13
- data/spec/licensee/license_spec.rb +5 -5
- data/spec/licensee/matchers/dice_matcher_spec.rb +2 -2
- data/spec/licensee/project_files/license_file_spec.rb +8 -2
- data/spec/licensee/project_spec.rb +1 -3
- data/spec/licensee_spec.rb +1 -1
- data/spec/spec_helper.rb +3 -3
- data/spec/vendored_license_spec.rb +1 -1
- data/vendor/choosealicense.com/_licenses/apache-2.0.txt +1 -1
- data/vendor/choosealicense.com/_licenses/bsl-1.0.txt +1 -1
- data/vendor/choosealicense.com/_licenses/eupl-1.2.txt +75 -58
- data/vendor/choosealicense.com/_licenses/mit-0.txt +45 -0
- data/vendor/choosealicense.com/_licenses/odbl-1.0.txt +1 -1
- data/vendor/choosealicense.com/_licenses/unlicense.txt +1 -1
- data/vendor/license-list-XML/src/0BSD.xml +21 -0
- data/vendor/license-list-XML/src/AFL-3.0.xml +212 -0
- data/vendor/license-list-XML/src/AGPL-3.0.xml +852 -0
- data/vendor/license-list-XML/src/Apache-2.0.xml +223 -0
- data/vendor/license-list-XML/src/Artistic-2.0.xml +238 -0
- data/vendor/license-list-XML/src/BSD-2-Clause.xml +42 -0
- data/vendor/license-list-XML/src/BSD-3-Clause-Clear.xml +59 -0
- data/vendor/license-list-XML/src/BSD-3-Clause.xml +46 -0
- data/vendor/license-list-XML/src/BSD-4-Clause.xml +59 -0
- data/vendor/license-list-XML/src/BSL-1.0.xml +30 -0
- data/vendor/license-list-XML/src/CC-BY-4.0.xml +444 -0
- data/vendor/license-list-XML/src/CC-BY-SA-4.0.xml +475 -0
- data/vendor/license-list-XML/src/CC0-1.0.xml +153 -0
- data/vendor/license-list-XML/src/CECILL-2.1.xml +669 -0
- data/vendor/license-list-XML/src/ECL-2.0.xml +242 -0
- data/vendor/license-list-XML/src/EPL-1.0.xml +255 -0
- data/vendor/license-list-XML/src/EPL-2.0.xml +639 -0
- data/vendor/license-list-XML/src/EUPL-1.1.xml +337 -0
- data/vendor/license-list-XML/src/EUPL-1.2.xml +502 -0
- data/vendor/license-list-XML/src/GPL-2.0.xml +474 -0
- data/vendor/license-list-XML/src/GPL-3.0.xml +858 -0
- data/vendor/license-list-XML/src/ISC.xml +29 -0
- data/vendor/license-list-XML/src/LGPL-2.1.xml +662 -0
- data/vendor/license-list-XML/src/LGPL-3.0.xml +260 -0
- data/vendor/license-list-XML/src/LPPL-1.3c.xml +380 -0
- data/vendor/license-list-XML/src/MIT-0.xml +40 -0
- data/vendor/license-list-XML/src/MIT.xml +32 -0
- data/vendor/license-list-XML/src/MPL-2.0.xml +438 -0
- data/vendor/license-list-XML/src/MS-PL.xml +89 -0
- data/vendor/license-list-XML/src/MS-RL.xml +97 -0
- data/vendor/license-list-XML/src/NCSA.xml +60 -0
- data/vendor/license-list-XML/src/ODbL-1.0.xml +660 -0
- data/vendor/license-list-XML/src/OFL-1.1.xml +94 -0
- data/vendor/license-list-XML/src/OSL-3.0.xml +209 -0
- data/vendor/license-list-XML/src/PostgreSQL.xml +32 -0
- data/vendor/license-list-XML/src/UPL-1.0.xml +46 -0
- data/vendor/license-list-XML/src/Unlicense.xml +27 -0
- data/vendor/license-list-XML/src/Vim.xml +124 -0
- data/vendor/license-list-XML/src/WTFPL.xml +30 -0
- data/vendor/license-list-XML/src/Zlib.xml +38 -0
- metadata +73 -13
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 63f3f7938e9e0c58907e71bcf9de72e69d2d494d2dbbba6c71e150b44190eda3
|
|
4
|
+
data.tar.gz: 51583db05dee9239fb50e373f3dc4c79dfa4515a5461facc2722dabe5ee0fb9a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 87b8a85992cec7c2e7c30fab5b96e33a0fdd4271df34a99ca2b99584f1f94cdcb70c5663d9a584ccf1164fd10eca2b1e7b26f09bb7b43a81a8c3705dc6341666
|
|
7
|
+
data.tar.gz: b261c2cf6a2b40fd5b4b10bd4644d179dda3e35686b6f6361af4177dcda852eb45c22bf0dafc43291824a2c48b30f1297c2f933a7786f12dbefbb0bde6dfb83b
|
data/LICENSE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2014-
|
|
3
|
+
Copyright (c) 2014-2021 Ben Balter and Licensee contributors
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
data/bin/licensee
CHANGED
data/lib/licensee.rb
CHANGED
|
@@ -28,11 +28,9 @@ class LicenseeCLI < Thor
|
|
|
28
28
|
['Licenses:', project.licenses.map(&:spdx_id)]
|
|
29
29
|
else
|
|
30
30
|
['License:', set_color('None', :red)]
|
|
31
|
-
|
|
31
|
+
end
|
|
32
32
|
|
|
33
|
-
unless project.matched_files.empty?
|
|
34
|
-
rows << ['Matched files:', project.matched_files.map(&:filename).join(', ')]
|
|
35
|
-
end
|
|
33
|
+
rows << ['Matched files:', project.matched_files.map(&:filename).join(', ')] unless project.matched_files.empty?
|
|
36
34
|
|
|
37
35
|
print_table rows
|
|
38
36
|
|
|
@@ -49,9 +49,7 @@ class LicenseeCLI < Thor
|
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
def expected_license
|
|
52
|
-
if options[:license]
|
|
53
|
-
@expected_license ||= Licensee::License.find options[:license]
|
|
54
|
-
end
|
|
52
|
+
@expected_license ||= Licensee::License.find options[:license] if options[:license]
|
|
55
53
|
return @expected_license if @expected_license
|
|
56
54
|
|
|
57
55
|
if options[:license]
|
|
@@ -23,8 +23,8 @@ module Licensee
|
|
|
23
23
|
url: %r{#{START_REGEX}https?://[^ ]+\n},
|
|
24
24
|
bullet: /\n\n\s*(?:[*-]|\(?[\da-z]{1,2}[).])\s+/i,
|
|
25
25
|
developed_by: /#{START_REGEX}developed by:.*?\n\n/im,
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
cc_dedication: /The\s+text\s+of\s+the\s+Creative\s+Commons.*?Public\s+Domain\s+Dedication./im,
|
|
27
|
+
cc_wiki: /wiki.creativecommons.org/i,
|
|
28
28
|
cc_legal_code: /^\s*Creative Commons Legal Code\s*$/i,
|
|
29
29
|
cc0_info: /For more information, please see\s*\S+zero\S+/im,
|
|
30
30
|
cc0_disclaimer: /CREATIVE COMMONS CORPORATION.*?\n\n/im,
|
|
@@ -36,10 +36,7 @@ module Licensee
|
|
|
36
36
|
https: { from: /http:/, to: 'https:' },
|
|
37
37
|
ampersands: { from: '&', to: 'and' },
|
|
38
38
|
dashes: { from: /(?<!^)([—–-]+)(?!$)/, to: '-' },
|
|
39
|
-
|
|
40
|
-
from: /#{REGEXES[:quote_begin]}+([\w -]*?\w)#{REGEXES[:quote_end]}+/,
|
|
41
|
-
to: '"\1"'
|
|
42
|
-
}
|
|
39
|
+
quote: { from: /[`'"‘“’”]/, to: "'" }
|
|
43
40
|
}.freeze
|
|
44
41
|
|
|
45
42
|
# Legally equivalent words that schould be ignored for comparison
|
|
@@ -90,10 +87,9 @@ module Licensee
|
|
|
90
87
|
}.freeze
|
|
91
88
|
STRIP_METHODS = %i[
|
|
92
89
|
bom
|
|
90
|
+
cc_optional
|
|
93
91
|
cc0_optional
|
|
94
92
|
unlicense_optional
|
|
95
|
-
hrs
|
|
96
|
-
markdown_headings
|
|
97
93
|
borders
|
|
98
94
|
title
|
|
99
95
|
version
|
|
@@ -101,7 +97,6 @@ module Licensee
|
|
|
101
97
|
copyright
|
|
102
98
|
title
|
|
103
99
|
block_markup
|
|
104
|
-
link_markup
|
|
105
100
|
developed_by
|
|
106
101
|
end_of_terms
|
|
107
102
|
whitespace
|
|
@@ -110,7 +105,7 @@ module Licensee
|
|
|
110
105
|
|
|
111
106
|
# A set of each word in the license, without duplicates
|
|
112
107
|
def wordset
|
|
113
|
-
@wordset ||= content_normalized&.scan(%r{(?:[\w
|
|
108
|
+
@wordset ||= content_normalized&.scan(%r{(?:[\w/-](?:'s|(?<=s)')?)+})&.to_set
|
|
114
109
|
end
|
|
115
110
|
|
|
116
111
|
# Number of characters in the normalized content
|
|
@@ -133,7 +128,7 @@ module Licensee
|
|
|
133
128
|
overlap = (wordset_fieldless & other.wordset).size
|
|
134
129
|
total = wordset_fieldless.size + other.wordset.size -
|
|
135
130
|
fields_normalized_set.size
|
|
136
|
-
(overlap * 200.0) / (total +
|
|
131
|
+
(overlap * 200.0) / (total + variation_adjusted_length_delta(other) / 4)
|
|
137
132
|
end
|
|
138
133
|
|
|
139
134
|
# SHA1 of the normalized content
|
|
@@ -148,7 +143,7 @@ module Licensee
|
|
|
148
143
|
def content_without_title_and_version
|
|
149
144
|
@content_without_title_and_version ||= begin
|
|
150
145
|
@_content = nil
|
|
151
|
-
ops = %i[html hrs comments markdown_headings title version]
|
|
146
|
+
ops = %i[html hrs comments markdown_headings link_markup title version]
|
|
152
147
|
ops.each { |op| strip(op) }
|
|
153
148
|
_content
|
|
154
149
|
end
|
|
@@ -186,12 +181,10 @@ module Licensee
|
|
|
186
181
|
text.gsub!(/([^\n])\n([^\n])/, '\1 \2')
|
|
187
182
|
|
|
188
183
|
text = text.split("\n").collect do |line|
|
|
189
|
-
if line =~ REGEXES[:hrs]
|
|
184
|
+
if line =~ REGEXES[:hrs] || line.length <= line_width
|
|
190
185
|
line
|
|
191
|
-
elsif line.length > line_width
|
|
192
|
-
line.gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n").strip
|
|
193
186
|
else
|
|
194
|
-
line
|
|
187
|
+
line.gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n").strip
|
|
195
188
|
end
|
|
196
189
|
end * "\n"
|
|
197
190
|
|
|
@@ -233,9 +226,7 @@ module Licensee
|
|
|
233
226
|
meth = "strip_#{regex_or_sym}"
|
|
234
227
|
return send(meth) if respond_to?(meth, true)
|
|
235
228
|
|
|
236
|
-
unless REGEXES[regex_or_sym]
|
|
237
|
-
raise ArgumentError, "#{regex_or_sym} is an invalid regex reference"
|
|
238
|
-
end
|
|
229
|
+
raise ArgumentError, "#{regex_or_sym} is an invalid regex reference" unless REGEXES[regex_or_sym]
|
|
239
230
|
|
|
240
231
|
regex_or_sym = REGEXES[regex_or_sym]
|
|
241
232
|
end
|
|
@@ -244,9 +235,7 @@ module Licensee
|
|
|
244
235
|
end
|
|
245
236
|
|
|
246
237
|
def strip_title
|
|
247
|
-
while _content =~ ContentHelper.title_regex
|
|
248
|
-
strip(ContentHelper.title_regex)
|
|
249
|
-
end
|
|
238
|
+
strip(ContentHelper.title_regex) while _content =~ ContentHelper.title_regex
|
|
250
239
|
end
|
|
251
240
|
|
|
252
241
|
def strip_borders
|
|
@@ -274,6 +263,13 @@ module Licensee
|
|
|
274
263
|
strip(REGEXES[:cc0_disclaimer])
|
|
275
264
|
end
|
|
276
265
|
|
|
266
|
+
def strip_cc_optional
|
|
267
|
+
return unless _content.include? 'creative commons'
|
|
268
|
+
|
|
269
|
+
strip(REGEXES[:cc_dedication])
|
|
270
|
+
strip(REGEXES[:cc_wiki])
|
|
271
|
+
end
|
|
272
|
+
|
|
277
273
|
def strip_unlicense_optional
|
|
278
274
|
return unless _content.include? 'unlicense'
|
|
279
275
|
|
|
@@ -295,7 +291,7 @@ module Licensee
|
|
|
295
291
|
|
|
296
292
|
def strip_html
|
|
297
293
|
return unless respond_to?(:filename) && filename
|
|
298
|
-
return unless File.extname(filename)
|
|
294
|
+
return unless /\.html?/i.match?(File.extname(filename))
|
|
299
295
|
|
|
300
296
|
require 'reverse_markdown'
|
|
301
297
|
@_content = ReverseMarkdown.convert(_content, unknown_tags: :bypass)
|
|
@@ -319,7 +315,7 @@ module Licensee
|
|
|
319
315
|
end
|
|
320
316
|
|
|
321
317
|
def normalize_bullets
|
|
322
|
-
normalize(REGEXES[:bullet], "\n\n
|
|
318
|
+
normalize(REGEXES[:bullet], "\n\n- ")
|
|
323
319
|
normalize(/\)\s+\(/, ')(')
|
|
324
320
|
end
|
|
325
321
|
|
|
@@ -337,10 +333,10 @@ module Licensee
|
|
|
337
333
|
@fields_normalized_set ||= fields_normalized.to_set
|
|
338
334
|
end
|
|
339
335
|
|
|
340
|
-
def
|
|
336
|
+
def variation_adjusted_length_delta(other)
|
|
341
337
|
delta = length_delta(other)
|
|
342
|
-
adjusted_delta = delta - fields_normalized.size *
|
|
343
|
-
adjusted_delta.positive? ? adjusted_delta :
|
|
338
|
+
adjusted_delta = delta - [fields_normalized.size, spdx_alt_segments].max * 4
|
|
339
|
+
adjusted_delta.positive? ? adjusted_delta : 0
|
|
344
340
|
end
|
|
345
341
|
end
|
|
346
342
|
end
|
data/lib/licensee/hash_helper.rb
CHANGED
data/lib/licensee/license.rb
CHANGED
|
@@ -4,6 +4,7 @@ require 'uri'
|
|
|
4
4
|
|
|
5
5
|
module Licensee
|
|
6
6
|
class InvalidLicense < ArgumentError; end
|
|
7
|
+
|
|
7
8
|
class License
|
|
8
9
|
@all = {}
|
|
9
10
|
@keys_licenses = {}
|
|
@@ -26,9 +27,11 @@ module Licensee
|
|
|
26
27
|
output.reject!(&:hidden?) unless options[:hidden]
|
|
27
28
|
output.reject!(&:pseudo_license?) unless options[:pseudo]
|
|
28
29
|
output.sort_by!(&:key)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
if options[:featured].nil?
|
|
31
|
+
output
|
|
32
|
+
else
|
|
33
|
+
output.select { |l| l.featured? == options[:featured] }
|
|
34
|
+
end
|
|
32
35
|
end
|
|
33
36
|
end
|
|
34
37
|
|
|
@@ -53,14 +56,17 @@ module Licensee
|
|
|
53
56
|
end
|
|
54
57
|
|
|
55
58
|
def license_dir
|
|
56
|
-
|
|
57
|
-
::File.expand_path '../../vendor/choosealicense.com/_licenses', dir
|
|
59
|
+
::File.expand_path '../../vendor/choosealicense.com/_licenses', __dir__
|
|
58
60
|
end
|
|
59
61
|
|
|
60
62
|
def license_files
|
|
61
63
|
@license_files ||= Dir.glob("#{license_dir}/*.txt")
|
|
62
64
|
end
|
|
63
65
|
|
|
66
|
+
def spdx_dir
|
|
67
|
+
::File.expand_path '../../vendor/license-list-XML/src', __dir__
|
|
68
|
+
end
|
|
69
|
+
|
|
64
70
|
private
|
|
65
71
|
|
|
66
72
|
def licenses
|
|
@@ -82,7 +88,7 @@ module Licensee
|
|
|
82
88
|
# `other` - The project had a license, but we were not able to detect it
|
|
83
89
|
# `no-license` - The project is not licensed (e.g., all rights reserved)
|
|
84
90
|
#
|
|
85
|
-
#
|
|
91
|
+
# NOTE: A lack of detected license will be a nil license
|
|
86
92
|
PSEUDO_LICENSES = %w[other no-license].freeze
|
|
87
93
|
|
|
88
94
|
# Default options to use when retrieving licenses via #all
|
|
@@ -154,9 +160,7 @@ module Licensee
|
|
|
154
160
|
key_regex = Regexp.new string, 'i'
|
|
155
161
|
|
|
156
162
|
parts = [title_regex, key_regex]
|
|
157
|
-
if meta.nickname
|
|
158
|
-
parts.push Regexp.new meta.nickname.sub(/\bGNU /i, '(?:GNU )?')
|
|
159
|
-
end
|
|
163
|
+
parts.push Regexp.new meta.nickname.sub(/\bGNU /i, '(?:GNU )?') if meta.nickname
|
|
160
164
|
|
|
161
165
|
@title_regex = Regexp.union parts
|
|
162
166
|
end
|
|
@@ -173,8 +177,8 @@ module Licensee
|
|
|
173
177
|
return @source_regex if defined? @source_regex
|
|
174
178
|
return unless meta.source
|
|
175
179
|
|
|
176
|
-
source = meta.source.dup.sub(/\A#{SOURCE_PREFIX}
|
|
177
|
-
source = source.sub(/#{SOURCE_SUFFIX}\z
|
|
180
|
+
source = meta.source.dup.sub(/\A#{SOURCE_PREFIX}/o, '')
|
|
181
|
+
source = source.sub(/#{SOURCE_SUFFIX}\z/o, '')
|
|
178
182
|
|
|
179
183
|
escaped_source = Regexp.escape(source)
|
|
180
184
|
@source_regex = /#{SOURCE_PREFIX}#{escaped_source}(?:#{SOURCE_SUFFIX})?/i
|
|
@@ -244,9 +248,7 @@ module Licensee
|
|
|
244
248
|
# Raw content of license file, including YAML front matter
|
|
245
249
|
def raw_content
|
|
246
250
|
return if pseudo_license?
|
|
247
|
-
unless File.exist?(path)
|
|
248
|
-
raise Licensee::InvalidLicense, "'#{key}' is not a valid license key"
|
|
249
|
-
end
|
|
251
|
+
raise Licensee::InvalidLicense, "'#{key}' is not a valid license key" unless File.exist?(path)
|
|
250
252
|
|
|
251
253
|
@raw_content ||= File.read(path, encoding: 'utf-8')
|
|
252
254
|
end
|
|
@@ -260,5 +262,17 @@ module Licensee
|
|
|
260
262
|
def yaml
|
|
261
263
|
@yaml ||= parts[1] if parts
|
|
262
264
|
end
|
|
265
|
+
|
|
266
|
+
def spdx_alt_segments
|
|
267
|
+
@spdx_alt_segments ||= begin
|
|
268
|
+
path = File.expand_path "#{spdx_id}.xml", Licensee::License.spdx_dir
|
|
269
|
+
raw_xml = File.read(path, encoding: 'utf-8')
|
|
270
|
+
text = raw_xml.match(%r{<text>(.*)</text>}m)[1]
|
|
271
|
+
text.gsub!(%r{<copyrightText>.*?</copyrightText>}m, '')
|
|
272
|
+
text.gsub!(%r{<titleText>.*?</titleText>}m, '')
|
|
273
|
+
text.gsub!(%r{<optional.*?>.*?</optional>}m, '')
|
|
274
|
+
text.scan(/<alt .*?>/m).size
|
|
275
|
+
end
|
|
276
|
+
end
|
|
263
277
|
end
|
|
264
278
|
end
|
|
@@ -5,16 +5,11 @@ module Licensee
|
|
|
5
5
|
class Copyright < Licensee::Matchers::Matcher
|
|
6
6
|
attr_reader :file
|
|
7
7
|
|
|
8
|
-
# rubocop:disable Layout/LineLength
|
|
9
8
|
COPYRIGHT_SYMBOLS = Regexp.union([/copyright/i, /\(c\)/i, "\u00A9", "\xC2\xA9"])
|
|
10
9
|
REGEX = /#{ContentHelper::START_REGEX}(?:portions )?([_*\-\s]*#{COPYRIGHT_SYMBOLS}.*$)+$/i.freeze
|
|
11
|
-
# rubocop:enable Layout/LineLength
|
|
12
|
-
|
|
13
10
|
def match
|
|
14
|
-
#
|
|
15
|
-
|
|
16
|
-
Licensee::License.find('no-license')
|
|
17
|
-
end
|
|
11
|
+
# NOTE: must use content, and not content_normalized here
|
|
12
|
+
Licensee::License.find('no-license') if /#{REGEX}+\z/io.match?(file.content.strip)
|
|
18
13
|
rescue Encoding::CompatibilityError
|
|
19
14
|
nil
|
|
20
15
|
end
|
|
@@ -26,7 +26,7 @@ module Licensee
|
|
|
26
26
|
# Otherwise, returns `nil`
|
|
27
27
|
def gpl_version(license_key)
|
|
28
28
|
match = license_key.match GPL_VERSION_REGEX
|
|
29
|
-
match ? "gpl-#{
|
|
29
|
+
match ? "gpl-#{match[1] || match[2]}.0" : nil
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
# Normalizes the license field value to an SPDX ID
|
|
@@ -10,7 +10,14 @@ module Licensee
|
|
|
10
10
|
PREFERRED_EXT_REGEX = /\.#{Regexp.union(PREFERRED_EXT)}\z/.freeze
|
|
11
11
|
|
|
12
12
|
# Regex to match any extension except .spdx or .header
|
|
13
|
-
|
|
13
|
+
LICENSE_EXT_REGEX = %r{\.(?!spdx|header)[^./]+\z}i.freeze
|
|
14
|
+
|
|
15
|
+
# Regex to match any extension except a few unlikely as license
|
|
16
|
+
# texts with complex filenames
|
|
17
|
+
OTHER_EXT_REGEX = %r{\.(?!xml|go|gemspec)[^./]+\z}i.freeze
|
|
18
|
+
|
|
19
|
+
# Regex to match any extension
|
|
20
|
+
ANY_EXT_REGEX = %r{\.[^./]+\z}i.freeze
|
|
14
21
|
|
|
15
22
|
# Regex to match, LICENSE, LICENCE, unlicense, etc.
|
|
16
23
|
LICENSE_REGEX = /(un)?licen[sc]e/i.freeze
|
|
@@ -26,22 +33,22 @@ module Licensee
|
|
|
26
33
|
|
|
27
34
|
# Hash of Regex => score with which to score potential license files
|
|
28
35
|
FILENAME_REGEXES = {
|
|
29
|
-
/\A#{LICENSE_REGEX}\z/
|
|
30
|
-
/\A#{LICENSE_REGEX}#{PREFERRED_EXT_REGEX}\z/
|
|
31
|
-
/\A#{COPYING_REGEX}\z/
|
|
32
|
-
/\A#{COPYING_REGEX}#{PREFERRED_EXT_REGEX}\z/
|
|
33
|
-
/\A#{LICENSE_REGEX}#{
|
|
34
|
-
/\A#{COPYING_REGEX}#{
|
|
35
|
-
/\A#{LICENSE_REGEX}[-_]/
|
|
36
|
-
/\A#{COPYING_REGEX}[-_]/
|
|
37
|
-
/\A\w+[-_]#{LICENSE_REGEX}/
|
|
38
|
-
/\A\w+[-_]#{COPYING_REGEX}/
|
|
39
|
-
/\A#{OFL_REGEX}#{PREFERRED_EXT_REGEX}/
|
|
40
|
-
/\A#{OFL_REGEX}#{OTHER_EXT_REGEX}/
|
|
41
|
-
/\A#{OFL_REGEX}\z/
|
|
42
|
-
/\A#{PATENTS_REGEX}\z/
|
|
43
|
-
/\A#{PATENTS_REGEX}#{OTHER_EXT_REGEX}\z/
|
|
44
|
-
//
|
|
36
|
+
/\A#{LICENSE_REGEX}\z/ => 1.00, # LICENSE
|
|
37
|
+
/\A#{LICENSE_REGEX}#{PREFERRED_EXT_REGEX}\z/ => 0.95, # LICENSE.md
|
|
38
|
+
/\A#{COPYING_REGEX}\z/ => 0.90, # COPYING
|
|
39
|
+
/\A#{COPYING_REGEX}#{PREFERRED_EXT_REGEX}\z/ => 0.85, # COPYING.md
|
|
40
|
+
/\A#{LICENSE_REGEX}#{LICENSE_EXT_REGEX}\z/ => 0.80, # LICENSE.textile
|
|
41
|
+
/\A#{COPYING_REGEX}#{ANY_EXT_REGEX}\z/ => 0.75, # COPYING.textile
|
|
42
|
+
/\A#{LICENSE_REGEX}[-_][^.]*#{OTHER_EXT_REGEX}?\z/ => 0.70, # LICENSE-MIT
|
|
43
|
+
/\A#{COPYING_REGEX}[-_][^.]*#{OTHER_EXT_REGEX}?\z/ => 0.65, # COPYING-MIT
|
|
44
|
+
/\A\w+[-_]#{LICENSE_REGEX}[^.]*#{OTHER_EXT_REGEX}?\z/ => 0.60, # MIT-LICENSE-MIT
|
|
45
|
+
/\A\w+[-_]#{COPYING_REGEX}[^.]*#{OTHER_EXT_REGEX}?\z/ => 0.55, # MIT-COPYING
|
|
46
|
+
/\A#{OFL_REGEX}#{PREFERRED_EXT_REGEX}/ => 0.50, # OFL.md
|
|
47
|
+
/\A#{OFL_REGEX}#{OTHER_EXT_REGEX}/ => 0.45, # OFL.textile
|
|
48
|
+
/\A#{OFL_REGEX}\z/ => 0.40, # OFL
|
|
49
|
+
/\A#{PATENTS_REGEX}\z/ => 0.35, # PATENTS
|
|
50
|
+
/\A#{PATENTS_REGEX}#{OTHER_EXT_REGEX}\z/ => 0.30, # PATENTS.txt
|
|
51
|
+
// => 0.00 # Catch all
|
|
45
52
|
}.freeze
|
|
46
53
|
|
|
47
54
|
# CC-NC and CC-ND are not open source licenses and should not be
|
|
@@ -56,11 +63,11 @@ module Licensee
|
|
|
56
63
|
|
|
57
64
|
def attribution
|
|
58
65
|
@attribution ||= begin
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
66
|
+
if copyright? || license.content&.include?('[fullname]')
|
|
67
|
+
matches = Matchers::Copyright::REGEX
|
|
68
|
+
.match(content_without_title_and_version)
|
|
69
|
+
matches[0] if matches
|
|
70
|
+
end
|
|
64
71
|
end
|
|
65
72
|
end
|
|
66
73
|
|
|
@@ -37,9 +37,7 @@ module Licensee
|
|
|
37
37
|
def initialize(content, metadata = {})
|
|
38
38
|
@content = content.dup
|
|
39
39
|
@content.force_encoding(ENCODING)
|
|
40
|
-
unless @content.valid_encoding?
|
|
41
|
-
@content.encode!(ENCODING, **ENCODING_OPTIONS)
|
|
42
|
-
end
|
|
40
|
+
@content.encode!(ENCODING, **ENCODING_OPTIONS) unless @content.valid_encoding?
|
|
43
41
|
@content.encode!(ENCODING, universal_newline: true)
|
|
44
42
|
|
|
45
43
|
metadata = { name: metadata } if metadata.is_a? String
|
|
@@ -93,7 +91,7 @@ module Licensee
|
|
|
93
91
|
return false unless is_a?(LicenseFile)
|
|
94
92
|
return false unless matcher.is_a?(Matchers::Copyright)
|
|
95
93
|
|
|
96
|
-
filename =~ /\Acopyright(?:#{LicenseFile::OTHER_EXT_REGEX})?\z/
|
|
94
|
+
filename =~ /\Acopyright(?:#{LicenseFile::OTHER_EXT_REGEX})?\z/io
|
|
97
95
|
end
|
|
98
96
|
|
|
99
97
|
def content_hash
|