license_finder 1.1.1-java → 1.2-java

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.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -2
  3. data/CHANGELOG.rdoc +10 -0
  4. data/Gemfile +1 -1
  5. data/README.md +363 -0
  6. data/Rakefile +30 -1
  7. data/TODO.md +28 -0
  8. data/bin/license_finder_pip.py +18 -0
  9. data/db/migrate/201410031451_rename_dependency_license_name.rb +6 -0
  10. data/features/multiple_licenses.feature +9 -0
  11. data/features/step_definitions/cli_steps.rb +9 -9
  12. data/features/step_definitions/cocoapod_steps.rb +1 -1
  13. data/features/step_definitions/configure_bundler_groups_steps.rb +3 -3
  14. data/features/step_definitions/configure_whitelist_steps.rb +4 -4
  15. data/features/step_definitions/gradle_steps.rb +1 -1
  16. data/features/step_definitions/manually_added_steps.rb +3 -3
  17. data/features/step_definitions/manually_approved_steps.rb +5 -5
  18. data/features/step_definitions/manually_assigned_license_steps.rb +4 -4
  19. data/features/step_definitions/maven_steps.rb +1 -1
  20. data/features/step_definitions/multiple_licenses_steps.rb +14 -0
  21. data/features/step_definitions/node_steps.rb +1 -1
  22. data/features/step_definitions/python_steps.rb +1 -1
  23. data/features/step_definitions/report_csv_steps.rb +3 -3
  24. data/features/step_definitions/report_html_steps.rb +5 -5
  25. data/features/step_definitions/shared_steps.rb +23 -6
  26. data/lib/license_finder.rb +3 -0
  27. data/lib/license_finder/cli.rb +13 -34
  28. data/lib/license_finder/configuration.rb +8 -4
  29. data/lib/license_finder/dependency_manager.rb +25 -15
  30. data/lib/license_finder/license.rb +8 -0
  31. data/lib/license_finder/logger.rb +59 -0
  32. data/lib/license_finder/package.rb +37 -30
  33. data/lib/license_finder/package_manager.rb +20 -0
  34. data/lib/license_finder/package_managers/bower.rb +4 -9
  35. data/lib/license_finder/package_managers/bower_package.rb +2 -1
  36. data/lib/license_finder/package_managers/bundler.rb +26 -41
  37. data/lib/license_finder/package_managers/bundler_package.rb +6 -3
  38. data/lib/license_finder/package_managers/cocoa_pods.rb +18 -10
  39. data/lib/license_finder/package_managers/cocoa_pods_package.rb +4 -3
  40. data/lib/license_finder/package_managers/gradle.rb +7 -11
  41. data/lib/license_finder/package_managers/gradle_package.rb +2 -7
  42. data/lib/license_finder/package_managers/maven.rb +5 -9
  43. data/lib/license_finder/package_managers/maven_package.rb +4 -8
  44. data/lib/license_finder/package_managers/npm.rb +6 -10
  45. data/lib/license_finder/package_managers/npm_package.rb +2 -1
  46. data/lib/license_finder/package_managers/pip.rb +11 -24
  47. data/lib/license_finder/package_managers/pip_package.rb +2 -1
  48. data/lib/license_finder/package_saver.rb +2 -2
  49. data/lib/license_finder/platform.rb +4 -0
  50. data/lib/license_finder/possible_license_file.rb +4 -0
  51. data/lib/license_finder/possible_license_files.rb +2 -1
  52. data/lib/license_finder/reports/detailed_text_report.rb +1 -1
  53. data/lib/license_finder/reports/formatted_report.rb +1 -1
  54. data/lib/license_finder/tables/dependency.rb +22 -12
  55. data/lib/license_finder/yml_to_sql.rb +1 -1
  56. data/lib/templates/html_report.erb +4 -4
  57. data/lib/templates/markdown_report.erb +4 -4
  58. data/lib/templates/text_report.erb +1 -1
  59. data/license_finder.gemspec +28 -12
  60. data/spec/lib/license_finder/cli_spec.rb +193 -185
  61. data/spec/lib/license_finder/configuration_spec.rb +46 -47
  62. data/spec/lib/license_finder/dependency_manager_spec.rb +48 -44
  63. data/spec/lib/license_finder/license/definitions_spec.rb +26 -26
  64. data/spec/lib/license_finder/license_spec.rb +25 -25
  65. data/spec/lib/license_finder/package_managers/bower_package_spec.rb +33 -17
  66. data/spec/lib/license_finder/package_managers/bower_spec.rb +35 -35
  67. data/spec/lib/license_finder/package_managers/bundler_package_spec.rb +20 -15
  68. data/spec/lib/license_finder/package_managers/bundler_spec.rb +12 -19
  69. data/spec/lib/license_finder/package_managers/cocoa_pods_package_spec.rb +8 -5
  70. data/spec/lib/license_finder/package_managers/cocoa_pods_spec.rb +20 -22
  71. data/spec/lib/license_finder/package_managers/gradle_package_spec.rb +8 -5
  72. data/spec/lib/license_finder/package_managers/gradle_spec.rb +20 -20
  73. data/spec/lib/license_finder/package_managers/maven_package_spec.rb +8 -5
  74. data/spec/lib/license_finder/package_managers/maven_spec.rb +18 -18
  75. data/spec/lib/license_finder/package_managers/npm_package_spec.rb +36 -17
  76. data/spec/lib/license_finder/package_managers/npm_spec.rb +17 -17
  77. data/spec/lib/license_finder/package_managers/pip_package_spec.rb +16 -10
  78. data/spec/lib/license_finder/package_managers/pip_spec.rb +21 -18
  79. data/spec/lib/license_finder/package_saver_spec.rb +15 -25
  80. data/spec/lib/license_finder/possible_license_file_spec.rb +5 -4
  81. data/spec/lib/license_finder/possible_license_files_spec.rb +11 -5
  82. data/spec/lib/license_finder/reports/detailed_text_report_spec.rb +3 -3
  83. data/spec/lib/license_finder/reports/html_report_spec.rb +23 -23
  84. data/spec/lib/license_finder/reports/markdown_report_spec.rb +12 -12
  85. data/spec/lib/license_finder/reports/reporter_spec.rb +11 -11
  86. data/spec/lib/license_finder/reports/text_report_spec.rb +3 -3
  87. data/spec/lib/license_finder/tables/dependency_spec.rb +59 -41
  88. data/spec/lib/license_finder/yml_to_sql_spec.rb +21 -21
  89. data/spec/lib/license_finder_spec.rb +1 -1
  90. data/spec/spec_helper.rb +0 -13
  91. data/spec/support/shared_examples_for_package.rb +46 -0
  92. data/spec/support/shared_examples_for_package_manager.rb +15 -0
  93. metadata +19 -100
  94. data/readme.md +0 -259
