license_scout 1.3.17 → 2.0.2

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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +195 -0
  3. data/bin/license_scout +3 -59
  4. data/bin/mix_lock_json +0 -0
  5. data/bin/rebar_lock_json +0 -0
  6. data/lib/license_scout/cli.rb +99 -0
  7. data/lib/license_scout/collector.rb +25 -77
  8. data/lib/license_scout/config.rb +94 -0
  9. data/lib/license_scout/data/dependeny_manifest_v2_schema.json +62 -0
  10. data/lib/license_scout/data/exceptions.json +306 -0
  11. data/lib/license_scout/data/licenses.json +4653 -0
  12. data/lib/license_scout/dependency.rb +79 -7
  13. data/lib/license_scout/dependency_manager/base.rb +74 -42
  14. data/lib/license_scout/dependency_manager/berkshelf.rb +25 -50
  15. data/lib/license_scout/dependency_manager/bundler/_bundler_script.rb +1 -1
  16. data/lib/license_scout/dependency_manager/bundler.rb +47 -69
  17. data/lib/license_scout/dependency_manager/cpanm.rb +62 -112
  18. data/lib/license_scout/dependency_manager/dep.rb +29 -36
  19. data/lib/license_scout/dependency_manager/glide.rb +25 -36
  20. data/lib/license_scout/dependency_manager/godep.rb +27 -26
  21. data/lib/license_scout/dependency_manager/habitat.rb +126 -0
  22. data/lib/license_scout/dependency_manager/mix.rb +105 -0
  23. data/lib/license_scout/dependency_manager/npm.rb +30 -86
  24. data/lib/license_scout/dependency_manager/rebar.rb +26 -45
  25. data/lib/license_scout/dependency_manager.rb +19 -5
  26. data/lib/license_scout/exceptions.rb +2 -43
  27. data/lib/license_scout/license.rb +126 -0
  28. data/lib/license_scout/{license_file_analyzer.rb → log.rb} +4 -6
  29. data/lib/license_scout/reporter.rb +149 -55
  30. data/lib/license_scout/spdx.rb +123 -0
  31. data/lib/license_scout/version.rb +1 -1
  32. data/lib/license_scout.rb +2 -0
  33. data/native_parsers/mix_lock_json/README.md +21 -0
  34. data/native_parsers/mix_lock_json/lib/mix_lock_json.ex +20 -0
  35. data/native_parsers/mix_lock_json/mix.exs +31 -0
  36. data/native_parsers/mix_lock_json/mix.lock +3 -0
  37. data/{erl_src → native_parsers}/rebar_lock_json/rebar.lock +2 -2
  38. metadata +144 -67
  39. data/lib/license_scout/canonical_licenses/BSD-2-Clause.txt +0 -19
  40. data/lib/license_scout/canonical_licenses/BSD-3-Clause.txt +0 -27
  41. data/lib/license_scout/canonical_licenses/BSD-4-Clause.txt +0 -31
  42. data/lib/license_scout/canonical_licenses/Chef-MLSA.txt +0 -5
  43. data/lib/license_scout/canonical_licenses/ISC.txt +0 -14
  44. data/lib/license_scout/canonical_licenses/MIT.txt +0 -20
  45. data/lib/license_scout/dependency_manager/bundler/LICENSE.md +0 -23
  46. data/lib/license_scout/dependency_manager/json/README.md +0 -392
  47. data/lib/license_scout/dependency_manager/manual.rb +0 -67
  48. data/lib/license_scout/license_file_analyzer/any_matcher.rb +0 -37
  49. data/lib/license_scout/license_file_analyzer/definitions.rb +0 -219
  50. data/lib/license_scout/license_file_analyzer/header_matcher.rb +0 -34
  51. data/lib/license_scout/license_file_analyzer/matcher.rb +0 -46
  52. data/lib/license_scout/license_file_analyzer/template.rb +0 -45
  53. data/lib/license_scout/license_file_analyzer/templates/Apache2-short.txt +0 -11
  54. data/lib/license_scout/license_file_analyzer/templates/Apache2.txt +0 -170
  55. data/lib/license_scout/license_file_analyzer/templates/BSD-2-Clause-bullets.txt +0 -18
  56. data/lib/license_scout/license_file_analyzer/templates/BSD-2-Clause.txt +0 -19
  57. data/lib/license_scout/license_file_analyzer/templates/BSD-3-Clause-alt-format.txt +0 -24
  58. data/lib/license_scout/license_file_analyzer/templates/BSD-3-Clause.txt +0 -21
  59. data/lib/license_scout/license_file_analyzer/templates/BSD.txt +0 -24
  60. data/lib/license_scout/license_file_analyzer/templates/Chef-MLSA.txt +0 -5
  61. data/lib/license_scout/license_file_analyzer/templates/EPLICENSE.txt +0 -286
  62. data/lib/license_scout/license_file_analyzer/templates/GPL-2.0.txt +0 -339
  63. data/lib/license_scout/license_file_analyzer/templates/GPL-3.0.txt +0 -674
  64. data/lib/license_scout/license_file_analyzer/templates/ISC.txt +0 -2
  65. data/lib/license_scout/license_file_analyzer/templates/LGPL-3.0.txt +0 -165
  66. data/lib/license_scout/license_file_analyzer/templates/MIT.txt +0 -9
  67. data/lib/license_scout/license_file_analyzer/templates/MPL2.txt +0 -373
  68. data/lib/license_scout/license_file_analyzer/templates/Python-2.0.txt +0 -47
  69. data/lib/license_scout/license_file_analyzer/templates/Ruby.txt +0 -52
  70. data/lib/license_scout/license_file_analyzer/text.rb +0 -46
  71. data/lib/license_scout/net_fetcher.rb +0 -106
  72. data/lib/license_scout/options.rb +0 -47
  73. data/lib/license_scout/overrides.rb +0 -1125
  74. /data/{erl_src → native_parsers}/rebar_lock_json/README.md +0 -0
  75. /data/{erl_src → native_parsers}/rebar_lock_json/rebar.config +0 -0
  76. /data/{erl_src → native_parsers}/rebar_lock_json/src/rebar_lock_json.app.src +0 -0
  77. /data/{erl_src → native_parsers}/rebar_lock_json/src/rebar_lock_json.erl +0 -0
