license_finder 0.9.5.1 → 1.0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +9 -0
  4. data/CHANGELOG.rdoc +9 -0
  5. data/MIT.LICENSE +20 -0
  6. data/db/migrate/201401302113_re_reassociate_license.rb +23 -0
  7. data/features/gradle_dependencies.feature +9 -0
  8. data/features/maven_dependencies.feature +9 -0
  9. data/features/step_definitions/gradle_steps.rb +8 -0
  10. data/features/step_definitions/maven_steps.rb +8 -0
  11. data/features/step_definitions/node_steps.rb +1 -1
  12. data/features/step_definitions/set_license_steps.rb +0 -1
  13. data/features/step_definitions/shared_steps.rb +26 -13
  14. data/lib/license_finder.rb +6 -1
  15. data/lib/license_finder/cli.rb +13 -9
  16. data/lib/license_finder/configuration.rb +113 -72
  17. data/lib/license_finder/dependency_manager.rb +12 -7
  18. data/lib/license_finder/license.rb +39 -65
  19. data/lib/license_finder/license/any_matcher.rb +13 -0
  20. data/lib/license_finder/license/definitions.rb +106 -0
  21. data/lib/license_finder/license/header_matcher.rb +10 -0
  22. data/lib/license_finder/license/matcher.rb +17 -0
  23. data/lib/license_finder/license/template.rb +16 -0
  24. data/lib/license_finder/license/text.rb +19 -0
  25. data/lib/license_finder/license_url.rb +1 -4
  26. data/lib/license_finder/package.rb +18 -2
  27. data/lib/license_finder/package_managers/bower_package.rb +3 -17
  28. data/lib/license_finder/package_managers/bundler_package.rb +2 -2
  29. data/lib/license_finder/package_managers/gradle.rb +29 -0
  30. data/lib/license_finder/package_managers/gradle_package.rb +41 -0
  31. data/lib/license_finder/package_managers/maven.rb +31 -0
  32. data/lib/license_finder/package_managers/maven_package.rb +46 -0
  33. data/lib/license_finder/package_managers/npm_package.rb +2 -16
  34. data/lib/license_finder/package_managers/pip_package.rb +7 -7
  35. data/lib/license_finder/package_saver.rb +1 -1
  36. data/lib/license_finder/possible_license_file.rb +1 -5
  37. data/lib/license_finder/possible_license_files.rb +4 -2
  38. data/lib/license_finder/reports/dependency_report.rb +5 -1
  39. data/lib/license_finder/reports/detailed_text_report.rb +0 -1
  40. data/lib/license_finder/reports/formatted_report.rb +21 -0
  41. data/lib/license_finder/reports/html_report.rb +1 -21
  42. data/lib/license_finder/reports/markdown_report.rb +1 -21
  43. data/lib/license_finder/reports/reporter.rb +8 -7
  44. data/lib/license_finder/reports/text_report.rb +0 -2
  45. data/lib/license_finder/tables.rb +1 -1
  46. data/lib/license_finder/tables/dependency.rb +12 -12
  47. data/lib/license_finder/yml_to_sql.rb +4 -4
  48. data/license_finder.gemspec +3 -2
  49. data/readme.md +10 -1
  50. data/release/publish.sh +10 -7
  51. data/spec/fixtures/build.gradle +24 -0
  52. data/spec/fixtures/pom.xml +19 -0
  53. data/spec/lib/license_finder/cli_spec.rb +13 -3
  54. data/spec/lib/license_finder/configuration_spec.rb +121 -74
  55. data/spec/lib/license_finder/dependency_manager_spec.rb +34 -16
  56. data/spec/lib/license_finder/license/{new_bsd_spec.rb → definitions_spec.rb} +93 -7
  57. data/spec/lib/license_finder/license_spec.rb +72 -26
  58. data/spec/lib/license_finder/license_url_spec.rb +10 -14
  59. data/spec/lib/license_finder/package_managers/bower_package_spec.rb +17 -5
  60. data/spec/lib/license_finder/package_managers/bundler_package_spec.rb +2 -2
  61. data/spec/lib/license_finder/package_managers/gradle_package_spec.rb +66 -0
  62. data/spec/lib/license_finder/package_managers/gradle_spec.rb +89 -0
  63. data/spec/lib/license_finder/package_managers/maven_package_spec.rb +72 -0
  64. data/spec/lib/license_finder/package_managers/maven_spec.rb +115 -0
  65. data/spec/lib/license_finder/package_managers/npm_package_spec.rb +17 -3
  66. data/spec/lib/license_finder/package_managers/pip_package_spec.rb +27 -5
  67. data/spec/lib/license_finder/possible_license_file_spec.rb +2 -2
  68. data/spec/lib/license_finder/{detailed_text_report_spec.rb → reports/detailed_text_report_spec.rb} +0 -0
  69. data/spec/lib/license_finder/{html_report_spec.rb → reports/html_report_spec.rb} +0 -0
  70. data/spec/lib/license_finder/{markdown_report_spec.rb → reports/markdown_report_spec.rb} +0 -0
  71. data/spec/lib/license_finder/reports/reporter_spec.rb +33 -0
  72. data/spec/lib/license_finder/{text_report_spec.rb → reports/text_report_spec.rb} +0 -0
  73. data/spec/lib/license_finder/tables/dependency_spec.rb +1 -2
  74. data/spec/lib/license_finder/tables/license_alias_spec.rb +1 -2
  75. data/spec/lib/license_finder/yml_to_sql_spec.rb +10 -11
  76. data/spec/lib/license_finder_spec.rb +5 -71
  77. metadata +64 -53
  78. data/features/rails_rake.feature +0 -9
  79. data/features/step_definitions/rails_rake_steps.rb +0 -12
  80. data/lib/license_finder/license/apache2.rb +0 -8
  81. data/lib/license_finder/license/bsd.rb +0 -4
  82. data/lib/license_finder/license/gplv2.rb +0 -4
  83. data/lib/license_finder/license/isc.rb +0 -3
  84. data/lib/license_finder/license/lgpl.rb +0 -4
  85. data/lib/license_finder/license/mit.rb +0 -23
  86. data/lib/license_finder/license/new_bsd.rb +0 -27
  87. data/lib/license_finder/license/python.rb +0 -8
  88. data/lib/license_finder/license/ruby.rb +0 -11
  89. data/lib/license_finder/license/simplified_bsd.rb +0 -8
  90. data/lib/license_finder/railtie.rb +0 -7
  91. data/lib/tasks/license_finder.rake +0 -7
  92. data/spec/lib/license_finder/license/apache_spec.rb +0 -7
  93. data/spec/lib/license_finder/license/bsd_spec.rb +0 -41
  94. data/spec/lib/license_finder/license/gplv2_spec.rb +0 -7
  95. data/spec/lib/license_finder/license/isc_spec.rb +0 -7
  96. data/spec/lib/license_finder/license/lgpl_spec.rb +0 -7
  97. data/spec/lib/license_finder/license/mit_spec.rb +0 -33
  98. data/spec/lib/license_finder/license/python_spec.rb +0 -7
  99. data/spec/lib/license_finder/license/ruby_spec.rb +0 -19
  100. data/spec/lib/license_finder/license/simplified_bsd_spec.rb +0 -7
  101. data/spec/lib/license_finder/reporter_spec.rb +0 -46
  102. data/spec/support/license_examples.rb +0 -30
