licensed 2.10.0 → 2.12.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8b47685dba77cc47406dfa9aa2dd805c5f4a1746ea547a5b34c39a6d2ec47dcf
4
- data.tar.gz: 0eef1add309449ee2f00a33831d780cf6250990bb74be08077cf786ab28996a2
3
+ metadata.gz: 42da8bbc3e526abe154311e85c5dcb1ffaeba7a631e3b6eab6dbb976a94d9c4d
4
+ data.tar.gz: b0884fb5ae8a8c332c8ea8684075a57e3efe86c6026656279eb2ffe0ae50105a
5
5
  SHA512:
6
- metadata.gz: e01ca0150f1690ade72d0c95743d435af9796269d6b3a51496d39b5e98c186dc0cf78dd824f565c7070dc75e8a85e5af0aad21c8382b92b1578bd09edbe89dd3
7
- data.tar.gz: 0d00ed4c4b0596f96cb2ec77972fe36352bc17a84ee7043b5c3d002db9d9b2f15c9ddf87a2b67ebf36b99eb8dc8b02b4a917e68f9d83d2d42457bb26ee3a5314
6
+ metadata.gz: e5d14b32dffb12a412090348429a116f9732bb6413bc35fb677dbf248e8af415ca531d7980bafeaa5a81ed2f083e798821cd21be7fd8eed1037a6659f24d4693
7
+ data.tar.gz: 411785733af02c33cc0b239980558f79389b8bfdc144bf862530fde111dc3ad0c8fd64040b9fdecba022ae93158287b0f45e26a10719567dda3022024a60728b
@@ -93,7 +93,7 @@ jobs:
93
93
  steps:
94
94
  - uses: actions/checkout@v2
95
95
  - name: Setup php
96
- uses: nanasess/setup-php@v1.0.2
96
+ uses: nanasess/setup-php@v3.0.4
97
97
  with:
98
98
  php-version: ${{ matrix.php }}
99
99
  - name: Set up Ruby