@@ -0,0 +1,105 @@
1
+ #
2
+ # Copyright:: Copyright 2016, Chef Software Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require "license_scout/dependency_manager/base"
19
+ require "license_scout/exceptions"
20
+
21
+ require "mixlib/shellout"
22
+ require "ffi_yajl"
23
+
24
+ module LicenseScout
25
+ module DependencyManager
26
+ class Mix < Base
27
+
28
+ attr_reader :packaged_dependencies
29
+
30
+ def initialize(directory)
31
+ super(directory)
32
+
33
+ @packaged_dependencies = {}
34
+ end
35
+
36
+ def name
37
+ "elixir_mix"
38
+ end
39
+
40
+ def type
41
+ "elixir"
42
+ end
43
+
44
+ def signature
45
+ "mix.lock file"
46
+ end
47
+
48
+ def install_command
49
+ "mix deps.get"
50
+ end
51
+
52
+ def detected?
53
+ File.exist?(mix_lock_path)
54
+ end
55
+
56
+ def dependencies
57
+ parse_packaged_dependencies
58
+
59
+ # Some dependencies are obtained via 'pkg' identifier of rebar. These
60
+ # dependencies include their version in the rebar.lock file. Here we
61
+ # parse the rebar.lock and remember all the versions we find.
62
+ packaged_dependencies.map do |dep_name, dep_version|
63
+ dep_path = Dir.glob(File.join(directory, "**", "deps", dep_name)).first
64
+
65
+ dependency = new_dependency(dep_name, dep_version, dep_path)
66
+
67
+ Array(hex_info(dep_name).dig("meta", "licenses")).each do |license|
68
+ dependency.add_license(license, "https://hex.pm/api/packages/#{dep_name}")
69
+ end
70
+
71
+ dependency
72
+ end.compact
73
+ end
74
+
75
+ private
76
+
77
+ def parse_packaged_dependencies
78
+ mix_lock_to_json_path = File.expand_path("../../../bin/mix_lock_json", File.dirname(__FILE__))
79
+ s = Mixlib::ShellOut.new("#{LicenseScout::Config.escript_bin} #{mix_lock_to_json_path} #{mix_lock_path}", environment: LicenseScout::Config.environment)
80
+ s.run_command
81
+ s.error!
82
+
83
+ mix_lock_content = FFI_Yajl::Parser.parse(s.stdout)
84
+
85
+ mix_lock_content.each do |dep|
86
+ name = dep.keys.first
87
+ version = dep.values.first
88
+
89
+ @packaged_dependencies[name] = version
90
+ end
91
+ end
92
+
93
+ def mix_lock_path
94
+ File.join(directory, "mix.lock")
95
+ end
96
+
97
+ def hex_info(package_name)
98
+ FFI_Yajl::Parser.parse(open("https://hex.pm/api/packages/#{package_name}").read)
99
+ rescue OpenURI::HTTPError
100
+ LicenseScout::Log.debug("[elixir] Unable to download hex.pm info for #{package_name}")
101
+ {}
102
+ end
103
+ end
104
+ end
105
+ end
@@ -15,16 +15,28 @@
15
15
  # limitations under the License.