@@ -15,7 +15,7 @@ module LicenseFinder
15
15
 
16
16
  modifying {
17
17
  dependency = Dependency.new(manual: true, name: name, version: version)
18
- dependency.license = LicenseAlias.create(name: license)
18
+ dependency.license = LicenseAlias.named(license)
19
19
  dependency.save
20
20
  }
21
21
  end
@@ -33,16 +33,15 @@ module LicenseFinder
33
33
  end
34
34
 
35
35
  def self.modifying
36
- checksum_before_modifying = if File.exists? LicenseFinder.config.database_uri
37
- Digest::SHA2.file(LicenseFinder.config.database_uri).hexdigest
38
- end
36
+ database_file = LicenseFinder.config.artifacts.database_file
37
+ checksum_before_modifying = checksum(database_file)
39
38
  result = yield
40
- checksum_after_modifying = Digest::SHA2.file(LicenseFinder.config.database_uri).hexdigest
39
+ checksum_after_modifying = checksum(database_file)
41
40
 
42
41
  unless checksum_after_modifying == checksum_before_modifying
43
42
  Reporter.write_reports
44
43
  end
45
- unless File.exists? LicenseFinder.config.dependencies_html
44
+ unless LicenseFinder.config.artifacts.html_file.exist?
46
45
  Reporter.write_reports
47
46
  end
48
47
 
@@ -56,7 +55,7 @@ module LicenseFinder
56
55
  end
57
56
 
58
57
  def self.package_managers
59
- [Bundler, NPM, Pip, Bower]
58
+ [Bundler, NPM, Pip, Bower, Maven, Gradle]
60
59
  end
