licensed 3.0.1 → 3.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +19 -0
- data/.github/workflows/release.yml +4 -4
- data/.github/workflows/test.yml +180 -47
- data/.ruby-version +1 -1
- data/CHANGELOG.md +60 -1
- data/README.md +25 -79
- data/docker/Dockerfile.build-linux +1 -1
- data/docs/adding_a_new_source.md +11 -8
- data/docs/commands/README.md +59 -0
- data/docs/commands/cache.md +35 -0
- data/docs/commands/env.md +10 -0
- data/docs/commands/list.md +23 -0
- data/docs/commands/migrate.md +10 -0
- data/docs/commands/notices.md +12 -0
- data/docs/commands/status.md +74 -0
- data/docs/commands/version.md +3 -0
- data/docs/configuration/README.md +11 -0
- data/docs/configuration/allowed_licenses.md +17 -0
- data/docs/configuration/application_name.md +63 -0
- data/docs/configuration/application_source.md +64 -0
- data/docs/configuration/configuration_root.md +27 -0
- data/docs/configuration/configuring_multiple_apps.md +58 -0
- data/docs/configuration/dependency_source_enumerators.md +28 -0
- data/docs/configuration/ignoring_dependencies.md +19 -0
- data/docs/configuration/metadata_cache.md +106 -0
- data/docs/configuration/reviewing_dependencies.md +18 -0
- data/docs/configuration.md +9 -161
- data/docs/sources/swift.md +4 -0
- data/lib/licensed/cli.rb +2 -2
- data/lib/licensed/commands/cache.rb +19 -20
- data/lib/licensed/commands/command.rb +104 -72
- data/lib/licensed/commands/environment.rb +12 -11
- data/lib/licensed/commands/list.rb +0 -19
- data/lib/licensed/commands/notices.rb +0 -19
- data/lib/licensed/commands/status.rb +13 -15
- data/lib/licensed/configuration.rb +105 -12
- data/lib/licensed/report.rb +44 -0
- data/lib/licensed/reporters/cache_reporter.rb +48 -64
- data/lib/licensed/reporters/json_reporter.rb +19 -21
- data/lib/licensed/reporters/list_reporter.rb +45 -58
- data/lib/licensed/reporters/notices_reporter.rb +33 -46
- data/lib/licensed/reporters/reporter.rb +37 -104
- data/lib/licensed/reporters/status_reporter.rb +58 -56
- data/lib/licensed/reporters/yaml_reporter.rb +19 -21
- data/lib/licensed/sources/bundler/definition.rb +36 -0
- data/lib/licensed/sources/bundler/missing_specification.rb +1 -1
- data/lib/licensed/sources/bundler.rb +38 -69
- data/lib/licensed/sources/dep.rb +2 -2
- data/lib/licensed/sources/go.rb +3 -3
- data/lib/licensed/sources/gradle.rb +2 -2
- data/lib/licensed/sources/helpers/content_versioning.rb +2 -1
- data/lib/licensed/sources/npm.rb +4 -3
- data/lib/licensed/sources/nuget.rb +56 -27
- data/lib/licensed/sources/swift.rb +69 -0
- data/lib/licensed/sources.rb +1 -0
- data/lib/licensed/version.rb +1 -1
- data/lib/licensed.rb +1 -0
- data/licensed.gemspec +4 -4
- data/script/source-setup/go +1 -1
- data/script/source-setup/swift +22 -0
- metadata +48 -13
- data/docs/commands.md +0 -95
@@ -29,12 +29,6 @@ module Licensed
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
def run(**options)
|
33
|
-
super do |report|
|
34
|
-
report["git_repo"] = Licensed::Git.git_repo?
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
32
|
# Returns the default reporter to use during the command run
|
39
33
|
#
|
40
34
|
# options - The options the command was run with
|
@@ -46,11 +40,18 @@ module Licensed
|
|
46
40
|
|
47
41
|
protected
|
48
42
|
|
49
|
-
def
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
43
|
+
def run_command(report)
|
44
|
+
report["git_repo"] = Licensed::Git.git_repo?
|
45
|
+
super
|
46
|
+
end
|
47
|
+
|
48
|
+
def run_app(app, report)
|
49
|
+
report.merge! AppEnvironment.new(app).to_h
|
50
|
+
super
|
51
|
+
end
|
52
|
+
|
53
|
+
def run_source(app, source, report)
|
54
|
+
true
|
54
55
|
end
|
55
56
|
end
|
56
57
|
end
|
@@ -13,25 +13,6 @@ module Licensed
|
|
13
13
|
|
14
14
|
protected
|
15
15
|
|
16
|
-
# Run the command for all enumerated dependencies found in a dependency source,
|
17
|
-
# recording results in a report.
|
18
|
-
# Enumerating dependencies in the source is skipped if a :sources option
|
19
|
-
# is provided and the evaluated `source.class.type` is not in the :sources values
|
20
|
-
#
|
21
|
-
# app - The application configuration for the source
|
22
|
-
# source - A dependency source enumerator
|
23
|
-
#
|
24
|
-
# Returns whether the command succeeded for the dependency source enumerator
|
25
|
-
def run_source(app, source)
|
26
|
-
super do |report|
|
27
|
-
next if Array(options[:sources]).empty?
|
28
|
-
next if options[:sources].include?(source.class.type)
|
29
|
-
|
30
|
-
report.warnings << "skipped source"
|
31
|
-
:skip
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
16
|
# Listing dependencies requires no extra work.
|
36
17
|
#
|
37
18
|
# app - The application configuration for the dependency
|
@@ -13,25 +13,6 @@ module Licensed
|
|
13
13
|
|
14
14
|
protected
|
15
15
|
|
16
|
-
# Run the command for all enumerated dependencies found in a dependency source,
|
17
|
-
# recording results in a report.
|
18
|
-
# Enumerating dependencies in the source is skipped if a :sources option
|
19
|
-
# is provided and the evaluated `source.class.type` is not in the :sources values
|
20
|
-
#
|
21
|
-
# app - The application configuration for the source
|
22
|
-
# source - A dependency source enumerator
|
23
|
-
#
|
24
|
-
# Returns whether the command succeeded for the dependency source enumerator
|
25
|
-
def run_source(app, source)
|
26
|
-
super do |report|
|
27
|
-
next if Array(options[:sources]).empty?
|
28
|
-
next if options[:sources].include?(source.class.type)
|
29
|
-
|
30
|
-
report.warnings << "skipped source"
|
31
|
-
:skip
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
16
|
# Load stored dependency record data to add to the notices report.
|
36
17
|
#
|
37
18
|
# app - The application configuration for the dependency
|
@@ -15,22 +15,17 @@ module Licensed
|
|
15
15
|
|
16
16
|
protected
|
17
17
|
|
18
|
-
# Run the
|
19
|
-
#
|
20
|
-
# Enumerating dependencies in the source is skipped if a :sources option
|
21
|
-
# is provided and the evaluated `source.class.type` is not in the :sources values
|
18
|
+
# Run the comand and set an error message to review the documentation
|
19
|
+
# when any errors have been reported
|
22
20
|
#
|
23
|
-
#
|
24
|
-
# source - A dependency source enumerator
|
21
|
+
# report - A Licensed::Report object for this command
|
25
22
|
#
|
26
|
-
# Returns whether the command succeeded
|
27
|
-
def
|
28
|
-
super do |
|
29
|
-
next if
|
30
|
-
|
31
|
-
|
32
|
-
report.warnings << "skipped source"
|
33
|
-
:skip
|
23
|
+
# Returns whether the command succeeded based on the call to super
|
24
|
+
def run_command(report)
|
25
|
+
super do |result|
|
26
|
+
next if result
|
27
|
+
|
28
|
+
report.errors << "Licensed found errors during source enumeration. Please see https://github.com/github/licensed/tree/master/docs/commands/status.md#status-errors-and-resolutions for possible resolutions."
|
34
29
|
end
|
35
30
|
end
|
36
31
|
|
@@ -47,11 +42,14 @@ module Licensed
|
|
47
42
|
def evaluate_dependency(app, source, dependency, report)
|
48
43
|
filename = app.cache_path.join(source.class.type, "#{dependency.name}.#{DependencyRecord::EXTENSION}")
|
49
44
|
report["filename"] = filename
|
45
|
+
report["version"] = dependency.version
|
50
46
|
|
51
47
|
cached_record = cached_record(filename)
|
52
48
|
if cached_record.nil?
|
49
|
+
report["license"] = nil
|
53
50
|
report.errors << "cached dependency record not found"
|
54
51
|
else
|
52
|
+
report["license"] = cached_record["license"]
|
55
53
|
report.errors << "cached dependency record out of date" if cached_record["version"] != dependency.version
|
56
54
|
report.errors << "missing license text" if cached_record.licenses.empty?
|
57
55
|
if cached_record["review_changed_license"]
|
@@ -61,7 +59,7 @@ module Licensed
|
|
61
59
|
end
|
62
60
|
end
|
63
61
|
|
64
|
-
report.errors.empty?
|
62
|
+
report["allowed"] = report.errors.empty?
|
65
63
|
end
|
66
64
|
|
67
65
|
# Returns true if a cached record needs further review based on the
|
@@ -3,9 +3,14 @@ require "pathname"
|
|
3
3
|
|
4
4
|
module Licensed
|
5
5
|
class AppConfiguration < Hash
|
6
|
+
DIRECTORY_NAME_GENERATOR_KEY = "directory_name".freeze
|
7
|
+
RELATIVE_PATH_GENERATOR_KEY = "relative_path".freeze
|
8
|
+
DEFAULT_RELATIVE_PATH_NAME_SEPARATOR = "-".freeze
|
9
|
+
ALL_NAME_GENERATOR_KEYS = [DIRECTORY_NAME_GENERATOR_KEY, RELATIVE_PATH_GENERATOR_KEY].freeze
|
10
|
+
|
6
11
|
DEFAULT_CACHE_PATH = ".licenses".freeze
|
7
12
|
|
8
|
-
# Returns the root for a configuration in following order of
|
13
|
+
# Returns the root for a configuration in following order of precedence:
|
9
14
|
# 1. explicitly configured "root" property
|
10
15
|
# 2. a found git repository root
|
11
16
|
# 3. the current directory
|
@@ -28,9 +33,9 @@ module Licensed
|
|
28
33
|
self["ignored"] ||= {}
|
29
34
|
self["allowed"] ||= []
|
30
35
|
self["root"] = AppConfiguration.root_for(self)
|
31
|
-
|
32
|
-
|
33
|
-
#
|
36
|
+
self["name"] = generate_app_name
|
37
|
+
# setting the cache path might need a valid app name.
|
38
|
+
# this must come after setting self["name"]
|
34
39
|
self["cache_path"] = detect_cache_path(options, inherited_options)
|
35
40
|
end
|
36
41
|
|
@@ -105,8 +110,9 @@ module Licensed
|
|
105
110
|
|
106
111
|
# Returns the cache path for the application based on:
|
107
112
|
# 1. An explicitly set cache path for the application, if set
|
108
|
-
# 2. An inherited
|
109
|
-
# 3.
|
113
|
+
# 2. An inherited shared cache path
|
114
|
+
# 3. An inherited cache path joined with the app name if not shared
|
115
|
+
# 4. The default cache path joined with the app name
|
110
116
|
def detect_cache_path(options, inherited_options)
|
111
117
|
return options["cache_path"] unless options["cache_path"].to_s.empty?
|
112
118
|
|
@@ -124,6 +130,65 @@ module Licensed
|
|
124
130
|
raise Licensed::Configuration::LoadError,
|
125
131
|
"App #{self["name"]} is missing required property #{property}"
|
126
132
|
end
|
133
|
+
|
134
|
+
# Returns a name for the application as one of:
|
135
|
+
# 1. An explicitly configured app name, if set
|
136
|
+
# 2. A generated app name based on an configured "name" options hash
|
137
|
+
# 3. A default value - the source_path directory name
|
138
|
+
def generate_app_name
|
139
|
+
# use default_app_name if a name value is not set
|
140
|
+
return source_path_directory_app_name if self["name"].to_s.empty?
|
141
|
+
# keep the same name value unless a hash is given with naming options
|
142
|
+
return self["name"] unless self["name"].is_a?(Hash)
|
143
|
+
|
144
|
+
generator = self.dig("name", "generator")
|
145
|
+
case generator
|
146
|
+
when nil, DIRECTORY_NAME_GENERATOR_KEY
|
147
|
+
source_path_directory_app_name
|
148
|
+
when RELATIVE_PATH_GENERATOR_KEY
|
149
|
+
relative_path_app_name
|
150
|
+
else
|
151
|
+
raise Licensed::Configuration::LoadError,
|
152
|
+
"Invalid value configured for name.generator: #{generator}. Value must be one of #{ALL_NAME_GENERATOR_KEYS.join(",")}"
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# Returns an app name from the directory name of the configured source path
|
157
|
+
def source_path_directory_app_name
|
158
|
+
File.basename(self["source_path"])
|
159
|
+
end
|
160
|
+
|
161
|
+
# Returns an app name from the relative path from the configured app root
|
162
|
+
# to the configured app source path.
|
163
|
+
def relative_path_app_name
|
164
|
+
source_path_parts = File.expand_path(self["source_path"]).split("/")
|
165
|
+
root_path_parts = File.expand_path(self["root"]).split("/")
|
166
|
+
|
167
|
+
# if the source path is equivalent to the root path,
|
168
|
+
# return the root directory name
|
169
|
+
return root_path_parts[-1] if source_path_parts == root_path_parts
|
170
|
+
|
171
|
+
if source_path_parts[0..root_path_parts.size-1] != root_path_parts
|
172
|
+
raise Licensed::Configuration::LoadError,
|
173
|
+
"source_path must be a descendent of the app root to generate an app name from the relative source_path"
|
174
|
+
end
|
175
|
+
|
176
|
+
name_parts = source_path_parts[root_path_parts.size..-1]
|
177
|
+
|
178
|
+
separator = self.dig("name", "separator") || DEFAULT_RELATIVE_PATH_NAME_SEPARATOR
|
179
|
+
depth = self.dig("name", "depth") || 0
|
180
|
+
if depth < 0
|
181
|
+
raise Licensed::Configuration::LoadError, "name.depth configuration value cannot be less than -1"
|
182
|
+
end
|
183
|
+
|
184
|
+
# offset the depth value by -1 to work as an offset from the end of the array
|
185
|
+
# 0 becomes -1, with a start index of (-1 - -1) = 0, or the full array
|
186
|
+
# 1 becomes 0, with a start index of (-1 - 0) = -1, or only the last element
|
187
|
+
# and so on...
|
188
|
+
depth = depth - 1
|
189
|
+
start_index = depth >= name_parts.length ? 0 : -1 - depth
|
190
|
+
name_parts[start_index..-1].join(separator)
|
191
|
+
end
|
127
192
|
end
|
128
193
|
|
129
194
|
class Configuration
|
@@ -151,6 +216,11 @@ module Licensed
|
|
151
216
|
def initialize(options = {})
|
152
217
|
apps = options.delete("apps") || []
|
153
218
|
apps << default_options.merge(options) if apps.empty?
|
219
|
+
|
220
|
+
# apply a root setting to all app configurations so that it's available
|
221
|
+
# when expanding app source paths
|
222
|
+
apps.each { |app| app["root"] ||= options["root"] if options["root"] }
|
223
|
+
|
154
224
|
apps = apps.flat_map { |app| self.class.expand_app_source_path(app) }
|
155
225
|
@apps = apps.map { |app| AppConfiguration.new(app, options) }
|
156
226
|
end
|
@@ -158,25 +228,48 @@ module Licensed
|
|
158
228
|
private
|
159
229
|
|
160
230
|
def self.expand_app_source_path(app_config)
|
161
|
-
|
231
|
+
# map a source_path configuration value to an array of non-empty values
|
232
|
+
source_path_array = Array(app_config["source_path"])
|
233
|
+
.reject { |path| path.to_s.empty? }
|
234
|
+
.compact
|
235
|
+
app_root = AppConfiguration.root_for(app_config)
|
236
|
+
return app_config.merge("source_path" => app_root) if source_path_array.empty?
|
162
237
|
|
163
238
|
# check if the source path maps to an existing directory
|
164
|
-
|
165
|
-
|
239
|
+
if source_path_array.length == 1
|
240
|
+
source_path = File.expand_path(source_path_array[0], app_root)
|
241
|
+
return app_config.merge("source_path" => source_path) if Dir.exist?(source_path)
|
242
|
+
end
|
166
243
|
|
167
244
|
# try to expand the source path for glob patterns
|
168
|
-
expanded_source_paths =
|
245
|
+
expanded_source_paths = source_path_array.reduce(Set.new) do |matched_paths, pattern|
|
246
|
+
current_matched_paths = if pattern.start_with?("!")
|
247
|
+
# if the pattern is an exclusion, remove all matching files
|
248
|
+
# from the result
|
249
|
+
matched_paths - Dir.glob(pattern[1..-1])
|
250
|
+
else
|
251
|
+
# if the pattern is an inclusion, add all matching files
|
252
|
+
# to the result
|
253
|
+
matched_paths + Dir.glob(pattern)
|
254
|
+
end
|
255
|
+
|
256
|
+
current_matched_paths.select { |p| File.directory?(p) }
|
257
|
+
end
|
258
|
+
|
169
259
|
configs = expanded_source_paths.map { |path| app_config.merge("source_path" => path) }
|
170
260
|
|
171
261
|
# if no directories are found for the source path, return the original config
|
172
|
-
|
262
|
+
if configs.size == 0
|
263
|
+
app_config["source_path"] = app_root if app_config["source_path"].is_a?(Array)
|
264
|
+
return app_config
|
265
|
+
end
|
173
266
|
|
174
267
|
# update configured values for name and cache_path for uniqueness.
|
175
268
|
# this is only needed when values are explicitly set, AppConfiguration
|
176
269
|
# will handle configurations that don't have these explicitly set
|
177
270
|
configs.each do |config|
|
178
271
|
dir_name = File.basename(config["source_path"])
|
179
|
-
config["name"] = "#{config["name"]}-#{dir_name}" if config["name"]
|
272
|
+
config["name"] = "#{config["name"]}-#{dir_name}" if config["name"].is_a?(String)
|
180
273
|
|
181
274
|
# if a cache_path is set and is not marked as shared, append the app name
|
182
275
|
# to the end of the cache path to make a unique cache path for the app
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Licensed
|
4
|
+
class Report < Hash
|
5
|
+
attr_reader :name
|
6
|
+
attr_reader :target
|
7
|
+
def initialize(name:, target:)
|
8
|
+
super()
|
9
|
+
@name = name
|
10
|
+
@target = target
|
11
|
+
end
|
12
|
+
|
13
|
+
def reports
|
14
|
+
@reports ||= []
|
15
|
+
end
|
16
|
+
|
17
|
+
def errors
|
18
|
+
@errors ||= []
|
19
|
+
end
|
20
|
+
|
21
|
+
def warnings
|
22
|
+
@warnings ||= []
|
23
|
+
end
|
24
|
+
|
25
|
+
def all_reports
|
26
|
+
result = []
|
27
|
+
result << self
|
28
|
+
result.push(*reports.flat_map(&:all_reports))
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns the data from the report as a hash
|
32
|
+
def to_h
|
33
|
+
# add name, errors and warnings if they have real data
|
34
|
+
output = {}
|
35
|
+
output["name"] = name unless name.to_s.empty?
|
36
|
+
output["errors"] = errors.dup if errors.any?
|
37
|
+
output["warnings"] = warnings.dup if warnings.any?
|
38
|
+
|
39
|
+
# merge the hash data from the report. command-specified data always
|
40
|
+
# overwrites local data
|
41
|
+
output.merge(super)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -2,89 +2,73 @@
|
|
2
2
|
module Licensed
|
3
3
|
module Reporters
|
4
4
|
class CacheReporter < Reporter
|
5
|
-
# Reports
|
5
|
+
# Reports the start of caching records for an app
|
6
6
|
#
|
7
7
|
# app - An application configuration
|
8
|
-
#
|
9
|
-
|
10
|
-
|
11
|
-
def report_app(app)
|
12
|
-
super do |report|
|
13
|
-
shell.info "Caching dependency records for #{app["name"]}"
|
14
|
-
yield report
|
15
|
-
end
|
8
|
+
# report - A report containing information about the app evaluation
|
9
|
+
def begin_report_app(app, report)
|
10
|
+
shell.info "Caching dependency records for #{app["name"]}"
|
16
11
|
end
|
17
12
|
|
18
|
-
# Reports
|
19
|
-
# Shows the type and count of dependencies found by the source.
|
13
|
+
# Reports the start of caching records for a dependency source
|
20
14
|
#
|
21
15
|
# source - A dependency source enumerator
|
22
|
-
#
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
super do |report|
|
27
|
-
shell.info " #{source.class.type}"
|
28
|
-
result = yield report
|
16
|
+
# report - A report containing information about the source evaluation
|
17
|
+
def begin_report_source(source, report)
|
18
|
+
shell.info " #{source.class.type}"
|
19
|
+
end
|
29
20
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
21
|
+
# Reports warnings and errors found while evaluating the dependency source
|
22
|
+
#
|
23
|
+
# source - A dependency source enumerator
|
24
|
+
# report - A report containing information about the source evaluation
|
25
|
+
def end_report_source(source, report)
|
26
|
+
warning_reports = report.all_reports.select { |r| r.warnings.any? }.to_a
|
27
|
+
if warning_reports.any?
|
28
|
+
shell.newline
|
29
|
+
shell.warn " * Warnings:"
|
30
|
+
warning_reports.each do |r|
|
31
|
+
display_metadata = r.map { |k, v| "#{k}: #{v}" }.join(", ")
|
36
32
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
end
|
42
|
-
shell.newline
|
33
|
+
shell.warn " * #{r.name}"
|
34
|
+
shell.warn " #{display_metadata}" unless display_metadata.empty?
|
35
|
+
r.warnings.each do |warning|
|
36
|
+
shell.warn " - #{warning}"
|
43
37
|
end
|
38
|
+
shell.newline
|
44
39
|
end
|
40
|
+
end
|
45
41
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
42
|
+
errored_reports = report.all_reports.select { |r| r.errors.any? }.to_a
|
43
|
+
if errored_reports.any?
|
44
|
+
shell.newline
|
45
|
+
shell.error " * Errors:"
|
46
|
+
errored_reports.each do |r|
|
47
|
+
display_metadata = r.map { |k, v| "#{k}: #{v}" }.join(", ")
|
52
48
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
end
|
58
|
-
shell.newline
|
49
|
+
shell.error " * #{r.name}"
|
50
|
+
shell.error " #{display_metadata}" unless display_metadata.empty?
|
51
|
+
r.errors.each do |error|
|
52
|
+
shell.error " - #{error}"
|
59
53
|
end
|
60
|
-
|
61
|
-
shell.confirm " * #{report.reports.size} #{source.class.type} dependencies"
|
54
|
+
shell.newline
|
62
55
|
end
|
63
|
-
|
64
|
-
|
56
|
+
else
|
57
|
+
shell.confirm " * #{report.reports.size} #{source.class.type} dependencies"
|
65
58
|
end
|
66
59
|
end
|
67
60
|
|
68
|
-
# Reports
|
69
|
-
# Shows whether the dependency's record was cached or reused.
|
61
|
+
# Reports whether the dependency's record was cached or reused.
|
70
62
|
#
|
71
63
|
# dependency - An application dependency
|
72
|
-
#
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
shell.error " Error #{dependency.name} (#{dependency.version})"
|
81
|
-
elsif report["cached"]
|
82
|
-
shell.info " Caching #{dependency.name} (#{dependency.version})"
|
83
|
-
else
|
84
|
-
shell.info " Using #{dependency.name} (#{dependency.version})"
|
85
|
-
end
|
86
|
-
|
87
|
-
result
|
64
|
+
# report - A report containing information about the dependency evaluation
|
65
|
+
def end_report_dependency(dependency, report)
|
66
|
+
if report.errors.any?
|
67
|
+
shell.error " Error #{dependency.name} (#{dependency.version})"
|
68
|
+
elsif report["cached"]
|
69
|
+
shell.info " Caching #{dependency.name} (#{dependency.version})"
|
70
|
+
else
|
71
|
+
shell.info " Using #{dependency.name} (#{dependency.version})"
|
88
72
|
end
|
89
73
|
end
|
90
74
|
end
|