licensed 3.2.1 → 3.3.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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -1
  3. data/docs/sources/cargo.md +19 -0
  4. data/lib/licensed/commands/cache.rb +4 -2
  5. data/lib/licensed/commands/command.rb +5 -2
  6. data/lib/licensed/sources/bundler/missing_specification.rb +10 -7
  7. data/lib/licensed/sources/bundler.rb +6 -2
  8. data/lib/licensed/sources/cargo.rb +70 -0
  9. data/lib/licensed/sources/manifest.rb +17 -22
  10. data/lib/licensed/sources/npm.rb +17 -3
  11. data/lib/licensed/sources.rb +1 -0
  12. data/lib/licensed/version.rb +1 -1
  13. data/licensed.gemspec +1 -1
  14. metadata +4 -32
  15. data/.github/dependabot.yml +0 -19
  16. data/.github/workflows/release.yml +0 -213
  17. data/.github/workflows/test.yml +0 -528
  18. data/.gitignore +0 -57
  19. data/.licensed.yml +0 -7
  20. data/.rubocop.yml +0 -8
  21. data/.ruby-version +0 -1
  22. data/docker/Dockerfile.build-linux +0 -15
  23. data/script/bootstrap +0 -6
  24. data/script/cibuild +0 -7
  25. data/script/console +0 -15
  26. data/script/package +0 -20
  27. data/script/packages/build +0 -95
  28. data/script/packages/linux +0 -57
  29. data/script/packages/mac +0 -41
  30. data/script/setup +0 -5
  31. data/script/source-setup/bower +0 -17
  32. data/script/source-setup/bundler +0 -20
  33. data/script/source-setup/cabal +0 -19
  34. data/script/source-setup/composer +0 -38
  35. data/script/source-setup/git_submodule +0 -39
  36. data/script/source-setup/go +0 -31
  37. data/script/source-setup/mix +0 -19
  38. data/script/source-setup/npm +0 -34
  39. data/script/source-setup/nuget +0 -17
  40. data/script/source-setup/pip +0 -29
  41. data/script/source-setup/pipenv +0 -21
  42. data/script/source-setup/swift +0 -22
  43. data/script/source-setup/yarn +0 -17
  44. data/script/test +0 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 157405d5c26fe8026b4c8d521a5753be821bb2727d9713f7732e2601699660e7
4
- data.tar.gz: 1f02c3bf319500352632331f72dfc40cbfaf6a0d00350570223d3b37b2496ca7
3
+ metadata.gz: 204627468559ebbf7283c41b74374a244f5aed5c885c4b9dcfc6fe59a8443c4a
4
+ data.tar.gz: f6db3198bf7bd592e8e1512803e408091dfe6230984c9aa166bbdf7d16edb1df
5
5
  SHA512:
