licensed 3.0.0 → 3.2.1
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.
- 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 -86
- 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
|