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
@@ -102,9 +102,13 @@ module LicenseFinder
102
102
  end
103
103
 
104
104
  def last_refreshed
105
- [database_file, text_file, detailed_text_file, html_file, markdown_file].map do |path|
106
- File.mtime(path)
107
- end.min
105
+ [
106
+ database_file,
107
+ text_file,
108
+ detailed_text_file,
109
+ html_file,
110
+ markdown_file
111
+ ].map(&:mtime).min
108
112
  end
109
113
  end
110
114
 
@@ -126,7 +130,7 @@ module LicenseFinder
126
130
  end
127
131
 
128
132
  def last_modified
129
- File.mtime(file)
133
+ file.mtime
130
134
  end
131
135
 
132
136
  private
@@ -1,8 +1,14 @@
1
1
  require 'digest'
2
2
 
3
3
  module LicenseFinder
4
- module DependencyManager
5
- def self.sync_with_package_managers
4
+ class DependencyManager
5
+ attr_reader :logger
6
+
7
+ def initialize options={}
8
+ @logger = options[:logger] || LicenseFinder::Logger::Default.new
9
+ end
10
+
11
+ def sync_with_package_managers options={}
6
12
  modifying {
7
13
  current_dependencies = PackageSaver.save_all(current_packages)
8
14
 
@@ -10,30 +16,30 @@ module LicenseFinder
10
16
  }
11
17
  end
12
18
 
13
- def self.manually_add(license, name, version)
19
+ def manually_add(license, name, version)
14
20
  raise Error.new("#{name} dependency already exists") unless Dependency.where(name: name).empty?
15
21
 
16
22
  modifying {
17
23
  dependency = Dependency.new(added_manually: true, name: name, version: version)
18
- dependency.license = License.find_by_name(license)
24
+ dependency.licenses = [License.find_by_name(license)].to_set
19
25
  dependency.save
20
26
  }
21
27
  end
22
28
 
23
- def self.manually_remove(name)
29
+ def manually_remove(name)
24
30
  modifying { find_by_name(name, Dependency.added_manually).destroy }
25
31
  end
26
32
 
27
- def self.license!(name, license_name)
33
+ def license!(name, license_name)
28
34
  license = License.find_by_name(license_name)
29
35
  modifying { find_by_name(name).set_license_manually!(license) }
30
36
  end
31
37
 
32
- def self.approve!(name, approver = nil, notes = nil)
38
+ def approve!(name, approver = nil, notes = nil)
33
39
  modifying { find_by_name(name).approve!(approver, notes) }
34
40
  end
35
41
 
36
- def self.modifying
42
+ def modifying
37
43
  checksum_before = checksum
38
44
  result = DB.transaction { yield }
39
45
  checksum_after = checksum
@@ -49,29 +55,33 @@ module LicenseFinder
49
55
 
50
56
  private # not really private, but it looks like it is!
51
57
 
52
- def self.reports_do_not_exist
58
+ def reports_do_not_exist
53
59
  !(LicenseFinder.config.artifacts.html_file.exist?)
54
60
  end
55
61
 
56
- def self.reports_are_stale
62
+ def reports_are_stale
57
63
  LicenseFinder.config.last_modified > LicenseFinder.config.artifacts.last_refreshed
58
64
  end
59
65
 
60
- def self.current_packages
61
- package_managers.select(&:active?).map(&:current_packages).flatten
66
+ def current_packages
67
+ package_managers.
68
+ map { |pm| pm.new(logger: logger) }.
69
+ select(&:active?).
70
+ map(&:current_packages).
71
+ flatten
62
72
  end
63
73
 
64
- def self.package_managers
74
+ def package_managers
65
75
  [Bundler, NPM, Pip, Bower, Maven, Gradle, CocoaPods]
66
76
  end
67
77
 
68
- def self.find_by_name(name, scope = Dependency)
78
+ def find_by_name(name, scope = Dependency)
69
79
  dep = scope.first(name: name)
70
80
  raise Error.new("could not find dependency named #{name}") unless dep
71
81
  dep
72
82
  end
73
83
 
74
- def self.checksum
84
+ def checksum
75
85
  database_file = LicenseFinder.config.artifacts.database_file
76
86
  if database_file.exist?
77
87
  Digest::SHA2.file(database_file).hexdigest
@@ -54,6 +54,14 @@ module LicenseFinder
54
54
  copy(whitelisted: true)
55
55
  end
56
56
 
57
+ def eql?(other)
58
+ name == other.name
59
+ end
60
+
61
+ def hash
62
+ name.hash
63
+ end
64
+
57
65
  private
58
66
 
59
67
  attr_reader :short_name, :pretty_name, :other_names
