license_scout 1.3.2 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
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/README.md +0 -0
  38. data/{erl_src → native_parsers}/rebar_lock_json/rebar.config +0 -0
  39. data/{erl_src → native_parsers}/rebar_lock_json/rebar.lock +2 -2
  40. data/{erl_src → native_parsers}/rebar_lock_json/src/rebar_lock_json.app.src +0 -0
  41. data/{erl_src → native_parsers}/rebar_lock_json/src/rebar_lock_json.erl +0 -0
  42. metadata +144 -67
  43. data/lib/license_scout/canonical_licenses/BSD-2-Clause.txt +0 -19
  44. data/lib/license_scout/canonical_licenses/BSD-3-Clause.txt +0 -27
  45. data/lib/license_scout/canonical_licenses/BSD-4-Clause.txt +0 -31
  46. data/lib/license_scout/canonical_licenses/Chef-MLSA.txt +0 -5
  47. data/lib/license_scout/canonical_licenses/ISC.txt +0 -14
  48. data/lib/license_scout/canonical_licenses/MIT.txt +0 -20
  49. data/lib/license_scout/dependency_manager/bundler/LICENSE.md +0 -23
  50. data/lib/license_scout/dependency_manager/json/README.md +0 -392
  51. data/lib/license_scout/dependency_manager/manual.rb +0 -67
  52. data/lib/license_scout/license_file_analyzer/any_matcher.rb +0 -37
  53. data/lib/license_scout/license_file_analyzer/definitions.rb +0 -219
  54. data/lib/license_scout/license_file_analyzer/header_matcher.rb +0 -34
  55. data/lib/license_scout/license_file_analyzer/matcher.rb +0 -46
  56. data/lib/license_scout/license_file_analyzer/template.rb +0 -45
  57. data/lib/license_scout/license_file_analyzer/templates/Apache2-short.txt +0 -11
  58. data/lib/license_scout/license_file_analyzer/templates/Apache2.txt +0 -170
  59. data/lib/license_scout/license_file_analyzer/templates/BSD-2-Clause-bullets.txt +0 -18
  60. data/lib/license_scout/license_file_analyzer/templates/BSD-2-Clause.txt +0 -19
  61. data/lib/license_scout/license_file_analyzer/templates/BSD-3-Clause-alt-format.txt +0 -24
  62. data/lib/license_scout/license_file_analyzer/templates/BSD-3-Clause.txt +0 -21
  63. data/lib/license_scout/license_file_analyzer/templates/BSD.txt +0 -24
  64. data/lib/license_scout/license_file_analyzer/templates/Chef-MLSA.txt +0 -5
  65. data/lib/license_scout/license_file_analyzer/templates/EPLICENSE.txt +0 -286
  66. data/lib/license_scout/license_file_analyzer/templates/GPL-2.0.txt +0 -339
  67. data/lib/license_scout/license_file_analyzer/templates/GPL-3.0.txt +0 -674
  68. data/lib/license_scout/license_file_analyzer/templates/ISC.txt +0 -2
  69. data/lib/license_scout/license_file_analyzer/templates/LGPL-3.0.txt +0 -165
  70. data/lib/license_scout/license_file_analyzer/templates/MIT.txt +0 -9
  71. data/lib/license_scout/license_file_analyzer/templates/MPL2.txt +0 -373
  72. data/lib/license_scout/license_file_analyzer/templates/Python-2.0.txt +0 -47
  73. data/lib/license_scout/license_file_analyzer/templates/Ruby.txt +0 -52
  74. data/lib/license_scout/license_file_analyzer/text.rb +0 -46
  75. data/lib/license_scout/net_fetcher.rb +0 -106
  76. data/lib/license_scout/options.rb +0 -47
  77. data/lib/license_scout/overrides.rb +0 -1113
@@ -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