licensed 2.14.3 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.