16
16
  #
17
17
 
18
- require "set" unless defined?(Set)
19
- require "ffi_yajl" unless defined?(FFI_Yajl)
18
+ require "set"
19
+ require "ffi_yajl"
20
20
  require "license_scout/dependency_manager/base"
21
21
 
22
22
  module LicenseScout
23
23
  module DependencyManager
24
- class NPM < Base
24
+ class Npm < Base
25
25
 
26
26
  def name
27
- "js_npm"
27
+ "nodejs_npm"
28
+ end
29
+
30
+ def type
31
+ "nodejs"
32
+ end
33
+
34
+ def signature
35
+ "node_modules directory"
36
+ end
37
+
38
+ def install_command
39
+ "npm install"
28
40
  end
29
41
 
30
42
  def detected?
@@ -32,33 +44,26 @@ module LicenseScout
32
44
  end
33
45
 
34
46
  def dependencies
35
- packages = all_package_json_files.inject(Set.new) do |package_set, package_json_file|
47
+ all_package_json_files.inject(Set.new) do |uniq_deps, package_json_file|
36
48
  pkg_info = File.open(package_json_file) do |f|
37
49
  FFI_Yajl::Parser.parse(f)
38
50
  end
39
51
 
40
- pkg_name = pkg_info["name"]
41
- pkg_version = pkg_info["version"]
42
- package_path = File.dirname(package_json_file)
52
+ dep_name = pkg_info["name"]
53
+ dep_version = pkg_info["version"]
54
+ dep_path = File.dirname(package_json_file)
43
55
 
44
- license = options.overrides.license_for(name, pkg_name, pkg_version) ||
45
- normalize_license_data(pkg_info["license"] || pkg_info["licence"] || pkg_info["licenses"])
56
+ dependency = new_dependency(dep_name, dep_version, dep_path)
46
57
 
47
- override_license_files = options.overrides.license_files_for(name, pkg_name, pkg_version)
48
- if override_license_files.empty?
49
- license_files = find_license_files_in(package_path)
50
- else
51
- license_files = override_license_files.resolve_locations(package_path)
58
+ case pkg_info["license"]
59
+ when String
60
+ dependency.add_license(pkg_info["license"], "package.json")
61
+ when Hash
62
+ dependency.add_license(pkg_info["license"]["type"], "package.json", pkg_info["license"]["url"])
52
63
  end
53
64
 
54
- package_set << create_dependency(
55
- pkg_name,
56
- pkg_version,
57
- license,
58
- license_files
59
- )
60
- end
61
- packages.to_a
65
+ uniq_deps << dependency
66
+ end.to_a
62
67
  end
63
68
 
64
69
  private