6
- metadata.gz: fa9b3832cfda8a30f99c7718a6e4c9433145e37cb51070c5e1a59009ff5b29269353ddeb68480196bd1f1680bd8c01c4ddd3538bea2f7401fcddcdb542f62ada
7
- data.tar.gz: ee5718fb34a1d23738849101b121db785fdc83d587d0f7750c2cc1e613f0c8a6ece707e427bb18473f04ef67569499db28e75ce80f14f0dde2cd09e18ed14053
6
+ metadata.gz: 5669804505cd5277a292eb51b6d46beda9f9a16e9ede968855ab9df95cdd45bd43564c15fdc45e80a9fe109c190584b93078f45588de78c689f0a93c86278bec
7
+ data.tar.gz: 7c57aa1d0a8bbe39860464a5efcec2d72bf06bd61b6b018c3b856547e7e0a6900e3dba4a440a41fed211b71b368a300d453a811f6fd11b65d82aa612bb7b203a
data/CHANGELOG.md CHANGED
@@ -6,6 +6,47 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## 3.3.1
10
+
11
+ 2021-10-07
12
+
13
+ ### Fixed
14
+
15
+ - Fix evaluation of peer dependencies with npm 7 (:tada: @manuelpuyol https://github.com/github/licensed/pull/411)
16
+
17
+ ### Changed
18
+
19
+ - Manifest source evaluation performance improvements (https://github.com/github/licensed/pull/407)
20
+
21
+ ## 3.3.0
22
+
23
+ 2021-09-18
24
+
25
+ ### Added
26
+
27
+ - New cargo source enumerates rust dependencies (https://github.com/github/licensed/pull/404)
28
+
29
+ ### Changed
30
+
31
+ - Removed non-functional files from gem builds (https://github.com/github/licensed/pull/405)
32
+
33
+ ## 3.2.3
34
+
35
+ 2021-09-14
36
+
37
+ ### Fixed
38
+
39
+ - Bundler source will no longer infinitely recurse when enumerating specifications (https://github.com/github/licensed/pull/402)
40
+ - Using the `--sources` command line option will no longer delete skipped sources' cached files (https://github.com/github/licensed/pull/401)
41
+
42
+ ## 3.2.2
43
+
44
+ 2021-09-09
45
+
46
+ ### Fixed
47
+
48
+ - Bundler source works properly again when used outside of `bundle exec` (https://github.com/github/licensed/pull/397)
49
+
9
50
  ## 3.2.1
10
51
 
11
52
  2021-09-06
@@ -480,4 +521,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
480
521
 
481
522
  Initial release :tada:
482
523
 
483
- [Unreleased]: https://github.com/github/licensed/compare/3.2.1...HEAD
524
+ [Unreleased]: https://github.com/github/licensed/compare/3.3.1...HEAD
@@ -0,0 +1,19 @@
1
+ # Cargo
2
+
3
+ The cargo source will detect dependencies when `Cargo.toml` is found at an apps `source_path`. The source uses the `cargo metadata` CLI and reports on all dependencies that are listed in the output in `resolve.nodes`, excluding packages that are listed in `workspace_members`.
4
+
5
+ ## Metadata CLI options
6
+
7
+ Licensed by default runs `cargo metadata --format-version=1`. You can specify additional CLI options by specifying them in your licensed configuration file under `cargo.metadata_options`. The configuration can be set as a string, or as an array of strings for multiple options.
8
+
9
+ ```yml
10
+ cargo:
11
+ metadata_options: '--all-features'
12
+ ```
13
+
14
+ ```yml
15
+ cargo:
16
+ metadata_options:
17
+ - '--all-features'
18
+ - '--filter-platform x86_64-pc-windows-msvc'
19
+ ```
@@ -39,11 +39,13 @@ module Licensed
39
39
  #
40
40
  # Returns whether the command succeeded for the dependency source enumerator
41
41
  def run_source(app, source, report)
42
+ result = super
43
+
42
44
  # add the full cache path to the list of cache paths
43
45
  # that should be cleaned up after the command run
44
- cache_paths << app.cache_path.join(source.class.type)
46
+ cache_paths << app.cache_path.join(source.class.type) unless result == :skipped
45
47
 
46
- super
48
+ result
47
49
  end
48
50
 
49
51
  # Cache dependency record data.
@@ -121,13 +121,16 @@ module Licensed
121
121
  # source - A dependency source enumerator
122
122
  # report - A report object for this source
123
123
  #
124
- # Returns whether the command succeeded for the dependency source enumerator
124
+ # Returns whether the command succeeded, failed, or was skipped for the dependency source enumerator
125
125
  def run_source(app, source, report)
126
126
  reporter.begin_report_source(source, report)
127
127
 
128
128
  if !sources_overrides.empty? && !sources_overrides.include?(source.class.type)
129
129
  report.warnings << "skipped source"
130
- return true
130
+
131
+ # return a symbol to speficy the source was skipped.
132
+ # This is truthy and will result in the source being considered successful
133
+ return :skipped
131
134
  end
132
135
 
133
136
  dependencies = source.dependencies.sort_by { |dependency| dependency.name }
@@ -38,17 +38,20 @@ module Licensed
38
38
  "could not find #{name} (#{version}) in any sources"
39
39
  end
40
40
  end
41
+
42
+ module LazySpecification
43
+ def __materialize__
44
+ spec = super
45
+ return spec if spec
46
+
47
+ Licensed::Bundler::MissingSpecification.new(name: name, version: version, platform: platform, source: source)
48
+ end
49
+ end
41
50
  end
42
51
  end
43
52
 
44
53
  module Bundler
45
54
  class LazySpecification
46
- alias_method :orig_materialize, :__materialize__
47
- def __materialize__
48
- spec = orig_materialize
49
- return spec if spec
50
-
51
- Licensed::Bundler::MissingSpecification.new(name: name, version: version, platform: platform, source: source)
52
- end
55
+ prepend ::Licensed::Bundler::LazySpecification
53
56
  end
54
57
  end
@@ -109,9 +109,11 @@ module Licensed
109
109
 
110
110
  # reset bundler to load from the current app's source path
111
111
  ::Bundler.reset!
112
- ::Bundler.load
113
112
  end
114
113
 
114
+ # ensure the bundler environment is loaded before enumeration
115
+ ::Bundler.load
116
+
115
117
  yield
116
118
  end
117
119
  ensure
@@ -119,8 +121,10 @@ module Licensed
119
121
  # restore bundler configuration
120
122
  ENV.replace(backup)
121
123
  ::Bundler.reset!
122
- ::Bundler.load
123
124
  end
125
+
126
+ # reload the bundler environment after enumeration
127
+ ::Bundler.load
124
128
  end
125
129
 
126
130
  # Returns whether the current licensed execution is running ruby-packer
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module Licensed
6
+ module Sources
7
+ class Cargo < Source
8
+ # Source is enabled when the cargo tool and Cargo.toml manifest file are available
9
+ def enabled?
10
+ return false unless Licensed::Shell.tool_available?("cargo")
11
+ config.pwd.join("Cargo.toml").exist?
12
+ end
13
+
14
+ def enumerate_dependencies
15
+ packages.map do |package|
16
+ Dependency.new(
17
+ name: "#{package["name"]}-#{package["version"]}",
18
+ version: package["version"],
19
+ path: File.dirname(package["manifest_path"]),
20
+ metadata: {
21
+ "name" => package["name"],
22
+ "type" => Cargo.type,
23
+ "summary" => package["description"],
24
+ "homepage" => package["homepage"]
25
+ }
26
+ )
27
+ end
28
+ end
29
+
30
+ # Returns the package data for all dependencies used to build the current package
31
+ def packages
32
+ cargo_metadata_resolved_node_ids.map { |id| cargo_metadata_packages[id] }
33
+ end
34
+
35
+ # Returns the ids of all resolved nodes used to build the current package
36
+ def cargo_metadata_resolved_node_ids
37
+ cargo_metadata.dig("resolve", "nodes")
38
+ .map { |node| node["id"] }
39
+ .reject { |id| cargo_metadata_workspace_members.include?(id) }
40
+
41
+ end
42
+
43
+ # Returns a hash of id => package pairs sourced from the "packages" cargo metadata property
44
+ def cargo_metadata_packages
45
+ @cargo_metadata_packages ||= cargo_metadata["packages"].each_with_object({}) do |package, hsh|
46
+ hsh[package["id"]] = package
47
+ end
48
+ end
49
+
50
+ # Returns a set of the ids of packages in the current workspace
51
+ def cargo_metadata_workspace_members
52
+ @cargo_metadata_workspace_members ||= Set.new(Array(cargo_metadata["workspace_members"]))
53
+ end
54
+
55
+ # Returns parsed JSON metadata returned from the cargo CLI
56
+ def cargo_metadata
57
+ @cargo_metadata ||= JSON.parse(cargo_metadata_command)
58
+ rescue JSON::ParserError => e
59
+ message = "Licensed was unable to parse the output from 'cargo metadata'. JSON Error: #{e.message}"
60
+ raise Licensed::Sources::Source::Error, message
61
+ end
62
+
63
+ # Runs a command to get cargo metadata for the current package
64
+ def cargo_metadata_command
65
+ options = Array(config.dig("cargo", "metadata_options")).flat_map(&:split)
66
+ Licensed::Shell.execute("cargo", "metadata", "--format-version=1", *options)
67
+ end
68
+ end
69
+ end
70
+ end
@@ -61,7 +61,7 @@ module Licensed
61
61
  manifest.each_with_object({}) do |(src, package_name), hsh|
62
62
  next if src.nil? || src.empty?
63
63
  hsh[package_name] ||= []
64
- hsh[package_name] << File.join(config.root, src)
64
+ hsh[package_name] << File.absolute_path(src, config.root)
65
65
  end
66
66
  end
67
67
 
@@ -130,19 +130,17 @@ module Licensed
130
130
  @configured_dependencies ||= begin
131
131
  dependencies = config.dig("manifest", "dependencies")&.dup || {}
132
132
 
133
- dependencies.each do |name, patterns|
133
+ dependencies.each_with_object({}) do |(name, patterns), hsh|
134
134
  # map glob pattern(s) listed for the dependency to a listing
135
135
  # of files that match the patterns and are not excluded
136
- dependencies[name] = files_from_pattern_list(patterns) & included_files
136
+ hsh[name] = files_from_pattern_list(patterns) & included_files
137
137
  end
138
-
139
- dependencies
140
138
  end
141
139
  end
142
140
 
143
141
  # Returns the set of project files that are included in dependency evaluation
144
142
  def included_files
145
- @sources ||= all_files - files_from_pattern_list(config.dig("manifest", "exclude"))
143
+ @included_files ||= tracked_files - files_from_pattern_list(config.dig("manifest", "exclude"))
146
144
  end
147
145
 
148
146
  # Finds and returns all files in the project that match
@@ -151,26 +149,23 @@ module Licensed
151
149
  return Set.new if patterns.nil? || patterns.empty?
152
150
 
153
151
  # evaluate all patterns from the project root
154
- Dir.chdir config.root do
155
- Array(patterns).reduce(Set.new) do |files, pattern|
156
- if pattern.start_with?("!")
157
- # if the pattern is an exclusion, remove all matching files
158
- # from the result
159
- files - Dir.glob(pattern[1..-1], File::FNM_DOTMATCH)
160
- else
161
- # if the pattern is an inclusion, add all matching files
162
- # to the result
163
- files + Dir.glob(pattern, File::FNM_DOTMATCH)
164
- end
152
+ Array(patterns).each_with_object(Set.new) do |pattern, files|
153
+ if pattern.start_with?("!")
154
+ # if the pattern is an exclusion, remove all matching files
155
+ # from the result
156
+ files.subtract(Dir.glob(pattern[1..-1], File::FNM_DOTMATCH, base: config.root))
157
+ else
158
+ # if the pattern is an inclusion, add all matching files
159
+ # to the result
160
+ files.merge(Dir.glob(pattern, File::FNM_DOTMATCH, base: config.root))
165
161
  end
166
162
  end
167
163
  end
168
164
 
169
- # Returns all tracked files in the project
170
- def all_files
171
- # remove files if they are tracked but don't exist on the file system
172
- @all_files ||= Set.new(Licensed::Git.files || [])
173
- .delete_if { |f| !File.exist?(File.join(Licensed::Git.repository_root, f)) }
165
+ # Returns all tracked files in the project as the intersection of what git tracks and the files in the project
166
+ def tracked_files
167
+ @tracked_files ||= Set.new(Array(Licensed::Git.files)) &
168
+ Set.new(Dir.glob("**/*", File::FNM_DOTMATCH, base: config.root))
174
169
  end
175
170
 
176
171
  class Dependency < Licensed::Dependency
@@ -66,15 +66,17 @@ module Licensed
66
66
 
67
67
  # Recursively parse dependency JSON data. Returns a hash mapping the
68
68
  # package name to it's metadata
69
- def recursive_dependencies(dependencies, result = {})
69
+ def recursive_dependencies(dependencies, result = {}, parent = nil)
70
70
  dependencies.each do |name, dependency|
71
- next if dependency["peerMissing"]
71
+ next if missing_peer?(parent, dependency, name)
72
72
  next if yarn_lock_present && dependency["missing"]
73
73
  next if dependency["extraneous"] && dependency["missing"]
74
74
 
75
75
  dependency["name"] = name
76
+ dependency["version"] ||= extract_version(parent, name) if dependency["missing"]
77
+
76
78
  (result[name] ||= []) << dependency
77
- recursive_dependencies(dependency["dependencies"] || {}, result)
79
+ recursive_dependencies(dependency["dependencies"] || {}, result, dependency)
78
80
  end
79
81
  result
80
82
  end
@@ -135,6 +137,18 @@ module Licensed
135
137
  def include_non_production?
136
138
  config.dig("npm", "production_only") == false
137
139
  end
140
+
141
+ def missing_peer?(parent, dependency, name)
142
+ dependency["peerMissing"] || (dependency["missing"] && peer_dependency(parent, name))
143
+ end
144
+
145
+ def peer_dependency(parent, name)
146
+ parent&.dig("peerDependencies", name)
147
+ end
148
+
149
+ def extract_version(parent, name)
150
+ parent&.dig("_dependencies", name) || peer_dependency(parent, name)
151
+ end
138
152
  end
139
153
  end
140
154
  end
@@ -5,6 +5,7 @@ module Licensed
5
5
  require "licensed/sources/bower"
6
6
  require "licensed/sources/bundler"
7
7
  require "licensed/sources/cabal"
8
+ require "licensed/sources/cargo"
8
9
  require "licensed/sources/composer"
9
10
  require "licensed/sources/dep"
10
11
  require "licensed/sources/git_submodule"
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module Licensed
3
- VERSION = "3.2.1".freeze
3
+ VERSION = "3.3.1".freeze
4
4
 
5
5
  def self.previous_major_versions
6
6
  major_version = Gem::Version.new(Licensed::VERSION).segments.first
data/licensed.gemspec CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
16
16
  spec.homepage = "https://github.com/github/licensed"
17
17
  spec.license = "MIT"
18
18
 
19
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test/|script/|docker/|\..+)}) }
20
20
  spec.bindir = "exe"
21
21
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
22
  spec.require_paths = ["lib"]
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: 3.2.1
4
+ version: 3.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-09-06 00:00:00.000000000 Z
11
+ date: 2021-10-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: licensee
@@ -238,13 +238,6 @@ executables:
238
238
  extensions: []
239
239
  extra_rdoc_files: []
240
240
  files:
241
- - ".github/dependabot.yml"
242
- - ".github/workflows/release.yml"
243
- - ".github/workflows/test.yml"
244
- - ".gitignore"
245
- - ".licensed.yml"
246
- - ".rubocop.yml"
247
- - ".ruby-version"
248
241
  - CHANGELOG.md
249
242
  - CODE_OF_CONDUCT.md
250
243
  - CONTRIBUTING.md
@@ -252,7 +245,6 @@ files:
252
245
  - LICENSE
253
246
  - README.md
254
247
  - Rakefile
255
- - docker/Dockerfile.build-linux
256
248
  - docs/adding_a_new_source.md
257
249
  - docs/commands/README.md
258
250
  - docs/commands/cache.md
@@ -280,6 +272,7 @@ files:
280
272
  - docs/sources/bower.md
281
273
  - docs/sources/bundler.md
282
274
  - docs/sources/cabal.md
275
+ - docs/sources/cargo.md
283
276
  - docs/sources/composer.md
284
277
  - docs/sources/dep.md
285
278
  - docs/sources/git_submodule.md
@@ -326,6 +319,7 @@ files:
326
319
  - lib/licensed/sources/bundler/definition.rb
327
320
  - lib/licensed/sources/bundler/missing_specification.rb
328
321
  - lib/licensed/sources/cabal.rb
322
+ - lib/licensed/sources/cargo.rb
329
323
  - lib/licensed/sources/composer.rb
330
324
  - lib/licensed/sources/dep.rb
331
325
  - lib/licensed/sources/git_submodule.rb
@@ -344,28 +338,6 @@ files:
344
338
  - lib/licensed/ui/shell.rb
345
339
  - lib/licensed/version.rb
346
340
  - licensed.gemspec
347
- - script/bootstrap
348
- - script/cibuild
349
- - script/console
350
- - script/package
351
- - script/packages/build
352
- - script/packages/linux
353
- - script/packages/mac
354
- - script/setup
355
- - script/source-setup/bower
356
- - script/source-setup/bundler
357
- - script/source-setup/cabal
358
- - script/source-setup/composer
359
- - script/source-setup/git_submodule
360
- - script/source-setup/go
361
- - script/source-setup/mix
362
- - script/source-setup/npm
363
- - script/source-setup/nuget
364
- - script/source-setup/pip
365
- - script/source-setup/pipenv
366
- - script/source-setup/swift
367
- - script/source-setup/yarn
368
- - script/test
369
341
  homepage: https://github.com/github/licensed
370
342
  licenses:
371
343
  - MIT
@@ -1,19 +0,0 @@
1
- # To get started with Dependabot version updates, you'll need to specify which
2
- # package ecosystems to update and where the package manifests are located.
3
- # Please see the documentation for all configuration options:
4
- # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5
-
6
- version: 2
7
- updates:
8
- - package-ecosystem: github-actions
9
- directory: /
10
- schedule:
11
- interval: daily
12
- - package-ecosystem: bundler
13
- directory: /
14
- schedule:
15
- interval: weekly
16
- - package-ecosystem: docker
17
- directory: docker
18
- schedule:
19
- interval: weekly