@@ -4,12 +4,11 @@ module LicenseFinder
4
4
  def_delegators :gem_def, :summary, :description, :name, :homepage
5
5
 
6
6
  attr_reader :gem_def
7
- attr_accessor :children
8
7
 
9
- def initialize(gem_def, bundler_def)
8
+ def initialize(gem_def, bundler_def, options={})
9
+ super options
10
10
  @gem_def = gem_def
11
11
  @bundler_def = bundler_def
12
- @children = []
13
12
  end
14
13
 
15
14
  def groups
@@ -20,6 +19,10 @@ module LicenseFinder
20
19
  gem_def.version.to_s
21
20
  end
22
21
 
22
+ def children
23
+ gem_def.dependencies.map(&:name)
24
+ end
25
+
23
26
  private
24
27
 
25
28
  def install_path
@@ -1,12 +1,11 @@
1
1
  require "json"
2
2
 
3
3
  module LicenseFinder
4
- class CocoaPods
5
-
6
- def self.current_packages
4
+ class CocoaPods < PackageManager
5
+ def current_packages
7
6
  podfile = YAML.load_file(lockfile_path)
8
7
 
9
- acknowledgements = JSON.parse(`plutil -convert json -o - #{Pathname.new('Pods/Pods-acknowledgements.plist').expand_path}`)["PreferenceSpecifiers"]
8
+ acknowledgements = read_plist(acknowledgements_path)["PreferenceSpecifiers"]
10
9
 
