licensed 2.14.3 → 3.0.0

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.
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/match_platform"
4
+
5
+ # Bundler normally raises a "GemNotFound" error when a specification
6
+ # can't be materialized which halts bundler dependency enumeration.
7
+
8
+ # This monkey patch instead creates MissingSpecification objects to
9
+ # identify missing specs without raising errors and halting enumeration.
10
+ # It was the most minimal-touch solution I could think of that should reliably
11
+ # work across many bundler versions
12
+
13
+ module Licensed
14
+ module Bundler
15
+ class MissingSpecification < Gem::BasicSpecification
16
+ include ::Bundler::MatchPlatform
17
+
18
+ attr_reader :name, :version, :platform, :source
19
+ def initialize(name:, version:, platform:, source:)
20
+ @name = name
21
+ @version = version
22
+ @platform = platform
23
+ @source = source
24
+ end
25
+
26
+ def dependencies
27
+ []
28
+ end
29
+
30
+ def gem_dir; end
31
+ def gems_dir
32
+ Gem.dir
33
+ end
34
+ def summary; end
35
+ def homepage; end
36
+
37
+ def error
38
+ "could not find #{name} (#{version}) in any sources"
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ module Bundler
45
+ 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
53
+ end
54
+ end
@@ -222,14 +222,25 @@ module Licensed
222
222
 
223
223
  # Returns a package info structure with an error set
224
224
  def missing_package(id)
225
- name, _, version = if id.index(/\s/).nil?
226
- id.rpartition("-") # e.g. to match the right-most dash from ipid fused-effects-1.0.0.0
227
- else
228
- id.partition(/\s/) # e.g. to match the left-most space from constraint fused-effects > 1.0.0.0
229
- end
230
-
225
+ name, version = package_id_name_version(id)
231
226
  { "name" => name, "version" => version, "error" => "package not found" }
232
227
  end
228
+
229
+ # Parses the name and version pieces from an id or package requirement string
230
+ def package_id_name_version(id)
231
+ name, version = id.split(" ", 2)
232
+ return [name, version] if version
233
+
234
+ # split by dashes, find the rightmost thing that looks like an
235
+ parts = id.split("-")
236
+ version_start_index = parts.rindex { |part| part.match?(/^[\d\.]+$/) }
237
+ return [id, nil] if version_start_index.nil?
238
+
239
+ [
240
+ parts[0...version_start_index].join("-"),
241
+ parts[version_start_index..-1].join("-")
242
+ ]
243
+ end
233
244
  end
234
245
  end
235
246
  end
@@ -170,7 +170,7 @@ module Licensed
170
170
  def all_files
171
171
  # remove files if they are tracked but don't exist on the file system
172
172
  @all_files ||= Set.new(Licensed::Git.files || [])
173
- .delete_if { |f| !File.exist?(f) }
173
+ .delete_if { |f| !File.exist?(File.join(Licensed::Git.repository_root, f)) }
174
174
  end
175
175
 
176
176
  class Dependency < Licensed::Dependency
@@ -4,6 +4,25 @@ require "json"
4
4
  module Licensed
5
5
  module Sources
6
6
  class NPM < Source
7
+ class Dependency < ::Licensed::Dependency
8
+ # override license_metadata to pull homepage and summary information
9
+ # from a packages package.json file, if it exists
10
+ # this accounts for the lack of this information in npm 7's `npm list` output
11
+ def license_metadata
12
+ data = super
13
+ return data if !data["homepage"].to_s.empty? && !data["summary"].to_s.empty?
14
+
15
+ package_json_path = File.join(path, "package.json")
16
+ return data unless File.exist?(package_json_path)
17
+
18
+ package_json = JSON.parse(File.read(package_json_path))
19
+ data["homepage"] = package_json["homepage"]
20
+ data["summary"] = package_json["description"]
21
+
22
+ data
23
+ end
24
+ end
25
+
7
26
  def self.type
8
27
  "npm"
9
28
  end
@@ -50,6 +69,9 @@ module Licensed
50
69
  dependencies.each do |name, dependency|
51
70
  next if dependency["peerMissing"]
52
71
  next if yarn_lock_present && dependency["missing"]
72
+ next if dependency["extraneous"] && dependency["missing"]
73
+
74
+ dependency["name"] = name
53
75
  (result[name] ||= []) << dependency
