license_scout 1.3.11 → 2.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +195 -0
- data/bin/license_scout +3 -59
- data/bin/mix_lock_json +0 -0
- data/bin/rebar_lock_json +0 -0
- data/lib/license_scout/cli.rb +99 -0
- data/lib/license_scout/collector.rb +25 -77
- data/lib/license_scout/config.rb +94 -0
- data/lib/license_scout/data/dependeny_manifest_v2_schema.json +62 -0
- data/lib/license_scout/data/exceptions.json +306 -0
- data/lib/license_scout/data/licenses.json +4653 -0
- data/lib/license_scout/dependency.rb +79 -7
- data/lib/license_scout/dependency_manager/base.rb +74 -42
- data/lib/license_scout/dependency_manager/berkshelf.rb +25 -50
- data/lib/license_scout/dependency_manager/bundler/_bundler_script.rb +1 -1
- data/lib/license_scout/dependency_manager/bundler.rb +47 -69
- data/lib/license_scout/dependency_manager/cpanm.rb +62 -112
- data/lib/license_scout/dependency_manager/dep.rb +29 -36
- data/lib/license_scout/dependency_manager/glide.rb +25 -36
- data/lib/license_scout/dependency_manager/godep.rb +27 -26
- data/lib/license_scout/dependency_manager/habitat.rb +126 -0
- data/lib/license_scout/dependency_manager/mix.rb +105 -0
- data/lib/license_scout/dependency_manager/npm.rb +30 -86
- data/lib/license_scout/dependency_manager/rebar.rb +26 -45
- data/lib/license_scout/dependency_manager.rb +19 -5
- data/lib/license_scout/exceptions.rb +2 -43
- data/lib/license_scout/license.rb +126 -0
- data/lib/license_scout/{license_file_analyzer.rb → log.rb} +4 -6
- data/lib/license_scout/reporter.rb +149 -55
- data/lib/license_scout/spdx.rb +123 -0
- data/lib/license_scout/version.rb +1 -1
- data/lib/license_scout.rb +2 -0
- data/native_parsers/mix_lock_json/README.md +21 -0
- data/native_parsers/mix_lock_json/lib/mix_lock_json.ex +20 -0
- data/native_parsers/mix_lock_json/mix.exs +31 -0
- data/native_parsers/mix_lock_json/mix.lock +3 -0
- data/{erl_src → native_parsers}/rebar_lock_json/rebar.lock +2 -2
- metadata +144 -67
- data/lib/license_scout/canonical_licenses/BSD-2-Clause.txt +0 -19
- data/lib/license_scout/canonical_licenses/BSD-3-Clause.txt +0 -27
- data/lib/license_scout/canonical_licenses/BSD-4-Clause.txt +0 -31
- data/lib/license_scout/canonical_licenses/Chef-MLSA.txt +0 -5
- data/lib/license_scout/canonical_licenses/ISC.txt +0 -14
- data/lib/license_scout/canonical_licenses/MIT.txt +0 -20
- data/lib/license_scout/dependency_manager/bundler/LICENSE.md +0 -23
- data/lib/license_scout/dependency_manager/json/README.md +0 -392
- data/lib/license_scout/dependency_manager/manual.rb +0 -67
- data/lib/license_scout/license_file_analyzer/any_matcher.rb +0 -37
- data/lib/license_scout/license_file_analyzer/definitions.rb +0 -219
- data/lib/license_scout/license_file_analyzer/header_matcher.rb +0 -34
- data/lib/license_scout/license_file_analyzer/matcher.rb +0 -46
- data/lib/license_scout/license_file_analyzer/template.rb +0 -45
- data/lib/license_scout/license_file_analyzer/templates/Apache2-short.txt +0 -11
- data/lib/license_scout/license_file_analyzer/templates/Apache2.txt +0 -170
- data/lib/license_scout/license_file_analyzer/templates/BSD-2-Clause-bullets.txt +0 -18
- data/lib/license_scout/license_file_analyzer/templates/BSD-2-Clause.txt +0 -19
- data/lib/license_scout/license_file_analyzer/templates/BSD-3-Clause-alt-format.txt +0 -24
- data/lib/license_scout/license_file_analyzer/templates/BSD-3-Clause.txt +0 -21
- data/lib/license_scout/license_file_analyzer/templates/BSD.txt +0 -24
- data/lib/license_scout/license_file_analyzer/templates/Chef-MLSA.txt +0 -5
- data/lib/license_scout/license_file_analyzer/templates/EPLICENSE.txt +0 -286
- data/lib/license_scout/license_file_analyzer/templates/GPL-2.0.txt +0 -339
- data/lib/license_scout/license_file_analyzer/templates/GPL-3.0.txt +0 -674
- data/lib/license_scout/license_file_analyzer/templates/ISC.txt +0 -2
- data/lib/license_scout/license_file_analyzer/templates/LGPL-3.0.txt +0 -165
- data/lib/license_scout/license_file_analyzer/templates/MIT.txt +0 -9
- data/lib/license_scout/license_file_analyzer/templates/MPL2.txt +0 -373
- data/lib/license_scout/license_file_analyzer/templates/Python-2.0.txt +0 -47
- data/lib/license_scout/license_file_analyzer/templates/Ruby.txt +0 -52
- data/lib/license_scout/license_file_analyzer/text.rb +0 -46
- data/lib/license_scout/net_fetcher.rb +0 -106
- data/lib/license_scout/options.rb +0 -47
- data/lib/license_scout/overrides.rb +0 -1120
- /data/{erl_src → native_parsers}/rebar_lock_json/README.md +0 -0
- /data/{erl_src → native_parsers}/rebar_lock_json/rebar.config +0 -0
- /data/{erl_src → native_parsers}/rebar_lock_json/src/rebar_lock_json.app.src +0 -0
- /data/{erl_src → native_parsers}/rebar_lock_json/src/rebar_lock_json.erl +0 -0
@@ -15,146 +15,96 @@
|
|
15
15
|
# limitations under the License.
|
16
16
|
#
|
17
17
|
|
18
|
-
require "ffi_yajl" unless defined?(FFI_Yajl)
|
19
|
-
require "psych"
|
20
|
-
require "mixlib/shellout" unless defined?(Mixlib::ShellOut)
|
21
|
-
|
22
18
|
require "license_scout/dependency_manager/base"
|
23
|
-
|
24
|
-
require "
|
19
|
+
|
20
|
+
require "ffi_yajl"
|
21
|
+
require "psych"
|
22
|
+
require "mixlib/shellout"
|
25
23
|
|
26
24
|
module LicenseScout
|
27
25
|
module DependencyManager
|
28
26
|
class Cpanm < Base
|
29
27
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
"perl_5" => "Perl-5",
|
34
|
-
"perl" => "Perl-5",
|
35
|
-
"apache_2_0" => "Apache-2.0",
|
36
|
-
"artistic_2" => "Artistic-2.0",
|
37
|
-
"gpl_3" => "GPL-3.0",
|
38
|
-
}.freeze
|
39
|
-
|
40
|
-
attr_reader :unpack_path
|
41
|
-
attr_reader :overrides
|
42
|
-
attr_reader :metadata
|
43
|
-
|
44
|
-
def initialize(unpack_path, overrides)
|
45
|
-
@unpack_path = unpack_path
|
46
|
-
@overrides = overrides
|
47
|
-
end
|
48
|
-
|
49
|
-
def to_dep
|
50
|
-
parse_metadata!
|
28
|
+
def name
|
29
|
+
"perl_cpanm"
|
30
|
+
end
|
51
31
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
license,
|
56
|
-
license_files,
|
57
|
-
"perl_cpanm"
|
58
|
-
)
|
59
|
-
end
|
32
|
+
def type
|
33
|
+
"perl"
|
34
|
+
end
|
60
35
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
# the plugins whereas MYMETA.* files are created by the build system
|
65
|
-
# after dynamic dependencies are resolved. For our purposes META.*
|
66
|
-
# files are enough. And for no good reason we prioritize json files
|
67
|
-
# over yml files.
|
68
|
-
@metadata ||= begin
|
69
|
-
json_path = File.join(unpack_path, "META.json")
|
70
|
-
yml_path = File.join(unpack_path, "META.yml")
|
71
|
-
|
72
|
-
if File.exist?(json_path)
|
73
|
-
FFI_Yajl::Parser.parse(File.read(json_path))
|
74
|
-
elsif File.exist?(yml_path)
|
75
|
-
Psych.safe_load(File.read(yml_path))
|
76
|
-
else
|
77
|
-
raise LicenseScout::Exceptions::Error.new("Can not find a metadata file for the perl package at '#{unpack_path}'.")
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
36
|
+
def signature
|
37
|
+
File.exist?(meta_json_path) ? "META.json file" : "META.yml file"
|
38
|
+
end
|
81
39
|
|
82
|
-
|
83
|
-
|
84
|
-
|
40
|
+
def install_command
|
41
|
+
"cpanm --installdeps ."
|
42
|
+
end
|
85
43
|
|
86
|
-
|
87
|
-
|
88
|
-
|
44
|
+
# NOTE: it's possible that projects won't have a META.yml, but the two
|
45
|
+
# that we care about for Chef Server do have one. As of 2015, 84% of perl
|
46
|
+
# distribution packages have one: http://neilb.org/2015/10/18/spotters-guide.html
|
47
|
+
def detected?
|
48
|
+
File.exist?(meta_json_path) || File.exist?(meta_yml_path)
|
49
|
+
end
|
89
50
|
|
90
|
-
|
91
|
-
|
92
|
-
|
51
|
+
def dependencies
|
52
|
+
Dir.glob("#{cpanm_root}/latest-build/*").map do |dep_path|
|
53
|
+
next unless File.directory?(dep_path)
|
93
54
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
55
|
+
dep_data = manifest(dep_path)
|
56
|
+
metafile = dep_data["metafile"]
|
57
|
+
dep_name = dep_data["name"]
|
58
|
+
dep_version = dep_data["version"]
|
98
59
|
|
99
|
-
|
100
|
-
LICENSE_TYPE_MAP[given_type] || given_type
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
60
|
+
dependency = new_dependency(dep_name, dep_version, dep_path)
|
104
61
|
|
105
|
-
|
106
|
-
|
107
|
-
|
62
|
+
# CPANM projects contain license metadata - include it!
|
63
|
+
unless dep_data["license"].nil?
|
64
|
+
Array(dep_data["license"]).each do |license|
|
65
|
+
next if license == "unknown"
|
108
66
|
|
109
|
-
|
110
|
-
find_license_files
|
111
|
-
else
|
112
|
-
override_license_files.resolve_locations(unpack_path)
|
67
|
+
dependency.add_license(license, metafile)
|
113
68
|
end
|
114
69
|
end
|
115
|
-
end
|
116
|
-
|
117
|
-
def find_license_files
|
118
|
-
Dir["#{unpack_path}/*"].select do |f|
|
119
|
-
Cpanm::POSSIBLE_LICENSE_FILES.include?(File.basename(f))
|
120
|
-
end
|
121
|
-
end
|
122
70
|
|
71
|
+
dependency
|
72
|
+
end.compact
|
123
73
|
end
|
124
74
|
|
125
|
-
|
126
|
-
"perl_cpanm"
|
127
|
-
end
|
75
|
+
private
|
128
76
|
|
129
|
-
def
|
130
|
-
|
131
|
-
File.expand_path("~/.cpanm")
|
77
|
+
def meta_yml_path
|
78
|
+
File.join(directory, "META.yml")
|
132
79
|
end
|
133
80
|
|
134
|
-
def
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
Dir.glob("#{cpanm_root}/latest-build/*").each do |dep_path|
|
139
|
-
next unless File.directory?(dep_path)
|
140
|
-
|
141
|
-
deps << CpanmDependency.new(dep_path, options.overrides).to_dep
|
142
|
-
end
|
81
|
+
def meta_json_path
|
82
|
+
File.join(directory, "META.json")
|
83
|
+
end
|
143
84
|
|
144
|
-
|
85
|
+
# Packages can contain metadata files named META.yml, META.json,
|
86
|
+
# MYMETA.json, MYMETA.yml. META.* files are created by the authors of
|
87
|
+
# the plugins whereas MYMETA.* files are created by the build system
|
88
|
+
# after dynamic dependencies are resolved. For our purposes META.*
|
89
|
+
# files are enough. And for no good reason we prioritize json files
|
90
|
+
# over yml files.
|
91
|
+
def manifest(unpack_path)
|
92
|
+
json_path = File.join(unpack_path, "META.json")
|
93
|
+
yml_path = File.join(unpack_path, "META.yml")
|
94
|
+
|
95
|
+
if File.exist?(json_path)
|
96
|
+
FFI_Yajl::Parser.parse(File.read(json_path)).merge({ "metafile" => "META.json" })
|
97
|
+
elsif File.exist?(yml_path)
|
98
|
+
Psych.safe_load(File.read(yml_path)).merge({ "metafile" => "META.yml" })
|
99
|
+
else
|
100
|
+
raise LicenseScout::Exceptions::Error.new("Can not find a metadata file for the perl package at '#{unpack_path}'.")
|
145
101
|
end
|
146
102
|
end
|
147
103
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
def detected?
|
152
|
-
meta_yml_path = File.join(project_dir, "META.yml")
|
153
|
-
meta_json_path = File.join(project_dir, "META.json")
|
154
|
-
|
155
|
-
File.exist?(meta_yml_path) || File.exist?(meta_json_path)
|
104
|
+
def cpanm_root
|
105
|
+
# By default cpanm downloads all the dependencies into ~/.cpanm directory
|
106
|
+
File.expand_path(LicenseScout::Config.cpanm_root)
|
156
107
|
end
|
157
|
-
|
158
108
|
end
|
159
109
|
end
|
160
110
|
end
|
@@ -15,8 +15,8 @@
|
|
15
15
|
# limitations under the License.
|
16
16
|
#
|
17
17
|
|
18
|
-
require "ffi_yajl"
|
19
|
-
require "yaml"
|
18
|
+
require "ffi_yajl"
|
19
|
+
require "yaml"
|
20
20
|
require "toml-rb"
|
21
21
|
require "license_scout/dependency_manager/base"
|
22
22
|
|
@@ -26,62 +26,55 @@ module LicenseScout
|
|
26
26
|
class Dep < Base
|
27
27
|
|
28
28
|
def name
|
29
|
-
"
|
29
|
+
"golang_dep"
|
30
30
|
end
|
31
31
|
|
32
|
-
def
|
33
|
-
|
32
|
+
def type
|
33
|
+
"golang"
|
34
34
|
end
|
35
35
|
|
36
|
-
def
|
37
|
-
|
38
|
-
|
39
|
-
end
|
40
|
-
return [] unless deps.key?("projects")
|
36
|
+
def signature
|
37
|
+
"Gopkg.lock file"
|
38
|
+
end
|
41
39
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
pkg_version = pkg_info["version"] || pkg_info["revision"]
|
46
|
-
license = options.overrides.license_for("go", pkg_import_name, pkg_version)
|
40
|
+
def install_command
|
41
|
+
"dep ensure"
|
42
|
+
end
|
47
43
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
else
|
52
|
-
license_files = override_license_files.resolve_locations(gopath(pkg_import_name))
|
53
|
-
end
|
44
|
+
def detected?
|
45
|
+
File.exist?(gopkg_lock_path)
|
46
|
+
end
|
54
47
|
|
55
|
-
|
56
|
-
|
57
|
-
|
48
|
+
def dependencies
|
49
|
+
Array(gopkg.dig("projects")).map do |pkg_info|
|
50
|
+
dep_name = pkg_info["name"]
|
51
|
+
dep_version = pkg_info["version"] || pkg_info["revision"]
|
52
|
+
dep_path = package_path(dep_name)
|
58
53
|
|
59
|
-
|
60
|
-
end
|
54
|
+
new_dependency(dep_name, dep_version, dep_path)
|
55
|
+
end.compact
|
61
56
|
end
|
62
57
|
|
63
58
|
private
|
64
59
|
|
65
|
-
def
|
66
|
-
|
67
|
-
found_license && found_license.short_name
|
60
|
+
def gopkg
|
61
|
+
File.open(gopkg_lock_path) { |f| TomlRB.parse(f) }
|
68
62
|
end
|
69
63
|
|
70
|
-
def
|
71
|
-
File.join(
|
64
|
+
def gopkg_lock_path
|
65
|
+
File.join(directory, "Gopkg.lock")
|
72
66
|
end
|
73
67
|
|
74
68
|
def gopath(pkg)
|
75
|
-
"#{ENV[
|
69
|
+
"#{ENV['GOPATH']}/src/#{pkg}"
|
76
70
|
end
|
77
71
|
|
78
72
|
def vendor_dir(pkg = nil)
|
79
|
-
File.join(
|
73
|
+
File.join(directory, "vendor/#{pkg}")
|
80
74
|
end
|
81
75
|
|
82
|
-
def
|
83
|
-
|
84
|
-
root_files.select { |f| POSSIBLE_LICENSE_FILES.include?(File.basename(f)) }
|
76
|
+
def package_path(pkg)
|
77
|
+
(Dir[vendor_dir(pkg)] + Dir[gopath(pkg)]).first
|
85
78
|
end
|
86
79
|
end
|
87
80
|
end
|
@@ -15,7 +15,7 @@
|
|
15
15
|
# limitations under the License.
|
16
16
|
#
|
17
17
|
|
18
|
-
require "
|
18
|
+
require "psych"
|
19
19
|
require "license_scout/dependency_manager/base"
|
20
20
|
|
21
21
|
module LicenseScout
|
@@ -23,56 +23,45 @@ module LicenseScout
|
|
23
23
|
class Glide < Base
|
24
24
|
|
25
25
|
def name
|
26
|
-
"
|
26
|
+
"golang_glide"
|
27
27
|
end
|
28
28
|
|
29
|
-
def
|
30
|
-
|
29
|
+
def type
|
30
|
+
"golang"
|
31
31
|
end
|
32
32
|
|
33
|
-
def
|
34
|
-
|
35
|
-
raise "Detected Go/Glide project that is missing its \"glide.lock\" "\
|
36
|
-
"file in #{project_dir}"
|
37
|
-
end
|
38
|
-
|
39
|
-
deps = YAML.safe_load(File.read(glide_yaml_locked), permitted_classes: [Date, Symbol, Time])
|
40
|
-
deps["imports"].map { |i| add_glide_dep(i) }
|
33
|
+
def signature
|
34
|
+
"glide.lock file"
|
41
35
|
end
|
42
36
|
|
43
|
-
|
37
|
+
def install_command
|
38
|
+
"glide install"
|
39
|
+
end
|
44
40
|
|
45
|
-
def
|
46
|
-
|
47
|
-
|
48
|
-
pkg_version = import_field["version"]
|
49
|
-
license = options.overrides.license_for("go", pkg_import_name, pkg_version)
|
41
|
+
def detected?
|
42
|
+
File.exist?(glide_lock_path)
|
43
|
+
end
|
50
44
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
45
|
+
def dependencies
|
46
|
+
# We cannot use YAML.safe_load because Psych throws a fit about the
|
47
|
+
# updated field. We should circle back and see what we can do to fix that.
|
48
|
+
YAML.load(File.read(glide_lock_path))["imports"].map do |import|
|
49
|
+
dep_name = import["name"]
|
50
|
+
dep_version = import["version"]
|
51
|
+
dep_path = gopath(dep_name)
|
57
52
|
|
58
|
-
|
53
|
+
new_dependency(dep_name, dep_version, dep_path)
|
54
|
+
end.compact
|
59
55
|
end
|
60
56
|
|
61
|
-
|
62
|
-
File.join(project_dir, "glide.yaml")
|
63
|
-
end
|
57
|
+
private
|
64
58
|
|
65
|
-
def
|
66
|
-
File.join(
|
59
|
+
def glide_lock_path
|
60
|
+
File.join(directory, "glide.lock")
|
67
61
|
end
|
68
62
|
|
69
63
|
def gopath(pkg)
|
70
|
-
"#{ENV[
|
71
|
-
end
|
72
|
-
|
73
|
-
def find_license_files_for_package_in_gopath(pkg)
|
74
|
-
root_files = Dir["#{gopath(pkg)}/*"]
|
75
|
-
root_files.select { |f| POSSIBLE_LICENSE_FILES.include?(File.basename(f)) }
|
64
|
+
"#{ENV['GOPATH']}/src/#{pkg}"
|
76
65
|
end
|
77
66
|
end
|
78
67
|
end
|
@@ -15,7 +15,7 @@
|
|
15
15
|
# limitations under the License.
|
16
16
|
#
|
17
17
|
|
18
|
-
require "ffi_yajl"
|
18
|
+
require "ffi_yajl"
|
19
19
|
require "license_scout/dependency_manager/base"
|
20
20
|
|
21
21
|
module LicenseScout
|
@@ -23,7 +23,19 @@ module LicenseScout
|
|
23
23
|
class Godep < Base
|
24
24
|
|
25
25
|
def name
|
26
|
-
"
|
26
|
+
"golang_godep"
|
27
|
+
end
|
28
|
+
|
29
|
+
def type
|
30
|
+
"golang"
|
31
|
+
end
|
32
|
+
|
33
|
+
def signature
|
34
|
+
"Godeps/Godeps.json file"
|
35
|
+
end
|
36
|
+
|
37
|
+
def install_command
|
38
|
+
"godep restore"
|
27
39
|
end
|
28
40
|
|
29
41
|
def detected?
|
@@ -31,40 +43,29 @@ module LicenseScout
|
|
31
43
|
end
|
32
44
|
|
33
45
|
def dependencies
|
34
|
-
godeps = File.open(root_godeps_file) do |f|
|
35
|
-
FFI_Yajl::Parser.parse(f)
|
36
|
-
end
|
37
|
-
|
38
46
|
godeps["Deps"].map do |pkg_info|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
license = options.overrides.license_for("go", pkg_import_name, pkg_version)
|
47
|
+
dep_name = pkg_info["ImportPath"]
|
48
|
+
dep_version = pkg_info["Comment"] || pkg_info["Rev"]
|
49
|
+
dep_path = gopath(dep_name)
|
43
50
|
|
44
|
-
|
45
|
-
|
46
|
-
license_files = find_license_files_for_package_in_gopath(pkg_import_name)
|
47
|
-
else
|
48
|
-
license_files = override_license_files.resolve_locations(gopath(pkg_import_name))
|
49
|
-
end
|
50
|
-
|
51
|
-
create_dependency(pkg_file_name, pkg_version, license, license_files)
|
52
|
-
end
|
51
|
+
new_dependency(dep_name, dep_version, dep_path)
|
52
|
+
end.compact
|
53
53
|
end
|
54
54
|
|
55
55
|
private
|
56
56
|
|
57
|
-
def
|
58
|
-
File.
|
57
|
+
def godeps
|
58
|
+
File.open(root_godeps_file) do |f|
|
59
|
+
FFI_Yajl::Parser.parse(f)
|
60
|
+
end
|
59
61
|
end
|
60
62
|
|
61
|
-
def
|
62
|
-
"
|
63
|
+
def root_godeps_file
|
64
|
+
File.join(directory, "Godeps/Godeps.json")
|
63
65
|
end
|
64
66
|
|
65
|
-
def
|
66
|
-
|
67
|
-
root_files.select { |f| POSSIBLE_LICENSE_FILES.include?(File.basename(f)) }
|
67
|
+
def gopath(pkg)
|
68
|
+
"#{ENV['GOPATH']}/src/#{pkg}"
|
68
69
|
end
|
69
70
|
end
|
70
71
|
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/dependency_manager/base"
|
19
|
+
|
20
|
+
require "open-uri"
|
21
|
+
require "mixlib/shellout"
|
22
|
+
|
23
|
+
module LicenseScout
|
24
|
+
module DependencyManager
|
25
|
+
class Habitat < Base
|
26
|
+
|
27
|
+
def name
|
28
|
+
"habitat"
|
29
|
+
end
|
30
|
+
|
31
|
+
def type
|
32
|
+
"habitat"
|
33
|
+
end
|
34
|
+
|
35
|
+
def signature
|
36
|
+
File.exist?(habitat_plan_sh_path) ? "habitat/plan.sh file" : "plan.sh file"
|
37
|
+
end
|
38
|
+
|
39
|
+
def install_command
|
40
|
+
""
|
41
|
+
end
|
42
|
+
|
43
|
+
def detected?
|
44
|
+
File.exist?(plan_sh_path) || File.exist?(habitat_plan_sh_path)
|
45
|
+
end
|
46
|
+
|
47
|
+
def dependencies
|
48
|
+
tdeps = Set.new(pkg_deps)
|
49
|
+
|
50
|
+
pkg_deps.each do |pkg_dep|
|
51
|
+
pkg_info(pkg_dep)["tdeps"].each { |dep| tdeps << to_ident(dep) }
|
52
|
+
end
|
53
|
+
|
54
|
+
tdeps.sort.map do |tdep|
|
55
|
+
o, n, v, r = tdep.split("/")
|
56
|
+
dep_name = "#{o}/#{n}"
|
57
|
+
dep_version = "#{v}-#{r}"
|
58
|
+
|
59
|
+
dependency = new_dependency(dep_name, dep_version, nil)
|
60
|
+
|
61
|
+
license_from_manifest(pkg_info(tdep)["manifest"]).each do |spdx|
|
62
|
+
dependency.add_license(spdx, "https://bldr.habitat.sh/v1/depot/channels/#{o}/stable/pkgs/#{n}/#{v}/#{r}")
|
63
|
+
end
|
64
|
+
|
65
|
+
dependency
|
66
|
+
end.compact
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def license_from_manifest(manifest_content)
|
72
|
+
/^*\s+__License__:\s+(.+)$/.match(manifest_content)[1].strip.split("\s")
|
73
|
+
end
|
74
|
+
|
75
|
+
def pkg_deps
|
76
|
+
@pkg_deps ||= begin
|
77
|
+
plan_path = File.exist?(plan_sh_path) ? plan_sh_path : habitat_plan_sh_path
|
78
|
+
|
79
|
+
c = Mixlib::ShellOut.new("bash -ec 'export PLAN_CONTEXT=\"#{File.dirname(plan_path)}\"; source #{plan_path}; echo ${pkg_deps[*]}'", LicenseScout::Config.environment)
|
80
|
+
c.run_command
|
81
|
+
c.error!
|
82
|
+
pkg_deps = c.stdout.split("\s")
|
83
|
+
|
84
|
+
# Fetch the fully-qualified pkg_ident for each pkg
|
85
|
+
pkg_deps.map { |dep| to_ident(pkg_info(dep)["ident"]) }
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def to_ident(ident_hash)
|
90
|
+
"#{ident_hash["origin"]}/#{ident_hash["name"]}/#{ident_hash["version"]}/#{ident_hash["release"]}"
|
91
|
+
end
|
92
|
+
|
93
|
+
def pkg_info(pkg_ident)
|
94
|
+
$habitat_pkg_info ||= {}
|
95
|
+
$habitat_pkg_info[pkg_ident] ||= begin
|
96
|
+
pkg_origin, pkg_name, pkg_version, pkg_release = pkg_ident.split("/")
|
97
|
+
|
98
|
+
base_api_uri = "https://bldr.habitat.sh/v1/depot/channels/#{pkg_origin}/stable/pkgs/#{pkg_name}"
|
99
|
+
if pkg_version.nil? && pkg_release.nil?
|
100
|
+
base_api_uri += "/latest"
|
101
|
+
elsif pkg_release.nil?
|
102
|
+
base_api_uri += "/#{pkg_version}/latest"
|
103
|
+
else
|
104
|
+
base_api_uri += "/#{pkg_version}/#{pkg_release}"
|
105
|
+
end
|
106
|
+
|
107
|
+
LicenseScout::Log.debug("[habitat] Fetching pkg_info from #{base_api_uri}")
|
108
|
+
FFI_Yajl::Parser.parse(open(base_api_uri).read)
|
109
|
+
rescue OpenURI::HTTPError
|
110
|
+
pkg_origin, pkg_name, = pkg_ident.split("/")
|
111
|
+
|
112
|
+
LicenseScout::Log.warn("[habitat] Could not find pkg_info for #{pkg_ident} - trying for the latest version of #{pkg_origin}/#{pkg_name}")
|
113
|
+
FFI_Yajl::Parser.parse(open("https://bldr.habitat.sh/v1/depot/channels/#{pkg_origin}/stable/pkgs/#{pkg_name}/latest").read)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def plan_sh_path
|
118
|
+
File.join(directory, "plan.sh")
|
119
|
+
end
|
120
|
+
|
121
|
+
def habitat_plan_sh_path
|
122
|
+
File.join(directory, "habitat", "plan.sh")
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|