11
10
  podfile["PODS"].map do |pod|
12
11
  pod = pod.keys.first if pod.is_a?(Hash)
@@ -17,19 +16,28 @@ module LicenseFinder
17
16
  end
18
17
  end
19
18
 
20
- def self.active?
21
- package_path.exist?
22
- end
23
-
24
19
  private
25
20
 
26
- def self.package_path
21
+ def package_path
27
22
  Pathname.new("Podfile")
28
23
  end
29
24
 
30
- def self.lockfile_path
25
+ def lockfile_path
31
26
  Pathname.new("Podfile.lock")
32
27
  end
33
28
 
29
+ def acknowledgements_path
30
+ filename = 'Pods-acknowledgements.plist'
31
+ directories = [
32
+ 'Pods', # cocoapods < 0.34
33
+ 'Pods/Target Support Files/Pods' # cocoapods >= 0.34
34
+ ]
35
+
36
+ directories.map { |dir| Pathname.new(File.join(dir, filename)) }.find(&:exist?)
37
+ end
38
+
39
+ def read_plist pathname
40
+ JSON.parse(`plutil -convert json -o - '#{pathname.expand_path}'`)
41
+ end
34
42
  end
35
43
  end
@@ -3,7 +3,8 @@ module LicenseFinder
3
3
  attr_reader :name, :version
4
4
  attr_reader :summary, :description, :homepage
5
5
 
6
- def initialize(name, version, license_text)
6
+ def initialize(name, version, license_text, options={})
7
+ super options
7
8
  @name = name
8
9
  @version = version
9
10
  @license_text = license_text
@@ -12,8 +13,8 @@ module LicenseFinder
12
13
  def groups; []; end
13
14
  def children; []; end
14
15
 
15
- def license
16
- License.find_by_text(@license_text.to_s) || default_license
16
+ def licenses
17
+ [License.find_by_text(@license_text.to_s) || default_license].to_set
17
18
  end
18
19
  end
19
20
  end
@@ -1,8 +1,8 @@
1
1
  require "xmlsimple"
2
2
 
3
3
  module LicenseFinder
4
- class Gradle
5
- def self.current_packages
4
+ class Gradle < PackageManager
5
+ def current_packages
6
6
  `#{LicenseFinder.config.gradle_command} downloadLicenses`
7
7
 
8
8
  xml = license_report.read
@@ -10,23 +10,19 @@ module LicenseFinder
10
10
  options = {
11
11
  'GroupTags' => { 'dependencies' => 'dependency' }
12
12
  }
13
- XmlSimple.xml_in(xml, options).fetch('dependency', []).map do |d|
14
- d["license"].reject! { |l| l["name"] == "No license found" }
15
- GradlePackage.new(d)
13
+ XmlSimple.xml_in(xml, options).fetch('dependency', []).map do |dep|
14
+ dep["license"].reject! { |l| l["name"] == "No license found" }
15
+ GradlePackage.new(dep, logger: logger)
16
16
  end
17
17
  end
18
18
 
19
- def self.active?
20
- package_path.exist?
21
- end
22
-
23
19
  private
24
20
 
25
- def self.license_report
21
+ def license_report
26
22
  Pathname.new('build/reports/license/dependency-license.xml')
27
23
  end
28
24
 
29
- def self.package_path
25
+ def package_path
30
26
  Pathname.new('build.gradle')