54
76
  recursive_dependencies(dependency["dependencies"] || {}, result)
55
77
  end
@@ -59,22 +81,50 @@ module Licensed
59
81
  # Returns parsed package metadata returned from `npm list`
60
82
  def package_metadata
61
83
  return @package_metadata if defined?(@package_metadata)
84
+ @package_metadata = JSON.parse(package_metadata_command)
85
+ rescue JSON::ParserError => e
86
+ message = "Licensed was unable to parse the output from 'npm list'. JSON Error: #{e.message}"
87
+ npm_error = package_metadata_error
88
+ message = "#{message}. npm Error: #{npm_error}" if npm_error
89
+ raise Licensed::Sources::Source::Error, message
90
+ end
62
91
 
63
- @package_metadata = begin
64
- JSON.parse(package_metadata_command)
65
- rescue JSON::ParserError => e
66
- raise Licensed::Sources::Source::Error,
67
- "Licensed was unable to parse the output from 'npm list'. Please run 'npm list --json --long' and check for errors. Error: #{e.message}"
68
- end
92
+ # Returns an error, if one exists, from running `npm list` to get package metadata
93
+ def package_metadata_error
94
+ Licensed::Shell.execute("npm", "list", *package_metadata_args)
95
+ return ""
96
+ rescue Licensed::Shell::Error => e
97
+ return e.message
69
98
  end
70
99
 
71
100
  # Returns the output from running `npm list` to get package metadata
72
101
  def package_metadata_command
73
102
  args = %w(--json --long)
74
- args << "--production" unless include_non_production?
103
+ args.concat(package_metadata_args)
104
+
75
105
  Licensed::Shell.execute("npm", "list", *args, allow_failure: true)
76
106
  end
77
107
 
108
+ # Returns an array of arguments that should be used for all `npm list`
109
+ # calls, regardless of how the output is formatted
110
+ def package_metadata_args
111
+ args = []
112
+ args << "--production" unless include_non_production?
113
+
114
+ # on npm 7+, the --all argument is necessary to evaluate the project's
115
+ # full dependency tree
116
+ args << "--all" if npm_version >= Gem::Version.new("7.0.0")
117
+
118
+ return args
119
+ end
120
+
121
+ # Returns the currently installed version of npm as a Gem::Version object
122
+ def npm_version
123
+ @npm_version ||= begin
124
+ Gem::Version.new(Licensed::Shell.execute("npm", "-v").strip)
125
+ end
126
+ end
127
+
78
128
  # Returns true if a yarn.lock file exists in the current directory
79
129
  def yarn_lock_present
80
130
  @yarn_lock_present ||= File.exist?(config.pwd.join("yarn.lock"))
@@ -8,7 +8,7 @@ module Licensed
8
8
  module Sources
9
9
  class Pip < Source
10
10
  VERSION_OPERATORS = %w(< > <= >= == !=).freeze