@@ -79,7 +84,7 @@ module LicenseScout
79
84
  # package metadata is removed).
80
85
  def all_package_json_files
81
86
  all_files = []
82
- package_dirs = [project_dir]
87
+ package_dirs = [directory]
83
88
  loop do
84
89
  break if package_dirs.empty?
85
90
 
@@ -98,70 +103,9 @@ module LicenseScout
98
103
  all_files
99
104
  end
100
105
 
101
- def find_license_files_in(dir)
102
- root_files = Dir["#{dir}/*"]
103
- root_files.select { |f| POSSIBLE_LICENSE_FILES.include?(File.basename(f)) }
104
- end
105
-
106
- def normalize_license_data(license_metadata)
107
- license_string =
108
- case license_metadata
109
- when nil
110
- nil
111
- when String
112
- license_metadata
113
- when Hash
114
- license_metadata["type"]
115
- when Array
116
- if (map = license_metadata.first) && map.is_a?(Hash) && (type = map["type"])
117
- type
118
- else
119
- nil
120
- end
121
- end
122
- select_best_license(license_string)
123
- end
124
-
125
- # npm packages use SPDX "expressions" for their licenses; Thus far we've
126
- # only seen a single license, optional multiple licenses like "(MIT OR Apache-2.0)"
127
- # or mandatory multiple licenses like "(MIT AND CC-BY-3.0)"
128
- #
129
- # If there are multiple options, we want to pick just one to keep it simple.
130
- def select_best_license(license_string)
131
- return nil if license_string.nil?
132
-
133
- options = license_string.tr("(", "").tr(")", "").split(" OR ")
134
- options.inject do |selected_license, license|
135
- if license_rank(selected_license) < license_rank(license)
136
- selected_license
137
- else
138
- license
139
- end
140
- end
141
- end
142
-
143
- # Rank licenses when selecting one of multiple options. Licenses are
144
- # converted to integer scores, the lower the better.
145
- #
146
- # We prefer Apache-2.0 since it matches our own projects, then MIT, then
147
- # BSDs. Everything else is considered equal.
148
- def license_rank(license)
149
- case license
150
- when "Apache-2.0"
151
- 0
152
- when "MIT"
153
- 1
154
- when /bsd/i
155
- 2
156
- else
157
- 3
158
- end
159
- end
160
-
161
106
  def root_node_modules_path
162
- File.join(project_dir, "node_modules")
107
+ File.join(directory, "node_modules")
163
108
  end
164
-
165
109
  end
166
110
  end
167
111
  end
@@ -16,12 +16,10 @@
16
16
  #
17
17
 
18
18
  require "license_scout/dependency_manager/base"
19
- require "license_scout/net_fetcher"
20
19
  require "license_scout/exceptions"
21
- require "license_scout/license_file_analyzer"
22
20
 
23
- require "mixlib/shellout" unless defined?(Mixlib::ShellOut)
24
- require "ffi_yajl" unless defined?(FFI_Yajl)
21
+ require "mixlib/shellout"
22
+ require "ffi_yajl"
25
23
 
26
24
  module LicenseScout
27
25
  module DependencyManager
@@ -29,8 +27,8 @@ module LicenseScout
29
27
 
30
28
  attr_reader :packaged_dependencies
31
29
 
32
- def initialize(project_dir, options)
33
- super(project_dir, options)
30
+ def initialize(directory)
31
+ super(directory)
34
32
 
35
33
  @packaged_dependencies = {}
36
34
  end
@@ -39,19 +37,29 @@ module LicenseScout
39
37
  "erlang_rebar"
40
38
  end
41
39
 
40
+ def type
41
+ "erlang"
42
+ end
43
+
44
+ def signature
45
+ "rebar.config file"
46
+ end
47
+
48
+ def install_command
49
+ "rebar get-deps"
50
+ end
51
+
42
52
  def detected?
43
53
  File.exist?(rebar_config_path)
44
54
  end
45
55
 
46
56
  def dependencies
47
- dependencies = []
48
-
49
57
  # Some dependencies are obtained via 'pkg' identifier of rebar. These