@@ -0,0 +1,59 @@
1
+ module LicenseFinder
2
+ module Logger
3
+ def self.new options={}
4
+ klass = if options[:quiet]
5
+ Quiet
6
+ elsif options[:debug]
7
+ Verbose
8
+ else
9
+ Progress
10
+ end
11
+ klass.new
12
+ end
13
+
14
+ class Base
15
+ def active package_manager, is_active
16
+ log package_manager, sprintf("%s active", (is_active ? "is" : "not"))
17
+ end
18
+
19
+ def package package_manager, package
20
+ dependencies = package.children
21
+ if dependencies.empty?
22
+ log package_manager, sprintf("package '%s' has no dependencies", package.name)
23
+ else
24
+ log package_manager, sprintf("package '%s' has dependencies:", package.name)
25
+ dependencies.each do |dep|
26
+ log package_manager, sprintf("- %s", dep)
27
+ end
28
+ end
29
+ end
30
+
31
+ def license package, package_name, license, how
32
+ log package, sprintf("package %s: found license '%s' %s", package_name, license, how)
33
+ end
34
+
35
+ def log prefix, string
36
+ raise NotImplementedError, "#log must be implemented"
37
+ end
38
+ end
39
+
40
+ class Quiet < Base
41
+ def log prefix, string
42
+ end
43
+ end
44
+
45
+ class Progress < Base
46
+ def log prefix, string
47
+ STDOUT.print(".") && STDOUT.flush
48
+ end
49
+ end
50
+
51
+ class Verbose < Base
52
+ def log prefix, string
53
+ STDOUT.printf("%s: %s\n", prefix, string)
54
+ end
55
+ end
56
+
57
+ Default = Quiet
58
+ end
59
+ end
@@ -3,9 +3,20 @@ module LicenseFinder
3
3
  # systems (gems, npm, pip, etc.) to a common interface.
4
4
  #
5
5
  # For guidance on adding a new system use the shared behavior
6
- # it_behaves_like "it conforms to interface required by PackageSaver"
7
- # and see BundlerPackage, PipPackage and NpmPackage
6
+ #
7
+ # it_behaves_like "a Package"
8
+ #
9
+ # Additional guidelines are:
10
+ #
11
+ # - if you're going to use Package#licenses ...
12
+ # - implement #licenses_names_from_spec
13
+ # - implement #install_path
14
+ # - else
15
+ # - implement #licenses
16
+ #
8
17
  class Package
18
+ attr_reader :logger
19
+
9
20
  def self.license_names_from_standard_spec(spec)
10
21
  licenses = spec["licenses"] || [spec["license"]].compact
11
22
  licenses = [licenses] unless licenses.is_a?(Array)
@@ -18,54 +29,50 @@ module LicenseFinder
18
29
  end
19
30
  end
20
31
 
21
- def license
22
- @license ||= determine_license
32
+ def initialize options={}
33
+ @logger = options[:logger] || LicenseFinder::Logger::Default.new
23
34
  end
24
35
 
25
- private
36
+ def licenses
37
+ @licenses ||= determine_license.to_set
38
+ end
26
39
 
27
40
  def determine_license
28
- if licenses_from_spec.any?
29
- choose_license_from licenses_from_spec
30
- elsif licenses_from_files.any?
31
- choose_license_from licenses_from_files
32
- else
33
- default_license
34
- end
35
- end
41
+ lfs = licenses_from_spec
42
+ return lfs if lfs.any?
36
43
 
37
- def choose_license_from licenses
38
- if ( licenses.uniq.size > 1 )
39
- License.find_by_name "multiple licenses: #{(licenses).map(&:name).uniq.join(', ')}"
40
- else
41
- licenses.first
42
- end
44
+ lff = licenses_from_files
45
+ return lff if lff.any?
46
+
47
+ [default_license].to_set
43
48
  end
44
49
 
45
50
  def licenses_from_spec
46
51
  license_names_from_spec.map do |name|
47
- License.find_by_name(name)
48
- end
52
+ License.find_by_name(name).tap do |license|
53
+ logger.license self.class, self.name, license.name, "from spec" if license
54
+ end
55
+ end.compact.to_set
49
56
  end
50
57
 
51
58
  def licenses_from_files
52
- license_files.map(&:license).compact
59
+ license_files.map do |license_file|
60
+ license_file.license.tap do |license|
61
+ logger.license self.class, self.name, license.name, "from file '#{license_file.path}'" if license
62
+ end
63
+ end.compact.to_set
53
64
  end
54
65
 
55
66
  def license_files
56
67
  PossibleLicenseFiles.find(install_path)
57
68
  end
58
69
 
59
- def multiple_licenses
60
- if ( licenses_from_spec.uniq.size > 1 )
61
- License.find_by_name "multiple licenses: #{(licenses_from_spec).map(&:name).uniq.join(', ')}"
62
- else
63
- License.find_by_name "multiple licenses: #{(licenses_from_files).map(&:name).uniq.join(', ')}"
64
- end
65
- end
66
-
67
70
  def default_license
68
71
  License.find_by_name nil
69
72
  end
73
+
74
+ def install_path
75
+ nil
76
+ end
70
77
  end