31
27
  end
32
28
  end
@@ -2,7 +2,8 @@ module LicenseFinder
2
2
  class GradlePackage < Package
3
3
  attr_reader :name, :version
4
4
 
5
- def initialize(gradle_dependency)
5
+ def initialize(gradle_dependency, options={})
6
+ super options
6
7
  @gradle_dependency = gradle_dependency
7
8
  @name = @gradle_dependency["name"].split(":")[1]
8
9
  @version = @gradle_dependency["name"].split(":")[2]
@@ -28,12 +29,6 @@ module LicenseFinder
28
29
  []
29
30
  end
30
31
 
31
- private
32
-
33
- def licenses_from_files
34
- []
35
- end
36
-
37
32
  def license_names_from_spec
38
33
  @gradle_dependency["license"].map { |l| l["name"] }
39
34
  end
@@ -1,8 +1,8 @@
1
1
  require "xmlsimple"
2
2
 
3
3
  module LicenseFinder
4
- class Maven
5
- def self.current_packages
4
+ class Maven < PackageManager
5
+ def current_packages
6
6
  `mvn license:download-licenses`
7
7
 
8
8
  xml = license_report.read
@@ -14,21 +14,17 @@ module LicenseFinder
14
14
  dependencies = XmlSimple.xml_in(xml, options)["dependencies"]
15
15
 
16
16
  dependencies.map do |dep|
17
- MavenPackage.new(dep)
17
+ MavenPackage.new(dep, logger: logger)
18
18
  end
19
19
  end
20
20
 
21
- def self.active?
22
- package_path.exist?
23
- end
24
-
25
21
  private
26
22
 
27
- def self.license_report
23
+ def license_report
28
24
  Pathname.new('target/generated-resources/licenses.xml')
29
25
  end
30
26
 
31
- def self.package_path
27
+ def package_path
32
28
  Pathname.new('pom.xml')
33
29
  end
34
30
  end
@@ -1,6 +1,9 @@
1
1
  module LicenseFinder
2
2
  class MavenPackage < Package
3
- def initialize(mvn_dependency)
3
+ attr_reader :mvn_dependency
4
+
5
+ def initialize(mvn_dependency, options={})
6
+ super options
4
7
  @mvn_dependency = mvn_dependency
5
8
  end
6
9
 
@@ -32,13 +35,6 @@ module LicenseFinder
32
35
  []
33
36
  end
34
37
 
35
- private
36
- attr_reader :mvn_dependency
37
-
38
- def licenses_from_files
39
- []
40
- end
41
-
42
38
  def license_names_from_spec
43
39
  mvn_dependency["licenses"].map { |l| l["name"] }
44
40
  end
@@ -1,25 +1,21 @@
1
1
  require 'json'
2
2
 
3
3
  module LicenseFinder
4
- class NPM
4
+ class NPM < PackageManager
5
5
  DEPENDENCY_GROUPS = ["dependencies", "devDependencies", "bundleDependencies", "bundledDependencies"]
6
6
 
7
- def self.current_packages
7
+ def current_packages
8
8
  json = npm_json
9
9
  dependencies = DEPENDENCY_GROUPS.map { |g| (json[g] || {}).values }.flatten(1).reject{ |d| d.is_a?(String) }
10
10
 
11
11
  dependencies.map do |node_module|
12
- NpmPackage.new(node_module)
12
+ NpmPackage.new(node_module, logger: logger)
13
13
  end
14
14
  end
15
15
 
16
- def self.active?
17
- package_path.exist?
18
- end
19
-
20
16
  private
21
17
 
22
- def self.npm_json
18
+ def npm_json
23
19
  command = "npm list --json --long"
24
20
  output, success = capture(command)
25
21
  if success
@@ -35,11 +31,11 @@ module LicenseFinder
35
31
  json
36
32
  end
37
33
 