50
58
  # dependencies include their version in the rebar.lock file. Here we
51
59
  # parse the rebar.lock and remember all the versions we find.
52
60
  parse_packaged_dependencies
53
61
 
54
- Dir.glob("#{project_deps_dir}/*").each do |dep_dir|
62
+ Dir.glob("#{project_deps_dir}/*").map do |dep_dir|
55
63
  next unless File.directory?(dep_dir)
56
64
 
57
65
  dep_name = File.basename(dep_dir)
@@ -59,10 +67,10 @@ module LicenseScout
59
67
  # First check if this dependency is coming from the parent software.
60
68
  # If so we do not need to worry about its version or licenses because
61
69
  # it will be covered under the parent software's license.
62
- next if File.directory?(File.join(project_dir, "apps", dep_name))
70
+ next if File.directory?(File.join(directory, "apps", dep_name))
63
71
 
64
72
  # Or skip if the dep name is the project name
65
- next if File.exist?(File.join(project_dir, "_build/default/rel", dep_name))
73
+ next if File.exist?(File.join(directory, "_build/default/rel", dep_name))
66
74
 
67
75
  # While determining the dependency version we first check the cache we
68
76
  # built from rebar.lock for the dependencies that come via 'pkg'
@@ -74,22 +82,8 @@ module LicenseScout
74
82
  git_rev_parse(dep_dir)
75
83
  end
76
84
 
77
- override_license_files = options.overrides.license_files_for(name, dep_name, dep_version)
78
- license_files =
79
- if override_license_files.empty?
80
- Dir.glob("#{dep_dir}/*").select { |f| POSSIBLE_LICENSE_FILES.include?(File.basename(f)) }
81
- else
82
- override_license_files.resolve_locations(dep_dir)
83
- end
84
-
85
- license_name = options.overrides.license_for(name, dep_name, dep_version) || scan_licenses(license_files)
86
-
87
- dep = create_dependency(dep_name, dep_version, license_name, license_files)
88
-
89
- dependencies << dep
90
- end
91
-
92
- dependencies
85
+ new_dependency(dep_name, dep_version, dep_dir)
86
+ end.compact
93
87
  end
94
88
 
95
89
  private
@@ -99,12 +93,12 @@ module LicenseScout
99
93
  # determine the version of them via git, we try to parse the rebar.lock
100
94
  # file and remember their versions to use it later.
101
95
  def parse_packaged_dependencies
102
- rebar_lock_path = File.join(project_dir, "rebar.lock")
96
+ rebar_lock_path = File.join(directory, "rebar.lock")
103
97
 
104
98
  return unless File.exist?(rebar_lock_path)
105
99
 
106
100
  rebar_lock_to_json_path = File.expand_path("../../../bin/rebar_lock_json", File.dirname(__FILE__))
107
- s = Mixlib::ShellOut.new("#{rebar_lock_to_json_path} #{rebar_lock_path}", environment: options.environment)
101
+ s = Mixlib::ShellOut.new("#{LicenseScout::Config.escript_bin} #{rebar_lock_to_json_path} #{rebar_lock_path}", environment: LicenseScout::Config.environment)
108
102
  s.run_command
109
103
  s.error!
110
104
 
@@ -115,7 +109,7 @@ module LicenseScout
115
109
  source_name = source_info["pkg_name"]
116
110
  source_version = source_info["pkg_version"]
117
111
 
118
- packaged_dependencies[source_name] = source_version
112
+ @packaged_dependencies[source_name] = source_version
119
113
  end
120
114
  end
121
115
  rescue Mixlib::ShellOut::ShellCommandFailed
@@ -139,27 +133,14 @@ module LicenseScout
139
133
  def project_deps_dir
140
134
  # rebar dependencies can be found in one of these two directories.
141
135
  ["deps", "_build/default/lib"].each do |dir|
142
- dep_dir = File.join(project_dir, dir)
136
+ dep_dir = File.join(directory, dir)
143
137
  return dep_dir if File.exist?(dep_dir)
144
138
  end
145
139
  end
146
140
 
