licensee 8.3.1 → 8.4.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/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
|