11
- PACKAGE_REGEX = /^([\w-]+)(#{VERSION_OPERATORS.join("|")})?/
11
+ PACKAGE_REGEX = /^([\w\.-]+)(#{VERSION_OPERATORS.join("|")})?/
12
12
 
13
13
  def enabled?
14
14
  return unless virtual_env_pip && Licensed::Shell.tool_available?(virtual_env_pip)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module Licensed
3
- VERSION = "2.14.3".freeze
3
+ VERSION = "3.0.0".freeze
4
4
 
5
5
  def self.previous_major_versions
6
6
  major_version = Gem::Version.new(Licensed::VERSION).segments.first
@@ -51,8 +51,11 @@ cd $COPY_DIR
51
51
  trap "git checkout $CURRENT_BRANCH" EXIT
52
52
  fi
53
53
 
54
+ # get the openssl dir to use when building based on ruby's default ssl cert dir
55
+ OPENSSL_DIR="$(cd "$(ruby -e 'require "net/https"; puts OpenSSL::X509::DEFAULT_CERT_DIR')/.." && pwd)"
56
+
54
57
  # build the licensed rubyc executable
55
- "$RUBYC" --clean-tmpdir -o "$BUILD_DIR/licensed" "$COPY_DIR/exe/licensed"
58
+ "$RUBYC" --openssl-dir "$OPENSSL_DIR" --clean-tmpdir -o "$BUILD_DIR/licensed" "$COPY_DIR/exe/licensed"
56
59
  chmod +x $BUILD_DIR/licensed
57
60
  )
58
61
 
@@ -34,6 +34,9 @@ build_linux_local() {
34
34
  sudo apt-get update
35
35
  sudo apt-get install -y --no-install-recommends cmake make gcc pkg-config squashfs-tools curl bison git rsync
36
36
 
37
+ sudo gem update --system
38
+ sudo gem update bundler
39
+
37
40
  RUBYC="$BASE_DIR/bin/rubyc-linux"
38
41
  if [ ! -f "$RUBYC" ]; then
39
42
  mkdir -p "$(dirname "$RUBYC")"
@@ -42,6 +45,7 @@ build_linux_local() {
42
45
  fi
43
46
 
44
47
  export CPPFLAGS="-P"
48
+ export SSL_CERT_DIR="/etc/ssl/certs"
45
49
  export RUBYC
46
50
  "$BASE_DIR"/script/packages/build
47
51
  }
data/script/packages/mac CHANGED
@@ -28,6 +28,9 @@ brew update
28
28
  brew list "squashfs" &>/dev/null || brew install "squashfs"
29
29
  brew list "pkg-config" &>/dev/null || brew install "pkg-config"
30
30
 
31
+ gem update --system
32
+ gem update bundler
33
+
31
34
  if [ ! -f "$RUBYC" ]; then
32
35
  mkdir -p "$(dirname "$RUBYC")"
33
36
  curl -L https://github.com/kontena/ruby-packer/releases/download/2.6.0-0.6.0/rubyc-2.6.0-0.6.0-osx-amd64.gz | gunzip > "$RUBYC"
@@ -10,8 +10,25 @@ fi
10
10
  BASE_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
11
11
  cd $BASE_PATH/test/fixtures/npm
12
12
 
13
+ FORCE=""
13
14
  if [ "$1" == "-f" ]; then
14
- find . -not -regex "\.*" -and -not -name "package\.json" -print0 | xargs -0 rm -rf
15
+ FORCE=1
16
+ fi
17
+
18
+ NPM_MAJOR_VERSION="$(npm -v | cut -d'.' -f1)"
19
+ if [ "$NPM_MAJOR_VERSION" -ge "7" ]; then
20
+ PACKAGE_JSON_SRC="package.json.npm7"
21
+ else
22
+ PACKAGE_JSON_SRC="package.json.npm6"
23
+ fi
24
+
25
+ if [ ! -f "package.json" ] || [ "$(cat package.json | md5sum )" != "$(cat "$PACKAGE_JSON_SRC" | md5sum)" ]; then
26
+ FORCE=1
27
+ cp -f "$PACKAGE_JSON_SRC" package.json
28
+ fi
29
+
30
+ if [ -n "$FORCE" ]; then
31
+ find . -not -regex "\.*" -and -not -name "package\.json*" -print0 | xargs -0 rm -rf
15
32
  fi
16
33
 
17
34
  npm install
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.14.3
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-12-13 00:00:00.000000000 Z
11
+ date: 2021-04-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: licensee
@@ -243,7 +243,8 @@ files:
243
243
  - docs/adding_a_new_source.md
244
244
  - docs/commands.md
245
245
  - docs/configuration.md
246
- - docs/migrating_to_newer_versions.md
246
+ - docs/migrations/v2.md
247
+ - docs/migrations/v3.md
247
248
  - docs/packaging.md
248
249
  - docs/reporters.md
249
250
  - docs/sources/bower.md
@@ -290,6 +291,7 @@ files:
290
291
  - lib/licensed/sources.rb
291
292
  - lib/licensed/sources/bower.rb
292
293
  - lib/licensed/sources/bundler.rb
294
+ - lib/licensed/sources/bundler/missing_specification.rb
293
295
  - lib/licensed/sources/cabal.rb
294
296
  - lib/licensed/sources/composer.rb
295
297
  - lib/licensed/sources/dep.rb
@@ -348,7 +350,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
348
350
  - !ruby/object:Gem::Version
349
351
  version: '0'
350
352
  requirements: []
351
- rubygems_version: 3.0.3
353
+ rubygems_version: 3.0.3.1
352
354
  signing_key:
353
355
  specification_version: 4
354
356
  summary: Extract and validate the licenses of dependencies.