147
141
  def rebar_config_path
148
- File.join(project_dir, "rebar.config")
149
- end
150
-
151
- def scan_licenses(license_files)
152
- if license_files.empty?
153
- nil
154
- else
155
- license_names = license_files.map do |license_file|
156
- found_license = LicenseScout::LicenseFileAnalyzer.find_by_text(IO.read(license_file))
157
- found_license ? found_license.short_name : nil
158
- end
159
- license_names.find { |x| x }
160
- end
142
+ File.join(directory, "rebar.config")
161
143
  end
162
-
163
144
  end
164
145
  end
165
146
  end
@@ -15,20 +15,34 @@
15
15
  # limitations under the License.
16
16
  #
17
17
 
18
+ require "license_scout/dependency_manager/base"
19
+
20
+ require "license_scout/dependency_manager/berkshelf"
18
21
  require "license_scout/dependency_manager/bundler"
19
- require "license_scout/dependency_manager/rebar"
20
22
  require "license_scout/dependency_manager/cpanm"
21
- require "license_scout/dependency_manager/godep"
22
23
  require "license_scout/dependency_manager/dep"
23
24
  require "license_scout/dependency_manager/glide"
24
- require "license_scout/dependency_manager/berkshelf"
25
+ require "license_scout/dependency_manager/godep"
26
+ require "license_scout/dependency_manager/habitat"
27
+ require "license_scout/dependency_manager/mix"
28
+ require "license_scout/dependency_manager/rebar"
25
29
  require "license_scout/dependency_manager/npm"
26
- require "license_scout/dependency_manager/manual"
27
30
 
28
31
  module LicenseScout
29
32
  module DependencyManager
30
33
  def self.implementations
31
- [Bundler, Rebar, Cpanm, Berkshelf, NPM, Godep, Dep, Glide, Manual]
34
+ [
35
+ Berkshelf,
36
+ Bundler,
37
+ Cpanm,
38
+ Dep,
39
+ Glide,
40
+ Godep,
41
+ Habitat,
42
+ Mix,
43
+ Rebar,
44
+ Npm,
45
+ ]
32
46
  end
33
47
  end
34
48
  end
@@ -18,48 +18,7 @@
18
18
  module LicenseScout
19
19
  module Exceptions
20
20
  class Error < RuntimeError; end
21
-
22
- class ProjectDirectoryMissing < Error
23
- def initialize(project_dir)
24
- @project_dir = project_dir
25
- end
26
-
27
- def to_s
28
- "Could not locate or access the provided project directory '#{@project_dir}'."
29
- end
30
- end
31
-
32
- class UnsupportedProjectType < Error
33
- def initialize(project_dir)
34
- @project_dir = project_dir
35
- end
36
-
37
- def to_s
38
- "Could not find a supported dependency manager for the project in the provided directory '#{@project_dir}'."
39
- end
40
- end
41
-
42
- class InaccessibleDependency < Error; end
43
- class InvalidOverride < Error; end
44
- class InvalidOutputReport < Error; end
45
- class InvalidManualDependency < Error; end
46
-
47
- class NetworkError < Error
48
-
49
- attr_reader :from_url
50
- attr_reader :network_error
51
-
52
- def initialize(from_url, network_error)
53
- @from_url = from_url
54
- @network_error = network_error
55
- end
56
-
57
- def to_s
58
- [
59
- "Network error while fetching '#{from_url}'",
60
- network_error.to_s,
61
- ].join("\n")
62
- end
63
- end
21
+ class ConfigError < Error; end
22
+ class MissingSourceDirectory < Error; end
64
23
  end
65
24
  end