38
- def self.capture(command)
34
+ def capture(command)
39
35
  [`#{command}`, $?.success?]
40
36
  end
41
37
 
42
- def self.package_path
38
+ def package_path
43
39
  Pathname.new('package.json')
44
40
  end
45
41
  end
@@ -1,6 +1,7 @@
1
1
  module LicenseFinder
2
2
  class NpmPackage < Package
3
- def initialize(node_module)
3
+ def initialize(node_module, options={})
4
+ super options
4
5
  @node_module = node_module
5
6
  end
6
7
 
@@ -2,40 +2,27 @@ require 'json'
2
2
  require 'httparty'
3
3
 
4
4
  module LicenseFinder
5
- class Pip
6
- GET_DEPENDENCIES_PY = <<-PYTHON.gsub(/\n+/, ";")
7
- from pip.util import get_installed_distributions
8
-
9
- dists = [(x.project_name, x.version, x.location) for x in get_installed_distributions()]
10
- dists = ["[\\\"{0}\\\", \\\"{1}\\\", \\\"{2}\\\"]".format(*dist) for dist in dists]
11
-
12
- print "[" + ",".join(dists) + "]"
13
- PYTHON
14
-
15
- def self.current_packages
16
- output = `python -c '#{GET_DEPENDENCIES_PY}'`
17
-
18
- JSON(output).map do |(name, version, install_dir)|
5
+ class Pip < PackageManager
6
+ def current_packages
7
+ output = `#{LicenseFinder::BIN_PATH.join("license_finder_pip.py")}`
8
+ JSON(output).map do |package|
19
9
  PipPackage.new(
20
- name,
21
- version,
22
- File.join(install_dir, name),
23
- pypi_def(name, version)
10
+ package["name"],
11
+ package["version"],
12
+ File.join(package["location"], package["name"]),
13
+ pypi_def(package["name"], package["version"]),
14
+ logger: logger
24
15
  )
25
16
  end
26
17
  end
27
18
 
28
- def self.active?
29
- requirements_path.exist?
30
- end
31
-
32
19
  private
33
20
 
34
- def self.requirements_path
21
+ def package_path
35
22
  Pathname.new('requirements.txt')
36
23
  end
37
24
 
38
- def self.pypi_def(name, version)
25
+ def pypi_def(name, version)
39
26
  response = HTTParty.get("https://pypi.python.org/pypi/#{name}/#{version}/json")
40
27
  if response.code == 200
41
28
  JSON.parse(response.body).fetch("info", {})
@@ -1,6 +1,7 @@
1
1
  module LicenseFinder
2
2
  class PipPackage < Package
3
- def initialize(name, version, install_path, pypi_def)
3
+ def initialize(name, version, install_path, pypi_def, options={})
4
+ super options
4
5
  @name = name
5
6
  @version = version
6
7
  @install_path = install_path
@@ -3,7 +3,7 @@ require 'forwardable'
3
3
  module LicenseFinder
4
4
  class PackageSaver
5
5
  extend Forwardable
6
- def_delegators :package, :license, :children, :groups, :summary, :description, :version, :homepage
6
+ def_delegators :package, :licenses, :children, :groups, :summary, :description, :version, :homepage
7
7
 
8
8
  attr_reader :dependency, :package
9
9
 
@@ -25,7 +25,7 @@ module LicenseFinder
25
25
  dependency.homepage = homepage
26
26
  dependency.bundler_group_names = groups.map(&:to_s)
27
27
  dependency.children_names = children
28
- dependency.apply_better_license license
28
+ dependency.set_licenses licenses
29
29
 
30
30
  # Only save *changed* dependencies. This ensures re-running
31
31
  # `license_finder` won't always update the DB, and therefore won't always
@@ -15,6 +15,10 @@ module LicenseFinder
15
15
  def self.java?
16
16
  RUBY_PLATFORM =~ /java/
17
17
  end
