licensee 8.3.1 → 8.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +1 -1
- data/lib/licensee/content_helper.rb +29 -1
- data/lib/licensee/license.rb +4 -0
- data/lib/licensee/matchers/copyright_matcher.rb +2 -1
- data/lib/licensee/matchers/dice_matcher.rb +10 -35
- data/lib/licensee/matchers/exact_matcher.rb +3 -1
- data/lib/licensee/project.rb +36 -2
- data/lib/licensee/project_files/license_file.rb +5 -0
- data/lib/licensee/projects/fs_project.rb +14 -9
- data/lib/licensee/projects/git_project.rb +14 -13
- data/lib/licensee/version.rb +1 -1
- data/lib/licensee.rb +7 -1
- data/test/fixtures/lgpl.git/HEAD +1 -0
- data/test/fixtures/lgpl.git/config +5 -0
- data/test/fixtures/lgpl.git/objects/1a/cd060ebbbeac294200008657d9502130f93465 +2 -0
- data/test/fixtures/lgpl.git/objects/4b/1f98c1e95b6d4dae0b0a160f554be97e5afece +2 -0
- data/test/fixtures/lgpl.git/objects/a4/cfa42bc8e1d432fa851c5c4e3f294f01e05fd3 +0 -0
- data/test/fixtures/lgpl.git/objects/b7/de6e186bd02935030f5d42867ea7043fb1c27c +0 -0
- data/test/fixtures/lgpl.git/objects/dd/d0e017b1bf39218a6ea4f2fadd29a7ea8ebe03 +0 -0
- data/test/fixtures/lgpl.git/objects/eb/d853e83a2d317422c52f3922f4c9c5bb4a10b7 +0 -0
- data/test/fixtures/lgpl.git/refs/heads/master +1 -0
- data/test/functions.rb +16 -9
- data/test/{test_licensee_copyright_matcher.rb → licensee/matchers/test_copyright_matcher.rb} +6 -0
- data/test/{test_licensee_dice_matcher.rb → licensee/matchers/test_dice_matcher.rb} +11 -2
- data/test/{test_licensee_exact_matcher.rb → licensee/matchers/test_exact_matcher.rb} +8 -0
- data/test/{test_licensee_gemspec_matcher.rb → licensee/matchers/test_gemspec_matcher.rb} +1 -1
- data/test/{test_licensee_npm_bower_matcher.rb → licensee/matchers/test_npm_bower_matcher.rb} +0 -0
- data/test/licensee/matchers/test_package_matcher.rb +27 -0
- data/test/{test_licensee_license_file.rb → licensee/project_files/test_license_file.rb} +15 -0
- data/test/{test_licensee_package_info.rb → licensee/project_files/test_package_info.rb} +0 -0
- data/test/{test_licensee_readme.rb → licensee/project_files/test_readme.rb} +0 -0
- data/test/licensee/test_content_helper.rb +56 -0
- data/test/{test_licensee_license.rb → licensee/test_license.rb} +11 -0
- data/test/{test_licensee_project.rb → licensee/test_project.rb} +5 -0
- data/test/{test_licensee_project_file.rb → licensee/test_project_file.rb} +0 -0
- data/test/test_licensee.rb +6 -2
- data/vendor/choosealicense.com/_licenses/afl-3.0.txt +5 -4
- data/vendor/choosealicense.com/_licenses/agpl-3.0.txt +8 -7
- data/vendor/choosealicense.com/_licenses/apache-2.0.txt +5 -4
- data/vendor/choosealicense.com/_licenses/artistic-2.0.txt +6 -5
- data/vendor/choosealicense.com/_licenses/bsd-2-clause.txt +4 -3
- data/vendor/choosealicense.com/_licenses/bsd-3-clause-clear.txt +5 -5
- data/vendor/choosealicense.com/_licenses/bsd-3-clause.txt +4 -3
- data/vendor/choosealicense.com/_licenses/cc-by-4.0.txt +5 -4
- data/vendor/choosealicense.com/_licenses/cc-by-sa-4.0.txt +6 -5
- data/vendor/choosealicense.com/_licenses/cc0-1.0.txt +1 -0
- data/vendor/choosealicense.com/_licenses/epl-1.0.txt +6 -5
- data/vendor/choosealicense.com/_licenses/eupl-1.1.txt +8 -7
- data/vendor/choosealicense.com/_licenses/gpl-2.0.txt +7 -6
- data/vendor/choosealicense.com/_licenses/gpl-3.0.txt +7 -6
- data/vendor/choosealicense.com/_licenses/isc.txt +4 -3
- data/vendor/choosealicense.com/_licenses/lgpl-2.1.txt +7 -6
- data/vendor/choosealicense.com/_licenses/lgpl-3.0.txt +7 -7
- data/vendor/choosealicense.com/_licenses/lppl-1.3c.txt +6 -5
- data/vendor/choosealicense.com/_licenses/mit.txt +4 -3
- data/vendor/choosealicense.com/_licenses/mpl-2.0.txt +6 -5
- data/vendor/choosealicense.com/_licenses/ms-pl.txt +4 -4
- data/vendor/choosealicense.com/_licenses/ms-rl.txt +7 -7
- data/vendor/choosealicense.com/_licenses/ofl-1.1.txt +4 -4
- data/vendor/choosealicense.com/_licenses/osl-3.0.txt +7 -7
- data/vendor/choosealicense.com/_licenses/unlicense.txt +6 -1
- data/vendor/choosealicense.com/_licenses/wtfpl.txt +2 -2
- data/vendor/choosealicense.com/_licenses/zlib.txt +5 -4
- metadata +24 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0ea7d783ce6fc8e59946877a34fc32d84b01f449
|
4
|
+
data.tar.gz: 65142dc4101a66360d080b7eede89977d5ca10c6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b93a5da892c334a4e3bce03be2ef7342ffda08ae64b6db412216f691af53ee9d8a7d54596c9aadaff6cd6d02038c04da21f4d4e98af222283788fdb77a340cc
|
7
|
+
data.tar.gz: d066ee5ed370b2c840cd5282f19fccf525f26cde2469a6205039ab886b5b1f2ca5e63e9ac88fc2888fa1c4657cda2b50d2f57f4da79632ac22ad4f96779bc33a
|
data/Rakefile
CHANGED
@@ -5,22 +5,50 @@ module Licensee
|
|
5
5
|
module ContentHelper
|
6
6
|
DIGEST = Digest::SHA1
|
7
7
|
|
8
|
+
# A set of each word in the license, without duplicates
|
8
9
|
def wordset
|
9
10
|
@wordset ||= if content_normalized
|
10
11
|
content_normalized.scan(/[\w']+/).to_set
|
11
12
|
end
|
12
13
|
end
|
13
14
|
|
15
|
+
# Number of characteres in the normalized content
|
16
|
+
def length
|
17
|
+
return 0 unless content_normalized
|
18
|
+
content_normalized.length
|
19
|
+
end
|
20
|
+
|
21
|
+
# Number of characters that could be added/removed to still be
|
22
|
+
# considered a potential match
|
23
|
+
def max_delta
|
24
|
+
(length * Licensee.inverse_confidence_threshold).to_i
|
25
|
+
end
|
26
|
+
|
27
|
+
# Given another license or project file, calculates the difference in length
|
28
|
+
def length_delta(other)
|
29
|
+
(length - other.length).abs
|
30
|
+
end
|
31
|
+
|
32
|
+
# Given another license or project file, calculates the similarity
|
33
|
+
# as a percentage of words in common
|
34
|
+
def similarity(other)
|
35
|
+
overlap = (wordset & other.wordset).size
|
36
|
+
total = wordset.size + other.wordset.size
|
37
|
+
100.0 * (overlap * 2.0 / total)
|
38
|
+
end
|
39
|
+
|
40
|
+
# SHA1 of the normalized content
|
14
41
|
def hash
|
15
42
|
@hash ||= DIGEST.hexdigest content_normalized
|
16
43
|
end
|
17
44
|
|
45
|
+
# Content with copyright header and linebreaks removed
|
18
46
|
def content_normalized
|
19
47
|
return unless content
|
20
48
|
@content_normalized ||= begin
|
21
49
|
content_normalized = content.downcase.strip
|
22
50
|
content_normalized.gsub!(/^#{Matchers::Copyright::REGEX}$/i, '')
|
23
|
-
content_normalized.tr("\n", ' ').squeeze(' ')
|
51
|
+
content_normalized.tr("\n", ' ').squeeze(' ').strip
|
24
52
|
end
|
25
53
|
end
|
26
54
|
end
|
data/lib/licensee/license.rb
CHANGED
@@ -2,7 +2,8 @@
|
|
2
2
|
module Licensee
|
3
3
|
module Matchers
|
4
4
|
class Copyright
|
5
|
-
|
5
|
+
# rubocop:disable Metrics/LineLength
|
6
|
+
REGEX = /\s*(Copyright|\(c\)) (©|\(c\)|\xC2\xA9)? ?(\d{4}|\[year\])(.*)?\s*/i
|
6
7
|
|
7
8
|
def initialize(file)
|
8
9
|
@file = file
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module Licensee
|
2
2
|
module Matchers
|
3
3
|
class Dice
|
4
|
+
attr_reader :file
|
5
|
+
|
4
6
|
def initialize(file)
|
5
7
|
@file = file
|
6
8
|
end
|
@@ -10,9 +12,8 @@ module Licensee
|
|
10
12
|
def match
|
11
13
|
return @match if defined? @match
|
12
14
|
matches = potential_licenses.map do |license|
|
13
|
-
|
14
|
-
|
15
|
-
end
|
15
|
+
similarity = license.similarity(file)
|
16
|
+
[license, similarity] if similarity >= Licensee.confidence_threshold
|
16
17
|
end
|
17
18
|
matches.compact!
|
18
19
|
@match = if matches.empty?
|
@@ -22,46 +23,20 @@ module Licensee
|
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
# the confidence threshold / 100
|
26
|
+
# Licenses that may be a match for this file.
|
27
|
+
# To avoid false positives, the percentage change in file length
|
28
|
+
# may not exceed the inverse of the confidence threshold
|
29
29
|
def potential_licenses
|
30
30
|
@potential_licenses ||= begin
|
31
|
-
|
32
|
-
|
33
|
-
license.wordset && length_delta(license) <= max_delta
|
31
|
+
Licensee.licenses(hidden: true).select do |license|
|
32
|
+
license.wordset && license.length_delta(file) <= license.max_delta
|
34
33
|
end
|
35
|
-
licenses.sort_by { |l| length_delta(l) }
|
36
34
|
end
|
37
35
|
end
|
38
36
|
|
39
|
-
# Calculate the difference between the file length and a given
|
40
|
-
# license's length
|
41
|
-
def length_delta(license)
|
42
|
-
(@file.wordset.size - license.wordset.size).abs
|
43
|
-
end
|
44
|
-
|
45
|
-
# Maximum possible difference between file length and license length
|
46
|
-
# for a license to be a potential license to be matched
|
47
|
-
def max_delta
|
48
|
-
@max_delta ||= (
|
49
|
-
@file.wordset.size * (Licensee.confidence_threshold / 100.0)
|
50
|
-
)
|
51
|
-
end
|
52
|
-
|
53
37
|
# Confidence that the matched license is a match
|
54
38
|
def confidence
|
55
|
-
@confidence ||= match ? similarity(match) : 0
|
56
|
-
end
|
57
|
-
|
58
|
-
private
|
59
|
-
|
60
|
-
# Calculate percent changed between file and potential license
|
61
|
-
def similarity(license)
|
62
|
-
overlap = (@file.wordset & license.wordset).size
|
63
|
-
total = @file.wordset.size + license.wordset.size
|
64
|
-
100.0 * (overlap * 2.0 / total)
|
39
|
+
@confidence ||= match ? file.similarity(match) : 0
|
65
40
|
end
|
66
41
|
end
|
67
42
|
end
|
@@ -6,7 +6,9 @@ module Licensee
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def match
|
9
|
-
Licensee.licenses(hidden: true).find
|
9
|
+
Licensee.licenses(hidden: true).find do |license|
|
10
|
+
license.length == @file.length && license.wordset == @file.wordset
|
11
|
+
end
|
10
12
|
end
|
11
13
|
|
12
14
|
def confidence
|
data/lib/licensee/project.rb
CHANGED
@@ -23,8 +23,16 @@ module Licensee
|
|
23
23
|
def license_file
|
24
24
|
return @license_file if defined? @license_file
|
25
25
|
@license_file = begin
|
26
|
-
|
27
|
-
|
26
|
+
license_file = license_from_file { |n| LicenseFile.name_score(n) }
|
27
|
+
return license_file unless license_file && license_file.license
|
28
|
+
|
29
|
+
# Special case LGPL, which actuall lives in LICENSE.lesser, per the
|
30
|
+
# license instructions. See https://git.io/viwyK
|
31
|
+
lesser = if license_file.license.gpl?
|
32
|
+
license_from_file { |file| LicenseFile.lesser_gpl_score(file) }
|
33
|
+
end
|
34
|
+
|
35
|
+
lesser || license_file
|
28
36
|
end
|
29
37
|
end
|
30
38
|
|
@@ -46,5 +54,31 @@ module Licensee
|
|
46
54
|
PackageInfo.new(content, name) if content && name
|
47
55
|
end
|
48
56
|
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
# Given a block, passes each filename to that block, and expects a numeric
|
61
|
+
# score in response. Returns an array of all files with a score > 0,
|
62
|
+
# sorted by file score descending
|
63
|
+
def find_files
|
64
|
+
return [] if files.empty? || files.nil?
|
65
|
+
found = files.each { |file| file[:score] = yield(file[:name]) }
|
66
|
+
found.select! { |file| file[:score] > 0 }
|
67
|
+
found.sort { |a, b| b[:score] <=> a[:score] }
|
68
|
+
end
|
69
|
+
|
70
|
+
# Given a block, passes each filename to that block, and expects a numeric
|
71
|
+
# score in response. Returns a hash representing the top scoring file
|
72
|
+
# or nil, if no file scored > 0
|
73
|
+
def find_file(&block)
|
74
|
+
return if files.empty? || files.nil?
|
75
|
+
file = find_files(&block).first
|
76
|
+
[load_file(file), file[:name]] if file
|
77
|
+
end
|
78
|
+
|
79
|
+
def license_from_file(&block)
|
80
|
+
content, name = find_file(&block)
|
81
|
+
LicenseFile.new(content, name) if content && name
|
82
|
+
end
|
49
83
|
end
|
50
84
|
end
|
@@ -20,6 +20,11 @@ module Licensee
|
|
20
20
|
return 0.5 if filename =~ /licen[sc]e/i
|
21
21
|
0.0
|
22
22
|
end
|
23
|
+
|
24
|
+
# case-insensitive block to determine if the given file is LICENSE.lesser
|
25
|
+
def self.lesser_gpl_score(filename)
|
26
|
+
filename.casecmp('copying.lesser').zero? ? 1 : 0
|
27
|
+
end
|
23
28
|
end
|
24
29
|
end
|
25
30
|
end
|
@@ -12,7 +12,9 @@ module Licensee
|
|
12
12
|
|
13
13
|
private
|
14
14
|
|
15
|
-
|
15
|
+
# Returns an array of hashes representing the project's files.
|
16
|
+
# Hashes will have the :name key, with the relative path to the file
|
17
|
+
def files
|
16
18
|
files = []
|
17
19
|
|
18
20
|
if ::File.file?(path)
|
@@ -24,17 +26,20 @@ module Licensee
|
|
24
26
|
|
25
27
|
Dir.glob(::File.join(path, pattern)) do |file|
|
26
28
|
next unless ::File.file?(file)
|
27
|
-
|
28
|
-
if (score = yield file) > 0
|
29
|
-
files.push(name: file, score: score)
|
30
|
-
end
|
29
|
+
files.push(name: ::File.basename(file))
|
31
30
|
end
|
32
31
|
|
33
|
-
|
34
|
-
|
32
|
+
files
|
33
|
+
end
|
35
34
|
|
36
|
-
|
37
|
-
|
35
|
+
# Retrieve a file's content from disk
|
36
|
+
#
|
37
|
+
# file - the file hash, with the :name key as the file's relative path
|
38
|
+
# path - the base path to the project
|
39
|
+
#
|
40
|
+
# Returns the fiel contents as a string
|
41
|
+
def load_file(file)
|
42
|
+
::File.read(::File.join(path, file[:name]))
|
38
43
|
end
|
39
44
|
end
|
40
45
|
end
|
@@ -36,24 +36,25 @@ module Licensee
|
|
36
36
|
|
37
37
|
MAX_LICENSE_SIZE = 64 * 1024
|
38
38
|
|
39
|
-
|
40
|
-
|
39
|
+
# Retrieve a file's content from the Git database
|
40
|
+
#
|
41
|
+
# file - the file hash, including the file's OID
|
42
|
+
#
|
43
|
+
# Returns a string representing the file's contents
|
44
|
+
def load_file(file)
|
45
|
+
data, = Rugged::Blob.to_buffer(repository, file[:oid], MAX_LICENSE_SIZE)
|
41
46
|
data
|
42
47
|
end
|
43
48
|
|
44
|
-
|
45
|
-
|
49
|
+
# Returns an array of hashes representing the project's files.
|
50
|
+
# Hashes will have the the following keys:
|
51
|
+
# :name - the file's path relative to the repo root
|
52
|
+
# :oid - the file's OID
|
53
|
+
def files
|
54
|
+
commit.tree.map do |entry|
|
46
55
|
next unless entry[:type] == :blob
|
47
|
-
|
48
|
-
{ name: entry[:name], oid: entry[:oid], score: score }
|
49
|
-
end
|
56
|
+
{ name: entry[:name], oid: entry[:oid] }
|
50
57
|
end.compact
|
51
|
-
|
52
|
-
return if files.empty?
|
53
|
-
files.sort! { |a, b| b[:score] <=> a[:score] }
|
54
|
-
|
55
|
-
f = files.first
|
56
|
-
[load_blob_data(f[:oid]), f[:name]]
|
57
58
|
end
|
58
59
|
end
|
59
60
|
end
|
data/lib/licensee/version.rb
CHANGED
data/lib/licensee.rb
CHANGED
@@ -23,7 +23,7 @@ require_relative 'licensee/matchers/npm_bower_matcher'
|
|
23
23
|
|
24
24
|
module Licensee
|
25
25
|
# Over which percent is a match considered a match by default
|
26
|
-
CONFIDENCE_THRESHOLD =
|
26
|
+
CONFIDENCE_THRESHOLD = 95
|
27
27
|
|
28
28
|
# Base domain from which to build license URLs
|
29
29
|
DOMAIN = 'http://choosealicense.com'.freeze
|
@@ -50,5 +50,11 @@ module Licensee
|
|
50
50
|
def confidence_threshold
|
51
51
|
@confidence_threshold ||= CONFIDENCE_THRESHOLD
|
52
52
|
end
|
53
|
+
|
54
|
+
# Inverse of the confidence threshold, represented as a float
|
55
|
+
# By default this will be 0.1
|
56
|
+
def inverse_confidence_threshold
|
57
|
+
@inverse ||= (1 - Licensee.confidence_threshold / 100.0).round(2)
|
58
|
+
end
|
53
59
|
end
|
54
60
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
ref: refs/heads/master
|
@@ -0,0 +1 @@
|
|
1
|
+
1acd060ebbbeac294200008657d9502130f93465
|
data/test/functions.rb
CHANGED
@@ -19,9 +19,11 @@ def license_from_path(path)
|
|
19
19
|
license
|
20
20
|
end
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
# Add random words to the end of a license to test similarity tollerances
|
23
|
+
def chaos_monkey(string, count: 5)
|
24
|
+
ipsum = %w[lorem ipsum dolor sit amet consectetur adipiscing elit]
|
25
|
+
Random.rand(count).times do
|
26
|
+
string << " #{ipsum[Random.rand(ipsum.length)]}"
|
25
27
|
end
|
26
28
|
string
|
27
29
|
end
|
@@ -35,15 +37,20 @@ def verify_license_file(license, chaos = false, wrap = false)
|
|
35
37
|
|
36
38
|
license_file = Licensee::Project::LicenseFile.new(text)
|
37
39
|
|
38
|
-
|
39
|
-
msg = "No match for #{expected}
|
40
|
-
|
41
|
-
|
40
|
+
detected = license_file.license
|
41
|
+
msg = "No match for #{expected}.\n"
|
42
|
+
matcher = Licensee::Matchers::Dice.new(license_file)
|
43
|
+
matcher.potential_licenses.each do |potential_license|
|
44
|
+
msg << "Potential license: #{potential_license.key}\n"
|
45
|
+
msg << "Potential similiarity: #{potential_license.similarity(license_file)}\n"
|
46
|
+
end
|
47
|
+
msg << "Text: #{license_file.content_normalized}"
|
48
|
+
assert detected, msg
|
42
49
|
|
43
|
-
msg = "Expeceted #{expected} but got #{
|
50
|
+
msg = "Expeceted #{expected} but got #{detected.key} for .match. "
|
44
51
|
msg << "Confidence: #{license_file.confidence}. "
|
45
52
|
msg << "Method: #{license_file.matcher.class}"
|
46
|
-
assert_equal expected,
|
53
|
+
assert_equal expected, detected.key, msg
|
47
54
|
end
|
48
55
|
|
49
56
|
def wrap(text, line_width = 80)
|
data/test/{test_licensee_copyright_matcher.rb → licensee/matchers/test_copyright_matcher.rb}
RENAMED
@@ -26,6 +26,12 @@ class TestLicenseeCopyrightMatchers < Minitest::Test
|
|
26
26
|
assert_equal 'no-license', Licensee::Matchers::Copyright.new(file).match.key
|
27
27
|
end
|
28
28
|
|
29
|
+
should 'match (c) copyright notices' do
|
30
|
+
text = '(C) 2015 Ben Balter'
|
31
|
+
file = Licensee::Project::LicenseFile.new(text)
|
32
|
+
assert_equal 'no-license', Licensee::Matchers::Copyright.new(file).match.key
|
33
|
+
end
|
34
|
+
|
29
35
|
should 'not false positive' do
|
30
36
|
path = Licensee::License.find('mit').path
|
31
37
|
text = File.read(path, encoding: 'utf-8').split('---').last
|
@@ -6,6 +6,12 @@ class TestLicenseeDiceMatchers < Minitest::Test
|
|
6
6
|
@mit = Licensee::Project::LicenseFile.new(text)
|
7
7
|
end
|
8
8
|
|
9
|
+
def concat_licenses(*args)
|
10
|
+
args.map do |license|
|
11
|
+
license_from_path(Licensee::License.find(license).path)
|
12
|
+
end.join("\n")
|
13
|
+
end
|
14
|
+
|
9
15
|
should 'match the license' do
|
10
16
|
assert_equal 'mit', Licensee::Matchers::Dice.new(@mit).match.key
|
11
17
|
end
|
@@ -15,7 +21,10 @@ class TestLicenseeDiceMatchers < Minitest::Test
|
|
15
21
|
assert matcher.confidence > 95, "#{matcher.confidence} < 95"
|
16
22
|
end
|
17
23
|
|
18
|
-
should '
|
19
|
-
|
24
|
+
should 'know when two licenses have be concatenated' do
|
25
|
+
text = concat_licenses('mit', 'gpl-2.0')
|
26
|
+
license = Licensee::Project::LicenseFile.new(text)
|
27
|
+
matcher = Licensee::Matchers::Dice.new(license)
|
28
|
+
refute matcher.match
|
20
29
|
end
|
21
30
|
end
|
@@ -14,4 +14,12 @@ class TestLicenseeExactMatchers < Minitest::Test
|
|
14
14
|
should 'know the match confidence' do
|
15
15
|
assert_equal 100, Licensee::Matchers::Exact.new(@mit).confidence
|
16
16
|
end
|
17
|
+
|
18
|
+
should 'require the file to be the same length' do
|
19
|
+
path = Licensee::License.find('mit').path
|
20
|
+
text = File.read(path, encoding: 'utf-8').split('---').last
|
21
|
+
text << ' MIT'
|
22
|
+
license = Licensee::Project::LicenseFile.new(text)
|
23
|
+
refute Licensee::Matchers::Exact.new(license).match
|
24
|
+
end
|
17
25
|
end
|
@@ -2,7 +2,7 @@ require 'helper'
|
|
2
2
|
|
3
3
|
class TestLicenseeGemspecMatchers < Minitest::Test
|
4
4
|
should 'detect its own license' do
|
5
|
-
root = File.expand_path '
|
5
|
+
root = File.expand_path '../../../', File.dirname(__FILE__)
|
6
6
|
project = Licensee::GitProject.new(root, detect_packages: true)
|
7
7
|
matcher = Licensee::Matchers::Gemspec.new(project.package_file)
|
8
8
|
assert_equal 'mit', matcher.send(:license_property)
|
data/test/{test_licensee_npm_bower_matcher.rb → licensee/matchers/test_npm_bower_matcher.rb}
RENAMED
File without changes
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class PackageMatcherTestHelper < Licensee::Matchers::Package
|
4
|
+
attr_accessor :license_property, :file
|
5
|
+
end
|
6
|
+
|
7
|
+
class TestLicenseePackageMatcher < Minitest::Test
|
8
|
+
def setup
|
9
|
+
pkg = File.read fixture_path('npm/package.json')
|
10
|
+
@file = Licensee::Project::PackageInfo.new(pkg)
|
11
|
+
@matcher = PackageMatcherTestHelper.new(@file)
|
12
|
+
@matcher.license_property = 'mit'
|
13
|
+
end
|
14
|
+
|
15
|
+
should 'store the file' do
|
16
|
+
assert_equal @matcher.file, @file
|
17
|
+
end
|
18
|
+
|
19
|
+
should 'match' do
|
20
|
+
assert @matcher.match
|
21
|
+
assert_equal 'mit', @matcher.match.key
|
22
|
+
end
|
23
|
+
|
24
|
+
should 'return the confidence' do
|
25
|
+
assert_equal 90, @matcher.confidence
|
26
|
+
end
|
27
|
+
end
|
@@ -55,4 +55,19 @@ class TestLicenseeLicenseFile < Minitest::Test
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
58
|
+
|
59
|
+
context 'LGPL scoring' do
|
60
|
+
{
|
61
|
+
'COPYING.lesser' => 1,
|
62
|
+
'copying.lesser' => 1,
|
63
|
+
'license.lesser' => 0,
|
64
|
+
'LICENSE.md' => 0,
|
65
|
+
'FOO.md' => 0
|
66
|
+
}.each do |filename, expected|
|
67
|
+
should "score a license named `#{filename}` as `#{expected}`" do
|
68
|
+
score = Licensee::Project::LicenseFile.lesser_gpl_score(filename)
|
69
|
+
assert_equal expected, score
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
58
73
|
end
|
File without changes
|
File without changes
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class ContentHelperTestHelper
|
4
|
+
include Licensee::ContentHelper
|
5
|
+
attr_accessor :content
|
6
|
+
|
7
|
+
DEFAULT_CONTENT = <<-EOS.freeze
|
8
|
+
Copyright 2016 Ben Balter
|
9
|
+
|
10
|
+
The made
|
11
|
+
up license.
|
12
|
+
EOS
|
13
|
+
|
14
|
+
def initialize(content = nil)
|
15
|
+
@content = content || DEFAULT_CONTENT
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class TestLicenseeContentHelper < Minitest::Test
|
20
|
+
def setup
|
21
|
+
@helper = ContentHelperTestHelper.new
|
22
|
+
end
|
23
|
+
|
24
|
+
should 'normalize the content' do
|
25
|
+
assert_equal 'the made up license.', @helper.content_normalized
|
26
|
+
end
|
27
|
+
|
28
|
+
should 'generate the hash' do
|
29
|
+
assert_equal '3c59634b9fae4396a76a978f3f6aa718ed790a9a', @helper.hash
|
30
|
+
end
|
31
|
+
|
32
|
+
should 'calculate the length' do
|
33
|
+
assert_equal 20, @helper.length
|
34
|
+
end
|
35
|
+
|
36
|
+
should 'know the max delta' do
|
37
|
+
assert_equal 1, @helper.max_delta
|
38
|
+
end
|
39
|
+
|
40
|
+
should 'build the wordset' do
|
41
|
+
assert_equal %w(the made up license).to_set, @helper.wordset
|
42
|
+
end
|
43
|
+
|
44
|
+
should 'calculate the length delta' do
|
45
|
+
other = ContentHelperTestHelper.new 'asdf'
|
46
|
+
assert_equal 16, @helper.length_delta(other)
|
47
|
+
end
|
48
|
+
|
49
|
+
should 'calculate the similarity' do
|
50
|
+
other = ContentHelperTestHelper.new 'asdf'
|
51
|
+
assert_equal 0, @helper.similarity(other)
|
52
|
+
|
53
|
+
other = ContentHelperTestHelper.new 'Not really the made up license'
|
54
|
+
assert_equal 80.0, @helper.similarity(other)
|
55
|
+
end
|
56
|
+
end
|
@@ -117,6 +117,17 @@ class TestLicenseeLicense < Minitest::Test
|
|
117
117
|
assert_equal '750260c322080bab4c19fd55eb78bc73e1ae8f11', @license.hash
|
118
118
|
end
|
119
119
|
|
120
|
+
should "recognize GPL'd licenses" do
|
121
|
+
license = Licensee::License.new 'gpl-2.0'
|
122
|
+
assert license.gpl?
|
123
|
+
|
124
|
+
license = Licensee::License.new 'gpl-3.0'
|
125
|
+
assert license.gpl?
|
126
|
+
|
127
|
+
license = Licensee::License.new 'mit'
|
128
|
+
refute license.gpl?
|
129
|
+
end
|
130
|
+
|
120
131
|
describe 'name without version' do
|
121
132
|
should 'strip the version from the license name' do
|
122
133
|
expected = 'GNU Affero General Public License'
|
@@ -72,6 +72,11 @@ class TestLicenseeProject < Minitest::Test
|
|
72
72
|
project = make_project 'no-license.git'
|
73
73
|
assert_equal nil, project.license
|
74
74
|
end
|
75
|
+
|
76
|
+
should 'detect an LGPL licensed project with LICENSE.lesser' do
|
77
|
+
project = make_project 'lgpl.git'
|
78
|
+
assert_equal 'lgpl-3.0', project.license.key
|
79
|
+
end
|
75
80
|
end
|
76
81
|
end
|
77
82
|
|
File without changes
|
data/test/test_licensee.rb
CHANGED
@@ -24,13 +24,17 @@ class TestLicensee < Minitest::Test
|
|
24
24
|
|
25
25
|
context 'confidence threshold' do
|
26
26
|
should 'return the confidence threshold' do
|
27
|
-
assert_equal
|
27
|
+
assert_equal 95, Licensee.confidence_threshold
|
28
28
|
end
|
29
29
|
|
30
30
|
should 'let the user override the confidence threshold' do
|
31
31
|
Licensee.confidence_threshold = 50
|
32
32
|
assert_equal 50, Licensee.confidence_threshold
|
33
|
-
Licensee.confidence_threshold =
|
33
|
+
Licensee.confidence_threshold = 95
|
34
|
+
end
|
35
|
+
|
36
|
+
should 'return the inverse of the confidence threshold' do
|
37
|
+
assert_equal 0.05, Licensee.inverse_confidence_threshold
|
34
38
|
end
|
35
39
|
end
|
36
40
|
end
|