61
60
 
62
61
  def self.find_by_name(name, scope = Dependency)
@@ -64,6 +63,12 @@ module LicenseFinder
64
63
  raise Error.new("could not find dependency named #{name}") unless dep
65
64
  dep
66
65
  end
66
+
67
+ def self.checksum(database_file)
68
+ if database_file.exist?
69
+ Digest::SHA2.file(database_file).hexdigest
70
+ end
71
+ end
67
72
  end
68
73
  end
69
74
 
@@ -1,90 +1,64 @@
1
1
  module LicenseFinder
2
- module License
2
+ class License
3
3
  class << self
4
4
  def all
5
5
  @all ||= []
6
6
  end
7
7
 
8
- def find_by_name(license_name)
9
- all.detect { |l| l.names.map(&:downcase).include? license_name.to_s.downcase }
10
- end
11
- end
12
-
13
- class Text
14
- def initialize(text)
15
- @text = normalized(text)
16
- end
17
-
18
- def to_s
19
- @text
8
+ def find_by_name(name)
9
+ all.detect { |l| l.matches_name? name } || UnknownLicense.new(name)
20
10
  end
21
11
 
22
- private
23
-
24
- def normalized(text)
25
- text.gsub(/\s+/, ' ').gsub(/['`"]{1,2}/, "\"")
12
+ def find_by_text(text)
13
+ all.detect { |l| l.matches_text? text } || UnknownLicense.new
26
14
  end
27
15
  end
28
16
 
29
- class Base
30
- class << self
31
- attr_accessor :license_url, :alternative_names
32
-
33
- def inherited(descendant)
34
- License.all << descendant
35
- end
36
-
37
- def names
38
- ([demodulized_name, pretty_name] + self.alternative_names).uniq
39
- end
17
+ autoload :Text, "license_finder/license/text"
18
+ autoload :Template, "license_finder/license/template"
19
+ autoload :Matcher, "license_finder/license/matcher"
20
+ autoload :HeaderMatcher, "license_finder/license/header_matcher"
21
+ autoload :AnyMatcher, "license_finder/license/any_matcher"
40
22
 
41
- def alternative_names
42
- @alternative_names ||= []
43
- end
23
+ attr_reader :url, :pretty_name
44
24
 
45
- def demodulized_name
46
- name.gsub(/^.*::/, '')
47
- end
48
-
49
- def slug
50
- demodulized_name.downcase
51
- end
25
+ def initialize(settings)
26
+ @short_name = settings.fetch(:short_name)
27
+ @pretty_name = settings.fetch(:pretty_name, short_name)
28
+ @other_names = settings.fetch(:other_names, [])
29
+ @url = settings.fetch(:url)
30
+ @matcher = settings.fetch(:matcher) { Matcher.from_template(Template.named(short_name)) }
31
+ end
52
32
 
53
- def pretty_name
54
- demodulized_name
55
- end
33
+ def matches_name?(name)
34
+ names.map(&:downcase).include? name.to_s.downcase
35
+ end
56
36
 
57
- def license_text
58
- unless defined?(@license_text)
59
- template = ROOT_PATH.join("data", "licenses", "#{demodulized_name}.txt")
37
+ def matches_text?(text)
38
+ matcher.matches_text?(text)
39
+ end
60
40
 
61
- @license_text = Text.new(template.read).to_s if template.exist?
62
- end
63
- @license_text
64
- end
41
+ private
65
42
 
66
- def license_regex
67
- /#{Regexp.escape(license_text).gsub(/<[^<>]+>/, '(.*)')}/ if license_text
68
- end
69
- end
43
+ attr_reader :short_name, :other_names, :matcher
70
44
 
71
- def initialize(text)
72
- self.text = text
73
- end
45
+ def names
46
+ ([short_name, pretty_name] + other_names).uniq
47
+ end
48
+ end
74
49
 
75
- attr_reader :text
50
+ class UnknownLicense
51
+ attr_reader :pretty_name
76
52
 
77
- def text=(text)
78
- @text = Text.new(text).to_s
79
- end
53
+ def initialize(name = nil)
54
+ @pretty_name = name
55
+ end
56
+ def url; end
80
57
 
81
- def matches?
82
- !!(text =~ self.class.license_regex if self.class.license_regex)
83
- end
58
+ def ==(other)
59
+ pretty_name.eql?(other.pretty_name)
84
60
  end
85
61
  end
86
62
  end
87
63
 
88
- Pathname.glob(LicenseFinder::ROOT_PATH.join('license_finder', 'license', "*.rb")) do |license|
89
- require license
90
- end
64
+ require LicenseFinder::ROOT_PATH.join("license_finder", "license", "definitions.rb")
@@ -0,0 +1,13 @@
1
+ module LicenseFinder
2
+ class License
3
+ class AnyMatcher
4
+ def initialize(*matchers)
5
+ @matchers = matchers
6
+ end
7
+
8
+ def matches_text?(text)
9
+ @matchers.any? { |m| m.matches_text? text }
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,106 @@
1
+ class LicenseFinder::License
2
+ def self.mit_matcher
3
+ url_regexp = %r{MIT Licen[sc]e.*http://(?:www\.)?opensource\.org/licenses/mit-license}
4
+ header_regexp = /The MIT Licen[sc]e/
5
+ one_liner_regexp = /is released under the MIT licen[sc]e/
6
+
7
+ AnyMatcher.new(
8
+ Matcher.from_template(Template.named("MIT")),
9
+ Matcher.new(url_regexp),
10
+ HeaderMatcher.new(Matcher.new(header_regexp)),
11
+ Matcher.new(one_liner_regexp)
12
+ )
13
+ end
14
+
15
+ def self.new_bsd_matcher
16
+ template = Template.named("NewBSD")
17
+ alternate_content = template.content.gsub(
18
+ "Neither the name of <organization> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.",
19
+ "The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission."
20
+ )
21
+
22
+ AnyMatcher.new(
23
+ Matcher.from_template(template),
24
+ Matcher.from_text(alternate_content)
25
+ )
26
+ end
27
+
28
+ def self.ruby_license_url
29
+ "http://www.ruby-lang.org/en/LICENSE.txt"
30
+ end
31
+
32
+ def self.ruby_matcher
33
+ url_regex = Regexp.new(Regexp.escape(ruby_license_url))
34
+
35
+ AnyMatcher.new(
36
+ Matcher.from_template(Template.named("Ruby")),
37
+ Matcher.new(url_regex)
38
+ )
39
+ end
40
+
41
+ all << new(
42
+ short_name: "Apache2",
43
+ pretty_name: "Apache 2.0",
44
+ other_names: ["Apache-2.0", "Apache Software License", "Apache License 2.0", "Apache License Version 2.0", "Apache Public License 2.0"],
45
+ url: "http://www.apache.org/licenses/LICENSE-2.0.txt"
46
+ )
47
+
48
+ all << new(
49
+ short_name: "BSD",
50
+ other_names: ["BSD4", "bsd-old", "4-clause BSD", "BSD-4-Clause", "BSD License"],
51
+ url: "http://en.wikipedia.org/wiki/BSD_licenses#4-clause_license_.28original_.22BSD_License.22.29"
52
+ )
53
+
54
+ all << new(
55
+ short_name: "GPLv2",
56
+ other_names: ["GPL V2", "gpl-v2", "GNU GENERAL PUBLIC LICENSE Version 2"],
57
+ url: "http://www.gnu.org/licenses/gpl-2.0.txt"
58
+ )
59
+
60
+ all << new(
61
+ short_name: "ISC",
62
+ url: "http://en.wikipedia.org/wiki/ISC_license"
63
+ )
64
+
65
+ all << new(
66
+ short_name: "LGPL",
67
+ other_names: ["LGPL-3", "LGPLv3", "LGPL-3.0"],
68
+ url: "http://www.gnu.org/licenses/lgpl.txt"
69
+ )
70
+
71
+ all << new(
72
+ short_name: "MIT",
73
+ other_names: ["Expat", "MIT license", "MIT License"],
74
+ url: "http://opensource.org/licenses/mit-license",
75
+ matcher: mit_matcher
76
+ )
77
+
78
+ all << new(
79
+ short_name: "NewBSD",
80
+ pretty_name: "New BSD",
81
+ other_names: ["Modified BSD", "BSD3", "BSD-3", "3-clause BSD", "BSD-3-Clause"],
82
+ url: "http://opensource.org/licenses/BSD-3-Clause",
83
+ matcher: new_bsd_matcher
84
+ )
85
+
86
+ all << new(
87
+ short_name: "Python",
88
+ pretty_name: "Python Software Foundation License",
89
+ other_names: ["PSF"],
90
+ url: "http://hg.python.org/cpython/raw-file/89ce323357db/LICENSE"
91
+ )
92
+
93
+ all << new(
94
+ short_name: "Ruby",
95
+ pretty_name: "ruby",
96
+ url: ruby_license_url,
97
+ matcher: ruby_matcher
98
+ )
99
+
100
+ all << new(
101
+ short_name: "SimplifiedBSD",
102
+ pretty_name: "Simplified BSD",
103
+ other_names: ["FreeBSD", "2-clause BSD", "BSD-2-Clause"],
104
+ url: "http://opensource.org/licenses/bsd-license"
105
+ )
106
+ end
@@ -0,0 +1,10 @@
1
+ module LicenseFinder
2
+ class License
3
+ HeaderMatcher = Struct.new(:base_matcher) do
4
+ def matches_text?(text)
5
+ header = text.split("\n").first || ''
6
+ base_matcher.matches_text?(header)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,17 @@
1
+ module LicenseFinder
2
+ class License
3
+ Matcher = Struct.new(:regexp) do
4
+ def self.from_template(template)
5
+ from_text(template.content)
6
+ end
7
+
8
+ def self.from_text(text)
9
+ new(Text.compile_to_regex(text))
10
+ end
11
+
12
+ def matches_text?(text)
13
+ !!(Text.normalize_punctuation(text) =~ regexp)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ module LicenseFinder
2
+ class License
3
+ class Template
4
+ def self.named(name)
5
+ path = ROOT_PATH.join("data", "licenses", "#{name}.txt")
6
+ new(path.read)
7
+ end
8
+
9
+ attr_reader :content
10
+
11
+ def initialize(raw_content)
12
+ @content = Text.normalize_punctuation(raw_content)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ module LicenseFinder
2
+ class License
3
+ module Text
4
+ SPACES = /\s+/
5
+ QUOTES = /['`"]{1,2}/
6
+ PLACEHOLDERS = /<[^<>]+>/
7
+
8
+ def self.normalize_punctuation(text)
9
+ text.gsub(SPACES, ' ')
10
+ .gsub(QUOTES, '"')
11
+ end
12
+
13
+ def self.compile_to_regex(text)
14
+ Regexp.new(Regexp.escape(text).gsub(PLACEHOLDERS, '(.*)'))
15
+ end
16
+ end
17
+ end
18
+ end
19
+
@@ -3,10 +3,7 @@ module LicenseFinder
3
3
  extend self
4
4
 
5
5
  def find_by_name(name)
6
- name = name.to_s
7
-
8
- license = License.find_by_name(name)
9
- license.license_url if license
6
+ License.find_by_name(name.to_s).url
10
7
  end
11
8
  end
12
9
  end
@@ -6,6 +6,17 @@ module LicenseFinder
6
6
  # it_behaves_like "it conforms to interface required by PackageSaver"
7
7
  # and see BundlerPackage, PipPackage and NpmPackage
8
8
  class Package
9
+ def self.extract_licenses_from_standard_spec(spec)
10
+ licenses = spec["licenses"] || [spec["license"]].compact
11
+ licenses.map do |license|
12
+ if license.is_a? Hash
13
+ license["type"]
14
+ else
15
+ license
16
+ end
17
+ end
18
+ end
19
+
9
20
  def license
10
21
  @license ||= determine_license
11
22
  end
@@ -13,11 +24,16 @@ module LicenseFinder
13
24
  private
14
25
 
15
26
  def determine_license
16
- license_from_spec || license_from_files || default_license
27
+ licenses = (licenses_from_spec + license_from_files).uniq
28
+ if licenses.length == 1
29
+ licenses.first
30
+ else
31
+ default_license
32
+ end
17
33
  end
18
34
 
19
35
  def license_from_files
20
- license_files.map(&:license).compact.first
36
+ license_files.map(&:license).compact
21
37
  end
22
38
 
23
39
  def license_files
@@ -39,25 +39,11 @@ module LicenseFinder
39
39
  attr_reader :module_metadata
40
40
 
41
41
  def install_path
42
- bower_module.fetch("canonicalDir", nil)
42
+ bower_module["canonicalDir"]
43
43
  end
44
44
 
45
- def license_from_spec
46
- license = module_metadata.fetch("licenses", []).first
47
-
48
- if license.is_a? Hash
49
- license = license.fetch("type", nil)
50
- end
51
-
52
- if license.nil?
53
- license = module_metadata.fetch("license", nil)
54
-
55
- if license.is_a? Hash
56
- license = license.fetch("type", nil)
57
- end
58
- end
59
-
60
- license
45
+ def licenses_from_spec
46
+ Package.extract_licenses_from_standard_spec(module_metadata)
61
47
  end
62
48
  end
63
49
  end