18
+
19
+ def self.darwin?
20
+ RUBY_PLATFORM =~ /darwin/
21
+ end
18
22
  end
19
23
  end
20
24
 
@@ -15,6 +15,10 @@ module LicenseFinder
15
15
  @text ||= @file_path.send(@file_path.respond_to?(:binread) ? :binread : :read)
16
16
  end
17
17
 
18
+ def path
19
+ File.join(@install_path, file_path)
20
+ end
21
+
18
22
  def license
19
23
  License.find_by_text(text)
20
24
  end
@@ -8,7 +8,7 @@ module LicenseFinder
8
8
  end
9
9
 
10
10
  def initialize(install_path)
11
- @install_path = Pathname(install_path)
11
+ @install_path = install_path ? Pathname(install_path) : nil
12
12
  end
13
13
 
14
14
  def find
@@ -28,6 +28,7 @@ module LicenseFinder
28
28
  end
29
29
 
30
30
  def candidate_files_and_dirs
31
+ return [] if install_path.nil?
31
32
  Pathname.glob(install_path.join('**', CANDIDATE_PATH_WILDCARD))
32
33
  end
33
34
 
@@ -8,7 +8,7 @@ module LicenseFinder
8
8
  csv << [
9
9
  s.name,
10
10
  s.version,
11
- s.license.name,
11
+ s.licenses.map(&:name).join(','),
12
12
  s.summary ? s.summary.strip : "",
13
13
  s.description ? s.description.strip : ""
14
14
  ]
@@ -7,7 +7,7 @@ module LicenseFinder
7
7
 
8
8
  def grouped_dependencies
9
9
  find_name = lambda do |dep|
10
- dep.license.name
10
+ dep.licenses.map(&:name).sort.join ', '
11
11
  end
12
12
 
13
13
  dependencies.group_by(&find_name).sort_by { |_, group| group.size }.reverse
@@ -1,10 +1,19 @@
1
+ require 'json'
2
+
1
3
  module LicenseFinder
2
4
  class Dependency < Sequel::Model
3
5
  plugin :boolean_readers
4
6
  plugin :composition
5
- composition :license,
6
- composer: ->(d) { License.find_by_name(d.license_name) },
7
- decomposer: ->(d) { self.license_name = license.name }
7
+ composition :licenses,
8
+ composer: ->(d) do
9
+ if d.license_names.nil?
10
+ [License.find_by_name(nil)].to_set
11
+ else
12
+ names = JSON.parse(d.license_names)
13
+ names.map { |n| License.find_by_name(n) }.to_set
14
+ end
15
+ end,
16
+ decomposer: ->(d) { self.license_names = licenses.map(&:name).to_json }
8
17
 
9
18
  one_to_one :manual_approval
10
19
  many_to_many :children, join_table: :ancestries, left_key: :parent_dependency_id, right_key: :child_dependency_id, class: self
@@ -58,26 +67,27 @@ module LicenseFinder
58
67
  end
59
68
 
60
69
  def whitelisted?
61
- license.whitelisted?
70
+ licenses.any? &:whitelisted?
62
71
  end
63
72
 
64
73
  def approved_manually?
65
74
  !!manual_approval
66
75
  end
67
76
 
77
+ def set_licenses(other_licenses)
78
+ return if license_assigned_manually?
79
+ other_licenses = other_licenses.to_set
80
+ if licenses != other_licenses
81
+ self.licenses = other_licenses
82
+ end
83
+ end
84
+
68
85
  def set_license_manually!(license)
69
- self.license = license
86
+ self.licenses = [license].to_set
70
87
  self.license_assigned_manually = true
71
88
  save
72
89
  end
73
90
 
74
- def apply_better_license(other_license)
75
- return if license_assigned_manually?
76
- if license.name != other_license.name
77
- self.license = other_license
78
- end
79
- end
80
-
81
91
  private
82
92
 
83
93
  def update_association_collection(association_name, names)