71
78
  end
@@ -0,0 +1,20 @@
1
+ module LicenseFinder
2
+ class PackageManager
3
+ attr_reader :logger
4
+
5
+ def initialize options={}
6
+ @logger = options[:logger] || LicenseFinder::Logger::Default.new
7
+ @package_path = options[:package_path] # dependency injection for tests
8
+ end
9
+
10
+ def active?
11
+ injected_package_path.exist?.tap { |is_active| logger.active self.class, is_active }
12
+ end
13
+
14
+ private
15
+
16
+ def injected_package_path
17
+ @package_path || package_path
18
+ end
19
+ end
20
+ end
@@ -1,25 +1,20 @@
1
1
  require 'json'
2
2
 
3
3
  module LicenseFinder
4
- class Bower
5
-
6
- def self.current_packages
4
+ class Bower < PackageManager
5
+ def current_packages
7
6
  output = `bower list --json`
8
7
 
9
8
  json = JSON(output)
10
9
 
11
10
  json.fetch("dependencies",[]).map do |package|
12
- BowerPackage.new(package[1])
11
+ BowerPackage.new(package[1], logger: logger)
13
12
  end
14
13
  end
15
14
 
16
- def self.active?
17
- package_path.exist?
18
- end
19
-
20
15
  private
21
16
 
22
- def self.package_path
17
+ def package_path
23
18
  Pathname.new('bower.json')
24
19
  end
25
20
  end
@@ -1,6 +1,7 @@
1
1
  module LicenseFinder
2
2
  class BowerPackage < Package
3
- def initialize(bower_module)
3
+ def initialize(bower_module, options={})
4
+ super options
4
5
  @bower_module = bower_module
5
6
  @module_metadata = bower_module.fetch("pkgMeta", Hash.new)
6
7
  end
@@ -1,48 +1,41 @@
1
1
  require "bundler"
2
2
 
3
3
  module LicenseFinder
4
- class Bundler
5
- class << self
6
- def current_packages(ignore_groups = LicenseFinder.config.ignore_groups, bundler_definition=nil)
7
- new(ignore_groups, bundler_definition).packages
8
- end
9
-
10
- def active?
11
- gemfile_path.exist?
12
- end
13
-
14
- def gemfile_path
15
- Pathname.new("Gemfile").expand_path
16
- end
4
+ class Bundler < PackageManager
5
+ def initialize options={}
6
+ super
7
+ @ignore_groups = options[:ignore_groups] # dependency injection for tests
8
+ @definition = options[:definition] # dependency injection for tests
17
9
  end
18
10
 
19
- def initialize(ignore_groups, bundler_definition=nil)
20
- @definition = bundler_definition || ::Bundler::Definition.build(self.class.gemfile_path, lockfile_path, nil)
21
- @ignore_groups = ignore_groups
22
- end
23
-
24
- def packages
25
- top_level_gems = Set.new
26
-
27
- packages = definition.specs_for(included_groups).map do |gem_def|
11
+ def current_packages
12
+ logger.log self.class, "including groups #{included_groups.inspect}"
13
+ definition.specs_for(included_groups).map do |gem_def|
28
14
  bundler_def = bundler_defs.detect { |bundler_def| bundler_def.name == gem_def.name }
29
-
30
- top_level_gems << format_name(gem_def)
31
-
32
- BundlerPackage.new(gem_def, bundler_def)
15
+ BundlerPackage.new(gem_def, bundler_def, logger: logger).tap do |package|
16
+ logger.package self.class, package
17
+ end
33
18
  end
19
+ end
34
20
 
35
- packages.each do |gem|
36
- gem.children = children_for(gem, top_level_gems)
37
- end
21
+ private
38
22
 
39
- packages
23
+ def definition
24
+ # DI
25
+ @definition ||= ::Bundler::Definition.build(package_path, lockfile_path, nil)
40
26
  end
41
27
 
42
- private
43
- attr_reader :definition, :ignore_groups
28
+ def ignore_groups
29
+ # DI
30
+ @ignore_groups ||= LicenseFinder.config.ignore_groups
31
+ end
32
+
33
+ def package_path
34
+ Pathname.new("Gemfile")
35
+ end
44
36
 
45
37
  def bundler_defs
38
+ # memoized
46
39
  @bundler_defs ||= definition.dependencies
47
40
  end
48
41
 
@@ -51,15 +44,7 @@ module LicenseFinder
51
44
  end
52
45
 
53
46
  def lockfile_path
54
- self.class.gemfile_path.dirname.join('Gemfile.lock')
55
- end
56
-
57
- def children_for(gem, top_level_gems)
58
- gem.gem_def.dependencies.map(&:name).select { |name| top_level_gems.include? name }
59
- end
60
-
61
- def format_name(gem)
62
- gem.name.split(" ")[0]
47
+ package_path.dirname.join('Gemfile.lock')
63
48
  end
64
49
  end
65
50
  end