data/.gitignore CHANGED
@@ -45,6 +45,8 @@ test/fixtures/mix/mix.lock
45
45
  test/fixtures/yarn/*
46
46
  !test/fixtures/yarn/package.json
47
47
 
48
+ test/fixtures/nuget/obj/*
49
+
48
50
  vendor/licenses
49
51
  .licenses
50
52
  *.gem
@@ -6,6 +6,44 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## 2.12.2
10
+ 2020-07-07
11
+
12
+ ### Changed
13
+ - Cleaned up ruby 2.7 warnings (:tada: @jurre https://github.com/github/licensed/pull/292)
14
+ - Cleaned up additional warnings in tests (https://github.com/github/licensed/pull/293)
15
+
16
+ ## 2.12.1
17
+ 2020-06-30
18
+
19
+ ### Fixed
20
+ - `licensed` no longer exits an error code when using the `--sources` CLI argument(https://github.com/github/licensed/pull/290)
21
+
22
+ ## 2.12.0
23
+ 2020-06-19
24
+
25
+ ### Added
26
+ - `--sources` argument for cache, list, status and notices commands to filter running sources (https://github.com/github/licensed/pull/287)
27
+
28
+ ### Fixed
29
+ - `cache` command will not remove files outside of enabled source cache paths (https://github.com/github/licensed/pull/287)
30
+
31
+ ## 2.11.1
32
+ 2020-06-09
33
+
34
+ ### Fixed
35
+ - `notices` command properly reads cached dependency notices contents (https://github.com/github/licensed/pull/283)
36
+
37
+ ## 2.11.0
38
+ 2020-06-02
39
+
40
+ ### Added
41
+ - `notices` command to create a `NOTICE` file for each configured app (https://github.com/github/licensed/pull/277)
42
+
43
+ ### Fixed
44
+ - NuGet source no longer crashes on a non-existent dependency path (https://github.com/github/licensed/pull/280)
45
+ - Go source no longer crashes on a non-existent dependency package path (https://github.com/github/licensed/pull/274)
46
+
9
47
  ## 2.10.0
10
48
  2020-05-15
11
49
 
@@ -13,7 +51,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
13
51
  - NPM source ignores missing peer dependencies (https://github.com/github/licensed/pull/267)
14
52
 
15
53
  ### Added
16
- - Nuget source (:tada: @zarenner https://github.com/github/licensed/pull/261)
54
+ - NuGet source (:tada: @zarenner https://github.com/github/licensed/pull/261)
17
55
  - Multiple apps can share a single cache location (https://github.com/github/licensed/pull/263)
18
56
 
19
57
  ## 2.9.2
@@ -302,4 +340,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
302
340
 
303
341
  Initial release :tada:
304
342
 
305
- [Unreleased]: https://github.com/github/licensed/compare/2.10.0...HEAD
343
+ [Unreleased]: https://github.com/github/licensed/compare/2.12.2...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. For example:
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
 
@@ -6,10 +6,14 @@ Run `licensed -h` to see help content for running licensed commands.
6
6
 
7
7
  Running the list command finds the dependencies for all sources in all configured applications. No additional actions are taken on each dependency.
8
8
 
9
+ An optional `--sources` flag can be given to limit which dependency sources are run. This is a filter over sources that are enabled via the licensed configuration file and cannot be used to run licensed with a disabled source.
10
+
9
11
  ## `cache`
10
12
 
11
13
  The cache command finds all dependencies and ensures that each dependency has an up-to-date cached record.
12
14
 
15
+ An optional `--sources` flag can be given to limit which dependency sources are run. This is a filter over sources that are enabled via the licensed configuration file and cannot be used to run licensed with a disabled source.
16
+
13
17
  Dependency records will be saved if:
14
18
  1. The `force` option is set
15
19
  2. No cached record is found
@@ -22,6 +26,8 @@ After the cache command is run, any cached records that don't match up to a curr
22
26
 
23
27
  The status command finds all dependencies and checks whether each dependency has a valid cached record.
24
28
 
29
+ An optional `--sources` flag can be given to limit which dependency sources are run. This is a filter over sources that are enabled via the licensed configuration file and cannot be used to run licensed with a disabled source.
30
+
25
31
  A dependency will fail the status checks if:
26
32
  1. No cached record is found
27
33
  2. The cached record's version is different than the current dependency's version
@@ -31,6 +37,14 @@ A dependency will fail the status checks if:
31
37
  5. The cached record is flagged for re-review.
32
38
  - This occurs when the record's license text has changed since the record was reviewed.
33
39
 
40
+ ## `notices`
41
+
42
+ 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`.
43
+
44
+ An optional `--sources` flag can be given to limit which dependency sources are run. This is a filter over sources that are enabled via the licensed configuration file and cannot be used to run licensed with a disabled source.
45
+
46
+ The `NOTICE` file contents are retrieved from cached records, with the assumption that cached records have already been reviewed in a compliance workflow.
47
+
34
48
  ## `env`
35
49
 
36
50
  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.
@@ -10,22 +10,38 @@ module Licensed
10
10
  desc: "Overwrite licenses even if version has not changed."
11
11
  method_option :config, aliases: "-c", type: :string,
12
12
  desc: "Path to licensed configuration file"
13
+ method_option :sources, aliases: "-s", type: :array,
14
+ desc: "Individual source(s) to evaluate. Must also be enabled via configuration."
13
15
  def cache
14
- run Licensed::Commands::Cache.new(config: config), force: options[:force]
16
+ run Licensed::Commands::Cache.new(config: config),
17
+ force: options[:force], sources: options[:sources]
15
18
  end
16
19
 
17
20
  desc "status", "Check status of dependencies' cached licenses"
18
21
  method_option :config, aliases: "-c", type: :string,
19
22
  desc: "Path to licensed configuration file"
23
+ method_option :sources, aliases: "-s", type: :array,
24
+ desc: "Individual source(s) to evaluate. Must also be enabled via configuration."
20
25
  def status
21
- run Licensed::Commands::Status.new(config: config)
26
+ run Licensed::Commands::Status.new(config: config), sources: options[:sources]
22
27
  end
23
28
 
24
29
  desc "list", "List dependencies"
25
30
  method_option :config, aliases: "-c", type: :string,
26
31
  desc: "Path to licensed configuration file"
32
+ method_option :sources, aliases: "-s", type: :array,
33
+ desc: "Individual source(s) to evaluate. Must also be enabled via configuration."
27
34
  def list
28
- run Licensed::Commands::List.new(config: config)
35
+ run Licensed::Commands::List.new(config: config), sources: options[:sources]
36
+ end
37
+
38
+ desc "notices", "Generate a NOTICE file from cached records"
39
+ method_option :config, aliases: "-c", type: :string,
40
+ desc: "Path to licensed configuration file"
41
+ method_option :sources, aliases: "-s", type: :array,
42
+ desc: "Individual source(s) to evaluate. Must also be enabled via configuration."
43
+ def notices
44
+ run Licensed::Commands::Notices.new(config: config), sources: options[:sources]
29
45
  end
30
46
 
31
47
  map "-v" => :version
@@ -80,7 +96,7 @@ module Licensed
80
96
  end
81
97
 
82
98
  def run(command, **args)
83
- exit command.run(args)
99
+ exit command.run(**args)
84
100
  end
85
101
  end
86
102
  end
@@ -6,5 +6,6 @@ module Licensed
6
6
  require "licensed/commands/status"
7
7
  require "licensed/commands/list"
8
8
  require "licensed/commands/environment"
9
+ require "licensed/commands/notices"
9
10
  end
10
11
  end
@@ -32,19 +32,26 @@ module Licensed
32
32
 
33
33
  protected
34
34
 
35
- # Run the command for all enabled sources for an application configuration,
35
+ # Run the command for all enumerated dependencies found in a dependency source,
36
36
  # recording results in a report.
37
+ # Enumerating dependencies in the source is skipped if a :sources option
38
+ # is provided and the evaluated `source.class.type` is not in the :sources values
37
39
  #
38
- # app - An application configuration
40
+ # app - The application configuration for the source
41
+ # source - A dependency source enumerator
39
42
  #
40
- # Returns whether the command succeeded for the application.
41
- def run_app(app)
42
- result = super
43
-
44
- # add the full cache path to the list of cache paths evaluted during this run
45
- cache_paths << app.cache_path
43
+ # Returns whether the command succeeded for the dependency source enumerator
44
+ def run_source(app, source)
45
+ super do |report|
46
+ if Array(options[:sources]).any? && !options[:sources].include?(source.class.type)
47
+ report.warnings << "skipped source"
48
+ next :skip
49
+ end
46
50
 
47
- result
51
+ # add the full cache path to the list of cache paths
52
+ # that should be cleaned up after the command run
53
+ cache_paths << app.cache_path.join(source.class.type)
54
+ end
48
55
  end
49
56
 
50
57
  # Cache dependency record data.
@@ -21,7 +21,9 @@ module Licensed
21
21
  begin
22
22
  result = reporter.report_run(self) do |report|
23
23
  # allow additional report data to be given by commands
24
- yield report if block_given?
24
+ if block_given?
25
+ next true if (yield report) == :skip
26
+ end
25
27
 
26
28
  config.apps.sort_by { |app| app["name"] }
27
29
  .map { |app| run_app(app) }
@@ -57,7 +59,9 @@ module Licensed
57
59
  Dir.chdir app.source_path do
58
60
  begin
59
61
  # allow additional report data to be given by commands
60
- yield report if block_given?
62
+ if block_given?
63
+ next true if (yield report) == :skip
64
+ end
61
65
 
62
66
  app.sources.select(&:enabled?)
63
67
  .sort_by { |source| source.class.type }
@@ -81,7 +85,9 @@ module Licensed
81
85
  reporter.report_source(source) do |report|
82
86
  begin
83
87
  # allow additional report data to be given by commands
84
- yield report if block_given?
88
+ if block_given?
89
+ next true if (yield report) == :skip
90
+ end
85
91
 
86
92
  source.dependencies.sort_by { |dependency| dependency.name }
87
93
  .map { |dependency| run_dependency(app, source, dependency) }
@@ -114,7 +120,9 @@ module Licensed
114
120
 
115
121
  begin
116
122
  # allow additional report data to be given by commands
117
- yield report if block_given?
123
+ if block_given?
124
+ next true if (yield report) == :skip
125
+ end
118
126
 
119
127
  evaluate_dependency(app, source, dependency, report)
120
128
  rescue Licensed::Shell::Error => err
@@ -13,6 +13,25 @@ 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
+
16
35
  # Listing dependencies requires no extra work.
17
36
  #
18
37
  # app - The application configuration for the dependency
@@ -0,0 +1,54 @@
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
+ # 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
+ # Load stored dependency record data to add to the notices report.
36
+ #
37
+ # app - The application configuration for the dependency
38
+ # source - The dependency source enumerator for the dependency
39
+ # dependency - An application dependency
40
+ # report - A report hash for the command to provide extra data for the report output.
41
+ #
42
+ # Returns true.
43
+ def evaluate_dependency(app, source, dependency, report)
44
+ filename = app.cache_path.join(source.class.type, "#{dependency.name}.#{DependencyRecord::EXTENSION}")
45
+ report["cached_record"] = Licensed::DependencyRecord.read(filename)
46
+ if !report["cached_record"]
47
+ report.warnings << "expected cached record not found at #{filename}"
48
+ end
49
+
50
+ true
51
+ end
52
+ end
53
+ end
54
+ end
@@ -15,6 +15,25 @@ module Licensed
15
15
 
16
16
  protected
17
17
 
18
+ # Run the command for all enumerated dependencies found in a dependency source,
19
+ # recording results in a report.
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
22
+ #
23
+ # app - The application configuration for the source
24
+ # source - A dependency source enumerator
25
+ #
26
+ # Returns whether the command succeeded for the dependency source enumerator
27
+ def run_source(app, source)
28
+ super do |report|
29
+ next if Array(options[:sources]).empty?
30
+ next if options[:sources].include?(source.class.type)
31
+
32
+ report.warnings << "skipped source"
33
+ :skip
34
+ end
35
+ end
36
+
18
37
  # Verifies that a cached record exists, is up to date and
19
38
  # has license data that complies with the licensed configuration.
20
39
  #
@@ -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, files| { "sources" => license_content_sources(files), "text" => 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
@@ -7,5 +7,6 @@ module Licensed
7
7
  require "licensed/reporters/list_reporter"
8
8
  require "licensed/reporters/json_reporter"
9
9
  require "licensed/reporters/yaml_reporter"
10
+ require "licensed/reporters/notices_reporter"
10
11
  end
11
12
  end
@@ -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 { |report| report.warnings.any? }.to_a
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 |report|
35
- display_metadata = report.map { |k, v| "#{k}: #{v}" }.join(", ")
34
+ warning_reports.each do |r|
35
+ display_metadata = r.map { |k, v| "#{k}: #{v}" }.join(", ")
36
36
 
37
- shell.warn " * #{report.name}"
37
+ shell.warn " * #{r.name}"
38
38
  shell.warn " #{display_metadata}" unless display_metadata.empty?
39
- report.warnings.each do |warning|
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 { |report| report.errors.any? }.to_a
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 |report|
51
- display_metadata = report.map { |k, v| "#{k}: #{v}" }.join(", ")
50
+ errored_reports.each do |r|
51
+ display_metadata = r.map { |k, v| "#{k}: #{v}" }.join(", ")
52
52
 
53
- shell.error " * #{report.name}"
53
+ shell.error " * #{r.name}"
54
54
  shell.error " #{display_metadata}" unless display_metadata.empty?
55
- report.errors.each do |error|
55
+ r.errors.each do |error|
56
56
  shell.error " - #{error}"
57
57
  end
58
58
  shell.newline
@@ -28,16 +28,32 @@ module Licensed
28
28
  shell.info " #{source.class.type}"
29
29
  result = yield report
30
30
 
31
- errored_reports = report.all_reports.select { |report| report.errors.any? }.to_a
31
+ warning_reports = report.all_reports.select { |r| r.warnings.any? }.to_a
32
+ if warning_reports.any?
33
+ shell.newline
34
+ shell.warn " * Warnings:"
35
+ warning_reports.each do |r|
36
+ display_metadata = r.map { |k, v| "#{k}: #{v}" }.join(", ")
37
+
38
+ shell.warn " * #{r.name}"
39
+ shell.warn " #{display_metadata}" unless display_metadata.empty?
40
+ r.warnings.each do |warning|
41
+ shell.warn " - #{warning}"
42
+ end
43
+ shell.newline
44
+ end
45
+ end
46
+
47
+ errored_reports = report.all_reports.select { |r| r.errors.any? }.to_a
32
48
  if errored_reports.any?
33
49
  shell.newline
34
50
  shell.error " * Errors:"
35
- errored_reports.each do |report|
36
- display_metadata = report.map { |k, v| "#{k}: #{v}" }.join(", ")
51
+ errored_reports.each do |r|
52
+ display_metadata = r.map { |k, v| "#{k}: #{v}" }.join(", ")
37
53
 
38
- shell.error " * #{report.name}"
54
+ shell.error " * #{r.name}"
39
55
  shell.error " #{display_metadata}" unless display_metadata.empty?
40
- report.errors.each do |error|
56
+ r.errors.each do |error|
41
57
  shell.error " - #{error}"
42
58
  end
43
59
  shell.newline
@@ -0,0 +1,99 @@
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
+
37
+ # Reports on a dependency source enumerator in a notices command run.
38
+ # Shows warnings encountered during the run.
39
+ #
40
+ # source - A dependency source enumerator
41
+ #
42
+ # Returns the result of the yielded method
43
+ # Note - must be called from inside the `report_run` scope
44
+ def report_source(source)
45
+ super do |report|
46
+ result = yield report
47
+
48
+ report.warnings.each do |warning|
49
+ shell.warn "* #{report.name}: #{warning}"
50
+ end
51
+
52
+ result
53
+ end
54
+ end
55
+
56
+ # Reports on a dependency in a notices command run.
57
+ #
58
+ # dependency - An application dependency
59
+ #
60
+ # Returns the result of the yielded method
61
+ # Note - must be called from inside the `report_run` scope
62
+ def report_dependency(dependency)
63
+ super do |report|
64
+ result = yield report
65
+ report.warnings.each do |warning|
66
+ shell.warn "* #{report.name}: #{warning}"
67
+ end
68
+ result
69
+ end
70
+ end
71
+
72
+ # Returns notices information for a dependency report
73
+ def notices(report)
74
+ return unless report.target.is_a?(Licensed::Dependency)
75
+
76
+ cached_record = report["cached_record"]
77
+ return unless cached_record
78
+
79
+ texts = cached_record.licenses.map(&:text)
80
+ cached_record.notices.each do |notice|
81
+ case notice
82
+ when Hash
83
+ texts << notice["text"]
84
+ when String
85
+ texts << notice
86
+ else
87
+ shell.warn "* unable to parse notices for #{report.target.name}"
88
+ end
89
+ end
90
+
91
+ <<~NOTICE
92
+ #{cached_record["name"]}@#{cached_record["version"]}
93
+
94
+ #{texts.map(&:strip).reject(&:empty?).compact.join(TEXT_SEPARATOR)}
95
+ NOTICE
96
+ end
97
+ end
98
+ end
99
+ end
@@ -15,20 +15,37 @@ module Licensed
15
15
  result = yield report
16
16
 
17
17
  all_reports = report.all_reports
18
- errored_reports = all_reports.select { |report| report.errors.any? }.to_a
19
18
 
20
- dependency_count = all_reports.select { |report| report.target.is_a?(Licensed::Dependency) }.size
21
- error_count = errored_reports.sum { |report| report.errors.size }
19
+ warning_reports = all_reports.select { |r| r.warnings.any? }.to_a
20
+ if warning_reports.any?
21
+ shell.newline
22
+ shell.warn "Warnings:"
23
+ warning_reports.each do |r|
24
+ display_metadata = r.map { |k, v| "#{k}: #{v}" }.join(", ")
25
+
26
+ shell.warn "* #{r.name}"
27
+ shell.warn " #{display_metadata}" unless display_metadata.empty?
28
+ r.warnings.each do |warning|
29
+ shell.warn " - #{warning}"
30
+ end
31
+ shell.newline
32
+ end
33
+ end
34
+
35
+ errored_reports = all_reports.select { |r| r.errors.any? }.to_a
36
+
37
+ dependency_count = all_reports.select { |r| r.target.is_a?(Licensed::Dependency) }.size
38
+ error_count = errored_reports.sum { |r| r.errors.size }
22
39
 
23
40
  if error_count > 0
24
41
  shell.newline
25
42
  shell.error "Errors:"
26
- errored_reports.each do |report|
27
- display_metadata = report.map { |k, v| "#{k}: #{v}" }.join(", ")
43
+ errored_reports.each do |r|
44
+ display_metadata = r.map { |k, v| "#{k}: #{v}" }.join(", ")
28
45
 
29
- shell.error "* #{report.name}"
46
+ shell.error "* #{r.name}"
30
47
  shell.error " #{display_metadata}" unless display_metadata.empty?
31
- report.errors.each do |error|
48
+ r.errors.each do |error|
32
49
  shell.error " - #{error}"
33
50
  end
34
51
  shell.newline
@@ -111,11 +111,11 @@ module Licensed
111
111
  info = package_info_command(id).strip
112
112
  return missing_package(id) if info.empty?
113
113
 
114
- info.lines.each_with_object({}) do |line, info|
114
+ info.lines.each_with_object({}) do |line, hsh|
115
115
  key, value = line.split(":", 2).map(&:strip)
116
116
  next unless key && value
117
117
 
118
- info[key] = value
118
+ hsh[key] = value
119
119
  end
120
120
  end
121
121
 
@@ -120,7 +120,7 @@ module Licensed
120
120
  return go_mod["Version"] if go_mod
121
121
 
122
122
  package_directory = package["Dir"]
123
- return unless package_directory
123
+ return unless package_directory && File.exist?(package_directory)
124
124
 
125
125
  # find most recent git SHA for a package, or nil if SHA is
126
126
  # not available
@@ -17,10 +17,13 @@ module Licensed
17
17
  PROJECT_URL_REGEX = /<projectUrl>\s*(.*)\s*<\/projectUrl>/ix.freeze
18
18
  PROJECT_DESC_REGEX = /<description>\s*(.*)\s*<\/description>/ix.freeze
19
19
 
20
- def initialize(name:, version:, path:, search_root: nil, metadata: {}, errors: [])
21
- super(name: name, version: version, path: path, search_root: search_root, metadata: metadata, errors: errors)
22
- @metadata["homepage"] = project_url if project_url
23
- @metadata["summary"] = description if description
20
+ # Returns the metadata that represents this dependency. This metadata
21
+ # is written to YAML in the dependencys cached text file
22
+ def license_metadata
23
+ super.tap do |record_metadata|
24
+ record_metadata["homepage"] = project_url if project_url
25
+ record_metadata["summary"] = description if description
26
+ end
24
27
  end
25
28
 
26
29
  def nuspec_path
@@ -29,14 +32,17 @@ module Licensed
29
32
  end
30
33
 
31
34
  def nuspec_contents
32
- return unless nuspec_path
33
- @nuspec_contents ||= File.read(nuspec_path)
35
+ return @nuspec_contents if defined?(@nuspec_contents)
36
+ @nuspec_contents = begin
37
+ return unless nuspec_path && File.exist?(nuspec_path)
38
+ File.read(nuspec_path)
39
+ end
34
40
  end
35
41
 
36
42
  def project_url
37
43
  return @project_url if defined?(@project_url)
38
- return unless nuspec_contents
39
44
  @project_url = begin
45
+ return unless nuspec_contents
40
46
  match = nuspec_contents.match PROJECT_URL_REGEX
41
47
  match[1] if match && match[1]
42
48
  end
@@ -44,8 +50,8 @@ module Licensed
44
50
 
45
51
  def description
46
52
  return @description if defined?(@description)
47
- return unless nuspec_contents
48
53
  @description = begin
54
+ return unless nuspec_contents
49
55
  match = nuspec_contents.match PROJECT_DESC_REGEX
50
56
  match[1] if match && match[1]
51
57
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module Licensed
3
- VERSION = "2.10.0".freeze
3
+ VERSION = "2.12.2".freeze
4
4
 
5
5
  def self.previous_major_versions
6
6
  major_version = Gem::Version.new(Licensed::VERSION).segments.first
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: licensed
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.10.0
4
+ version: 2.12.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-15 00:00:00.000000000 Z
11
+ date: 2020-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: licensee
@@ -284,6 +284,7 @@ files:
284
284
  - lib/licensed/commands/command.rb
285
285
  - lib/licensed/commands/environment.rb
286
286
  - lib/licensed/commands/list.rb
287
+ - lib/licensed/commands/notices.rb
287
288
  - lib/licensed/commands/status.rb
288
289
  - lib/licensed/configuration.rb
289
290
  - lib/licensed/dependency.rb
@@ -295,6 +296,7 @@ files:
295
296
  - lib/licensed/reporters/cache_reporter.rb
296
297
  - lib/licensed/reporters/json_reporter.rb
297
298
  - lib/licensed/reporters/list_reporter.rb
299
+ - lib/licensed/reporters/notices_reporter.rb
298
300
  - lib/licensed/reporters/reporter.rb
299
301
  - lib/licensed/reporters/status_reporter.rb
300
302
  - lib/licensed/reporters/yaml_reporter.rb