licensed 2.9.0 → 2.11.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/workflows/release.yml +11 -12
- data/.github/workflows/test.yml +69 -50
- data/.gitignore +2 -0
- data/CHANGELOG.md +42 -4
- data/README.md +11 -7
- data/docs/commands.md +6 -0
- data/docs/configuration.md +20 -0
- data/docs/sources/nuget.md +14 -0
- data/lib/licensed/cli.rb +7 -0
- data/lib/licensed/commands.rb +1 -0
- data/lib/licensed/commands/cache.rb +47 -17
- data/lib/licensed/commands/notices.rb +35 -0
- data/lib/licensed/configuration.rb +12 -2
- data/lib/licensed/dependency.rb +1 -1
- data/lib/licensed/reporters.rb +1 -0
- data/lib/licensed/reporters/cache_reporter.rb +10 -10
- data/lib/licensed/reporters/list_reporter.rb +5 -5
- data/lib/licensed/reporters/notices_reporter.rb +77 -0
- data/lib/licensed/reporters/reporter.rb +3 -0
- data/lib/licensed/reporters/status_reporter.rb +7 -7
- data/lib/licensed/sources.rb +1 -0
- data/lib/licensed/sources/cabal.rb +2 -2
- data/lib/licensed/sources/go.rb +2 -2
- data/lib/licensed/sources/npm.rb +1 -0
- data/lib/licensed/sources/nuget.rb +212 -0
- data/lib/licensed/version.rb +1 -1
- data/licensed.gemspec +3 -2
- data/script/source-setup/nuget +17 -0
- metadata +25 -6
data/CHANGELOG.md
CHANGED
@@ -6,17 +6,55 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## 2.11.1
|
10
|
+
2020-06-09
|
11
|
+
|
12
|
+
### Fixed
|
13
|
+
- `notices` command properly reads cached dependency notices contents (https://github.com/github/licensed/pull/283)
|
14
|
+
|
15
|
+
## 2.11.0
|
16
|
+
2020-06-02
|
17
|
+
|
18
|
+
### Added
|
19
|
+
- `notices` command to create a `NOTICE` file for each configured app (https://github.com/github/licensed/pull/277)
|
20
|
+
|
21
|
+
### Fixed
|
22
|
+
- NuGet source no longer crashes on a non-existent dependency path (https://github.com/github/licensed/pull/280)
|
23
|
+
- Go source no longer crashes on a non-existent dependency package path (https://github.com/github/licensed/pull/274)
|
24
|
+
|
25
|
+
## 2.10.0
|
26
|
+
2020-05-15
|
27
|
+
|
28
|
+
### Changed
|
29
|
+
- NPM source ignores missing peer dependencies (https://github.com/github/licensed/pull/267)
|
30
|
+
|
31
|
+
### Added
|
32
|
+
- NuGet source (:tada: @zarenner https://github.com/github/licensed/pull/261)
|
33
|
+
- Multiple apps can share a single cache location (https://github.com/github/licensed/pull/263)
|
34
|
+
|
35
|
+
## 2.9.2
|
36
|
+
2020-04-28
|
37
|
+
|
38
|
+
### Changed
|
39
|
+
- `licensee` minimum version bumped to 9.13.2 (https://github.com/github/licensed/pull/256)
|
40
|
+
|
41
|
+
## 2.9.1
|
42
|
+
2020-03-24
|
43
|
+
|
44
|
+
### Changed
|
45
|
+
- relaxed gem version restrictions on Thor (:tada: @eileencodes https://github.com/github/licensed/pull/254)
|
46
|
+
|
9
47
|
## 2.9.0
|
10
48
|
2020-03-19
|
11
49
|
|
12
|
-
|
50
|
+
### Added
|
13
51
|
- Source paths use glob pattern matching (https://github.com/github/licensed/pull/245)
|
14
52
|
|
15
|
-
|
53
|
+
### Fixed
|
16
54
|
- Mix source supports updates to mix.lock format (:tada: @bruce https://github.com/github/licensed/pull/242)
|
17
55
|
- Go source supports `go list` format changes in go 1.14 (https://github.com/github/licensed/pull/247)
|
18
56
|
|
19
|
-
|
57
|
+
### Changed
|
20
58
|
- `licensed cache` will flag dependencies for re-review when license text changes (https://github.com/github/licensed/pull/248)
|
21
59
|
- `licensed status` will raise errors on dependencies that need re-review (https://github.com/github/licensed/pull/248)
|
22
60
|
- `licensee` minimum version bumped to 9.13.1 (https://github.com/github/licensed/pull/251)
|
@@ -280,4 +318,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
280
318
|
|
281
319
|
Initial release :tada:
|
282
320
|
|
283
|
-
[Unreleased]: https://github.com/github/licensed/compare/2.
|
321
|
+
[Unreleased]: https://github.com/github/licensed/compare/2.11.1...HEAD
|
data/README.md
CHANGED
@@ -24,13 +24,13 @@ See the [migration documentation](./docs/migrating_to_newer_versions.md) for mor
|
|
24
24
|
### Dependencies
|
25
25
|
|
26
26
|
Licensed uses the `libgit2` bindings for Ruby provided by `rugged`. `rugged` requires `cmake` and `pkg-config` which you may need to install before you can install Licensed.
|
27
|
-
|
27
|
+
|
28
28
|
> Ubuntu
|
29
|
-
|
29
|
+
|
30
30
|
sudo apt-get install cmake pkg-config
|
31
|
-
|
31
|
+
|
32
32
|
> OS X
|
33
|
-
|
33
|
+
|
34
34
|
brew install cmake pkg-config
|
35
35
|
|
36
36
|
### With a Gemfile
|
@@ -64,8 +64,10 @@ For system wide usage, install licensed to a location on `$PATH`, e.g. `/usr/loc
|
|
64
64
|
|
65
65
|
- `licensed list`: Output enumerated dependencies only.
|
66
66
|
- `licensed cache`: Cache licenses and metadata.
|
67
|
-
- `licensed status`: Check status of dependencies' cached licenses.
|
67
|
+
- `licensed status`: Check status of dependencies' cached licenses.
|
68
|
+
- `licensed notices`: Write a `NOTICE` file for each application configuration.
|
68
69
|
- `licensed version`: Show current installed version of Licensed. Aliases: `-v|--version`
|
70
|
+
- `licensed env`: Output environment information from the licensed configuration.
|
69
71
|
|
70
72
|
See the [commands documentation](./docs/commands.md) for additional documentation, or run `licensed -h` to see all of the current available commands.
|
71
73
|
|
@@ -102,14 +104,16 @@ Dependencies will be automatically detected for all of the following sources by
|
|
102
104
|
1. [Bundler](./docs/sources/bundler.md)
|
103
105
|
1. [Cabal](./docs/sources/cabal.md)
|
104
106
|
1. [Composer](./docs/sources/composer.md)
|
107
|
+
1. [Git Submodules (git_submodule)](./docs/sources/git_submodule.md)
|
105
108
|
1. [Go](./docs/sources/go.md)
|
106
109
|
1. [Go Dep (dep)](./docs/sources/dep.md)
|
110
|
+
1. [Gradle](./docs/sources/gradle.md)
|
107
111
|
1. [Manifest lists (manifests)](./docs/sources/manifests.md)
|
112
|
+
1. [Mix](./docs/sources/mix.md)
|
108
113
|
1. [NPM](./docs/sources/npm.md)
|
114
|
+
1. [NuGet](./docs/sources/nuget.md)
|
109
115
|
1. [Pip](./docs/sources/pip.md)
|
110
116
|
1. [Pipenv](./docs/sources/pipenv.md)
|
111
|
-
1. [Git Submodules (git_submodule)](./docs/sources/git_submodule.md)
|
112
|
-
1. [Mix](./docs/sources/mix.md)
|
113
117
|
1. [Yarn](./docs/sources/yarn.md)
|
114
118
|
|
115
119
|
You can disable any of them in the configuration file:
|
data/docs/commands.md
CHANGED
@@ -31,6 +31,12 @@ A dependency will fail the status checks if:
|
|
31
31
|
5. The cached record is flagged for re-review.
|
32
32
|
- This occurs when the record's license text has changed since the record was reviewed.
|
33
33
|
|
34
|
+
## `notices`
|
35
|
+
|
36
|
+
Outputs license and notice text for all dependencies in each app into a `NOTICE` file in the app's `cache_path`. If an app uses a shared cache path, the file name will contain the app name as well, e.g. `NOTICE.my_app`.
|
37
|
+
|
38
|
+
The `NOTICE` file contents are retrieved from cached records, with the assumption that cached records have already been reviewed in a compliance workflow.
|
39
|
+
|
34
40
|
## `env`
|
35
41
|
|
36
42
|
Prints the runtime environment used by licensed after loading a configuration file. By default the output is in YAML format, but can be output in JSON using the `--json` flag.
|
data/docs/configuration.md
CHANGED
@@ -209,6 +209,26 @@ apps:
|
|
209
209
|
|
210
210
|
In this example, the root configuration will contain a default cache path of `.licenses`. `app1` will inherit this value and append it's name, resulting in a cache path of `.licenses/app1`.
|
211
211
|
|
212
|
+
### Sharing caches between apps
|
213
|
+
|
214
|
+
Dependency caches can be shared between apps by setting the same cache path on each app.
|
215
|
+
|
216
|
+
```yaml
|
217
|
+
apps:
|
218
|
+
- source_path: "path/to/app1"
|
219
|
+
cache_path: ".licenses/apps"
|
220
|
+
- source_path: "path/to/app2"
|
221
|
+
cache_path: ".licenses/apps"
|
222
|
+
```
|
223
|
+
|
224
|
+
When using a source path with a glob pattern, the apps created from the glob pattern can share a dependency by setting an explicit cache path and setting `shared_cache` to true.
|
225
|
+
|
226
|
+
```yaml
|
227
|
+
source_path: "path/to/apps/*"
|
228
|
+
cache_path: ".licenses/apps"
|
229
|
+
shared_cache: true
|
230
|
+
```
|
231
|
+
|
212
232
|
## Source specific configuration
|
213
233
|
|
214
234
|
See the [source documentation](./sources) for details on any source specific configuration.
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# NuGet
|
2
|
+
|
3
|
+
The NuGet source will detect ProjectReference-style restored packages by inspecting `project.assets.json` files for dependencies. It requires that `dotnet restore` has already ran on the project.
|
4
|
+
|
5
|
+
The source currently expects that `source_path` is set to the `obj` directory containing the `project.assets.json`.
|
6
|
+
For example, if your project lives at `foo/foo.proj`, you likely want to set `source_path` to `foo/obj`.
|
7
|
+
If in MSBuild you have customized your `obj` paths (e.g. to live outside your source tree), you may need to set `source_path` to something different such as `../obj/foo`.
|
8
|
+
|
9
|
+
### Search strategy
|
10
|
+
This source looks for licenses:
|
11
|
+
1. Specified by SPDX expression via `<license type="expression">` in a package's `.nuspec` (via licensee)
|
12
|
+
2. In license files such as `LICENSE.txt`, even if not specified in the `.nuspec` (via licensee)
|
13
|
+
3. Specified by filepath via `<license type="file">` in a package's `.nuspec`, even if not a standard license filename.
|
14
|
+
4. By downloading and inspecting the contents of `<licenseUrl>` in a package's `.nuspec`, if not found otherwise.
|
data/lib/licensed/cli.rb
CHANGED
@@ -28,6 +28,13 @@ module Licensed
|
|
28
28
|
run Licensed::Commands::List.new(config: config)
|
29
29
|
end
|
30
30
|
|
31
|
+
desc "notices", "Generate a NOTICE file from cached records"
|
32
|
+
method_option :config, aliases: "-c", type: :string,
|
33
|
+
desc: "Path to licensed configuration file"
|
34
|
+
def notices
|
35
|
+
run Licensed::Commands::Notices.new(config: config)
|
36
|
+
end
|
37
|
+
|
31
38
|
map "-v" => :version
|
32
39
|
map "--version" => :version
|
33
40
|
desc "version", "Show Installed Version of Licensed, [-v, --version]"
|
data/lib/licensed/commands.rb
CHANGED
@@ -11,20 +11,39 @@ module Licensed
|
|
11
11
|
Licensed::Reporters::CacheReporter.new
|
12
12
|
end
|
13
13
|
|
14
|
+
# Run the command.
|
15
|
+
# Removes any cached records that don't match a current application
|
16
|
+
# dependency.
|
17
|
+
#
|
18
|
+
# options - Options to run the command with
|
19
|
+
#
|
20
|
+
# Returns whether the command was a success
|
21
|
+
def run(**options)
|
22
|
+
begin
|
23
|
+
result = super
|
24
|
+
clear_stale_cached_records if result
|
25
|
+
|
26
|
+
result
|
27
|
+
ensure
|
28
|
+
cache_paths.clear
|
29
|
+
files.clear
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
14
33
|
protected
|
15
34
|
|
16
|
-
# Run the command for all
|
35
|
+
# Run the command for all enabled sources for an application configuration,
|
17
36
|
# recording results in a report.
|
18
|
-
# Removes any cached records that don't match a current application
|
19
|
-
# dependency.
|
20
37
|
#
|
21
|
-
# app -
|
22
|
-
# source - A dependency source enumerator
|
38
|
+
# app - An application configuration
|
23
39
|
#
|
24
|
-
# Returns whether the command succeeded for the
|
25
|
-
def
|
40
|
+
# Returns whether the command succeeded for the application.
|
41
|
+
def run_app(app)
|
26
42
|
result = super
|
27
|
-
|
43
|
+
|
44
|
+
# add the full cache path to the list of cache paths evaluted during this run
|
45
|
+
cache_paths << app.cache_path
|
46
|
+
|
28
47
|
result
|
29
48
|
end
|
30
49
|
|
@@ -62,6 +81,9 @@ module Licensed
|
|
62
81
|
report.warnings << "expected dependency path #{dependency.path} does not exist"
|
63
82
|
end
|
64
83
|
|
84
|
+
# add the absolute dependency file path to the list of files seen during this licensed run
|
85
|
+
files << filename.to_s
|
86
|
+
|
65
87
|
true
|
66
88
|
end
|
67
89
|
|
@@ -86,18 +108,26 @@ module Licensed
|
|
86
108
|
|
87
109
|
# Clean up cached files that dont match current dependencies
|
88
110
|
#
|
89
|
-
# app - An application configuration
|
90
|
-
# source - A dependency source enumerator
|
91
|
-
#
|
92
111
|
# Returns nothing
|
93
|
-
def clear_stale_cached_records
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
112
|
+
def clear_stale_cached_records
|
113
|
+
cache_paths.each do |cache_path|
|
114
|
+
Dir.glob(cache_path.join("**/*.#{DependencyRecord::EXTENSION}")).each do |file|
|
115
|
+
next if files.include?(file)
|
116
|
+
|
117
|
+
FileUtils.rm(file)
|
118
|
+
end
|
99
119
|
end
|
100
120
|
end
|
121
|
+
|
122
|
+
# Set of unique cache paths that are evaluted during the run
|
123
|
+
def cache_paths
|
124
|
+
@cache_paths ||= Set.new
|
125
|
+
end
|
126
|
+
|
127
|
+
# Set of unique absolute file paths of cached records evaluted during the run
|
128
|
+
def files
|
129
|
+
@files ||= Set.new
|
130
|
+
end
|
101
131
|
end
|
102
132
|
end
|
103
133
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Licensed
|
3
|
+
module Commands
|
4
|
+
class Notices < Command
|
5
|
+
# Create a reporter to use during a command run
|
6
|
+
#
|
7
|
+
# options - The options the command was run with
|
8
|
+
#
|
9
|
+
# Raises a Licensed::Reporters::CacheReporter
|
10
|
+
def create_reporter(options)
|
11
|
+
Licensed::Reporters::NoticesReporter.new
|
12
|
+
end
|
13
|
+
|
14
|
+
protected
|
15
|
+
|
16
|
+
# Load stored dependency record data to add to the notices report.
|
17
|
+
#
|
18
|
+
# app - The application configuration for the dependency
|
19
|
+
# source - The dependency source enumerator for the dependency
|
20
|
+
# dependency - An application dependency
|
21
|
+
# report - A report hash for the command to provide extra data for the report output.
|
22
|
+
#
|
23
|
+
# Returns true.
|
24
|
+
def evaluate_dependency(app, source, dependency, report)
|
25
|
+
filename = app.cache_path.join(source.class.type, "#{dependency.name}.#{DependencyRecord::EXTENSION}")
|
26
|
+
report["cached_record"] = Licensed::DependencyRecord.read(filename)
|
27
|
+
if !report["cached_record"]
|
28
|
+
report["warning"] = "expected cached record not found at #{filename}"
|
29
|
+
end
|
30
|
+
|
31
|
+
true
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -108,7 +108,12 @@ module Licensed
|
|
108
108
|
def detect_cache_path(options, inherited_options)
|
109
109
|
return options["cache_path"] unless options["cache_path"].to_s.empty?
|
110
110
|
|
111
|
-
|
111
|
+
# if cache_path and shared_cache are both set in inherited_options,
|
112
|
+
# don't append the app name to the cache path
|
113
|
+
cache_path = inherited_options["cache_path"]
|
114
|
+
return cache_path if cache_path && inherited_options["shared_cache"] == true
|
115
|
+
|
116
|
+
cache_path ||= DEFAULT_CACHE_PATH
|
112
117
|
File.join(cache_path, self["name"])
|
113
118
|
end
|
114
119
|
|
@@ -167,7 +172,12 @@ module Licensed
|
|
167
172
|
# will handle configurations that don't have these explicitly set
|
168
173
|
dir_name = File.basename(path)
|
169
174
|
config["name"] = "#{config["name"]}-#{dir_name}" if config["name"]
|
170
|
-
|
175
|
+
|
176
|
+
# if a cache_path is set and is not marked as shared, append the app name
|
177
|
+
# to the end of the cache path to make a unique cache path for the app
|
178
|
+
if config["cache_path"] && config["shared_cache"] != true
|
179
|
+
config["cache_path"] = File.join(config["cache_path"], dir_name)
|
180
|
+
end
|
171
181
|
|
172
182
|
config
|
173
183
|
end
|
data/lib/licensed/dependency.rb
CHANGED
@@ -74,7 +74,7 @@ module Licensed
|
|
74
74
|
def license_contents
|
75
75
|
files = matched_files.reject { |f| f == package_file }
|
76
76
|
.group_by(&:content)
|
77
|
-
.map { |content,
|
77
|
+
.map { |content, sources| { "sources" => license_content_sources(sources), "text" => content } }
|
78
78
|
|
79
79
|
files << generated_license_contents if files.empty?
|
80
80
|
files.compact
|
data/lib/licensed/reporters.rb
CHANGED
@@ -27,32 +27,32 @@ module Licensed
|
|
27
27
|
shell.info " #{source.class.type}"
|
28
28
|
result = yield report
|
29
29
|
|
30
|
-
warning_reports = report.all_reports.select { |
|
30
|
+
warning_reports = report.all_reports.select { |r| r.warnings.any? }.to_a
|
31
31
|
if warning_reports.any?
|
32
32
|
shell.newline
|
33
33
|
shell.warn " * Warnings:"
|
34
|
-
warning_reports.each do |
|
35
|
-
display_metadata =
|
34
|
+
warning_reports.each do |r|
|
35
|
+
display_metadata = r.map { |k, v| "#{k}: #{v}" }.join(", ")
|
36
36
|
|
37
|
-
shell.warn " * #{
|
37
|
+
shell.warn " * #{r.name}"
|
38
38
|
shell.warn " #{display_metadata}" unless display_metadata.empty?
|
39
|
-
|
39
|
+
r.warnings.each do |warning|
|
40
40
|
shell.warn " - #{warning}"
|
41
41
|
end
|
42
42
|
shell.newline
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
errored_reports = report.all_reports.select { |
|
46
|
+
errored_reports = report.all_reports.select { |r| r.errors.any? }.to_a
|
47
47
|
if errored_reports.any?
|
48
48
|
shell.newline
|
49
49
|
shell.error " * Errors:"
|
50
|
-
errored_reports.each do |
|
51
|
-
display_metadata =
|
50
|
+
errored_reports.each do |r|
|
51
|
+
display_metadata = r.map { |k, v| "#{k}: #{v}" }.join(", ")
|
52
52
|
|
53
|
-
shell.error " * #{
|
53
|
+
shell.error " * #{r.name}"
|
54
54
|
shell.error " #{display_metadata}" unless display_metadata.empty?
|
55
|
-
|
55
|
+
r.errors.each do |error|
|
56
56
|
shell.error " - #{error}"
|
57
57
|
end
|
58
58
|
shell.newline
|
@@ -28,16 +28,16 @@ module Licensed
|
|
28
28
|
shell.info " #{source.class.type}"
|
29
29
|
result = yield report
|
30
30
|
|
31
|
-
errored_reports = report.all_reports.select { |
|
31
|
+
errored_reports = report.all_reports.select { |r| r.errors.any? }.to_a
|
32
32
|
if errored_reports.any?
|
33
33
|
shell.newline
|
34
34
|
shell.error " * Errors:"
|
35
|
-
errored_reports.each do |
|
36
|
-
display_metadata =
|
35
|
+
errored_reports.each do |r|
|
36
|
+
display_metadata = r.map { |k, v| "#{k}: #{v}" }.join(", ")
|
37
37
|
|
38
|
-
shell.error " * #{
|
38
|
+
shell.error " * #{r.name}"
|
39
39
|
shell.error " #{display_metadata}" unless display_metadata.empty?
|
40
|
-
|
40
|
+
r.errors.each do |error|
|
41
41
|
shell.error " - #{error}"
|
42
42
|
end
|
43
43
|
shell.newline
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Licensed
|
4
|
+
module Reporters
|
5
|
+
class NoticesReporter < Reporter
|
6
|
+
TEXT_SEPARATOR = "\n\n#{("-" * 5)}\n\n".freeze
|
7
|
+
LICENSE_SEPARATOR = "\n#{("*" * 5)}\n".freeze
|
8
|
+
|
9
|
+
# Reports on an application configuration in a notices command run
|
10
|
+
#
|
11
|
+
# app - An application configuration
|
12
|
+
#
|
13
|
+
# Returns the result of the yielded method
|
14
|
+
# Note - must be called from inside the `report_run` scope
|
15
|
+
def report_app(app)
|
16
|
+
super do |report|
|
17
|
+
filename = app["shared_cache"] ? "NOTICE.#{app["name"]}" : "NOTICE"
|
18
|
+
path = app.cache_path.join(filename)
|
19
|
+
shell.info "Writing notices for #{app["name"]} to #{path}"
|
20
|
+
|
21
|
+
result = yield report
|
22
|
+
|
23
|
+
File.open(path, "w") do |file|
|
24
|
+
file << "THIRD PARTY NOTICES\n"
|
25
|
+
file << LICENSE_SEPARATOR
|
26
|
+
file << report.all_reports
|
27
|
+
.map { |r| notices(r) }
|
28
|
+
.compact
|
29
|
+
.join(LICENSE_SEPARATOR)
|
30
|
+
end
|
31
|
+
|
32
|
+
result
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Reports on a dependency in a notices command run.
|
37
|
+
#
|
38
|
+
# dependency - An application dependency
|
39
|
+
#
|
40
|
+
# Returns the result of the yielded method
|
41
|
+
# Note - must be called from inside the `report_run` scope
|
42
|
+
def report_dependency(dependency)
|
43
|
+
super do |report|
|
44
|
+
result = yield report
|
45
|
+
shell.warn "* #{report["warning"]}" if report["warning"]
|
46
|
+
result
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns notices information for a dependency report
|
51
|
+
def notices(report)
|
52
|
+
return unless report.target.is_a?(Licensed::Dependency)
|
53
|
+
|
54
|
+
cached_record = report["cached_record"]
|
55
|
+
return unless cached_record
|
56
|
+
|
57
|
+
texts = cached_record.licenses.map(&:text)
|
58
|
+
cached_record.notices.each do |notice|
|
59
|
+
case notice
|
60
|
+
when Hash
|
61
|
+
texts << notice["text"]
|
62
|
+
when String
|
63
|
+
texts << notice
|
64
|
+
else
|
65
|
+
shell.warn "* unable to parse notices for #{report.target.name}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
<<~NOTICE
|
70
|
+
#{cached_record["name"]}@#{cached_record["version"]}
|
71
|
+
|
72
|
+
#{texts.map(&:strip).reject(&:empty?).compact.join(TEXT_SEPARATOR)}
|
73
|
+
NOTICE
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|