@@ -0,0 +1,126 @@
1
+ #
2
+ # Copyright:: Copyright 2018, Chef Software Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require "license_scout/spdx"
19
+
20
+ module LicenseScout
21
+ class License
22
+ # A class that represents the components that make up a license.
23
+ class Record
24
+ attr_reader :id
25
+ attr_reader :parsed_expression
26
+ attr_reader :source
27
+ attr_reader :content
28
+ attr_reader :spdx_license_data
29
+
30
+ def initialize(license_id = nil, source = nil, content = nil, options = {})
31
+ @id = LicenseScout::SPDX.find(license_id, options[:force])
32
+ @parsed_expression = LicenseScout::SPDX.parse(id)
33
+ @source = source
34
+ @content = content
35
+ end
36
+
37
+ def to_h
38
+ {
39
+ id: id,
40
+ source: source,
41
+ content: content,
42
+ }
43
+ end
44
+ end
45
+
46
+ attr_reader :project
47
+ attr_reader :records
48
+
49
+ # @param path [String, nil] A path to give to Licensee to search for the license. Could be local path or GitHub URL.
50
+ def initialize(path = nil)
51
+ if path.nil?
52
+ @project = nil
53
+ @records = []
54
+ else
55
+ @project = Licensee.project(path, detect_readme: true)
56
+ @records = []
57
+
58
+ project.licenses.each_index do |i|
59
+ record = Record.new(
60
+ project.licenses[i].spdx_id,
61
+ project.matched_files[i].filename,
62
+ project.matched_files[i].content
63
+ )
64
+
65
+ # Favor records that have identified a license
66
+ record.id.nil? ? @records.push(record) : @records.unshift(record)
67
+ end
68
+ end
69
+ end
70
+
71
+ # Capture a license that was specified in metadata
72
+ #
73
+ # @param license_id [String] The license as specified in the metadata file
74
+ # @param source [String] Where we found the license info
75
+ # @param contents_url [String] Where we can find the contents of the license
76
+ # @param options [Hash] Options to control various behavior
77
+ #
78
+ # @return [void]
79
+ def add_license(license_id, source, contents_url, options)
80
+ content = license_content(license_id, contents_url)
81
+ @records.push(Record.new(license_id, source, content, options))
82
+ end
83
+
84
+ # @return [Boolean] Whether or not the license(s) are allowed
85
+ def is_allowed?
86
+ (records.map(&:parsed_expression).flatten.compact & LicenseScout::Config.allowed_licenses).any?
87
+ end
88
+
89
+ # @return [Boolean] Whether or not the license(s) are flagged
90
+ def is_flagged?
91
+ (records.map(&:parsed_expression).flatten.compact & LicenseScout::Config.flagged_licenses).any?
92
+ end
93
+
94
+ # @return [Boolean] Whether we were unable to determine a license
95
+ def undetermined?
96
+ (records.map(&:parsed_expression).flatten.compact).empty?
97
+ end
98
+
99
+ private
100
+
101
+ def license_content(license_id, contents_url)
102
+ if contents_url.nil?
103
+ nil
104
+ else
105
+ new_url = raw_github_url(contents_url)
106
+
107
+ begin
108
+ LicenseScout::Log.debug("[license] Pulling license content for #{license_id} from #{new_url}")
109
+ open(new_url).read
110
+ rescue OpenURI::HTTPError
111
+ LicenseScout::Log.warn("[license] Unable to download license for #{license_id} from #{new_url}")
112
+ nil
113
+ end
114
+ end
115
+ end
116
+
117
+ def raw_github_url(url)
118
+ case url
119
+ when /github.com\/(.+)\/blob\/(.+)/
120
+ "https://raw.githubusercontent.com/#{$1}/#{$2}"
121
+ else
122
+ url
123
+ end
124
+ end
125
+ end
126
+ end
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright:: Copyright 2016, Chef Software Inc.
2
+ # Copyright:: Copyright 2018, Chef Software Inc.
3
3
  # License:: Apache License, Version 2.0
4
4
  #
5
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,12 +15,10 @@
15
15
  # limitations under the License.
16
16
  #
17
17
 
18
- require "license_scout/license_file_analyzer/definitions"
18
+ require "mixlib/log"
19
19
 
20
20
  module LicenseScout
21
- module LicenseFileAnalyzer
22
- def self.find_by_text(text)
23
- Definitions.all.detect { |l| l.matches_text? text }
24
- end
21
+ class Log
22
+ extend Mixlib::Log
25
23
  end
26
24
  end