dependabot-npm_and_yarn 0.286.0 → 0.288.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9a5e7554647eeb278bd1afac30d758d969939c6548c8d071dca5d4b24a02bdfd
4
- data.tar.gz: 5f5014b3963b987df9470defc260a8e0301e81f471c7587acf1908dbf400da2f
3
+ metadata.gz: ef19e7ca0938baa0bee66d3db0500574f6d3b42b181fef8fe38d36396587a2f4
4
+ data.tar.gz: 4905508434d0e5ac9ef7cbe1b71dcc10d466c5932291b8c9abb4473d53d854b1
5
5
  SHA512:
6
- metadata.gz: 6d56917a3c901afaea501c59b134d0b7d3fb5d1f1200a27e57a83b26d86408ac6ae6a73ca840b6172f50b633c2b5068990ef2a9dd888db5bcf0c23e8f427445e
7
- data.tar.gz: e56c6bc29204d912ec122f441ac52603542a5ef91a828f6a899acc569b8cb081112bdcf148cff9c2b6ff288655458f60c38b0c71f7f0aefcaf4684c69183efc4
6
+ metadata.gz: 9981d5b93d3b36479e9500d54fcfcc2d0de8aed94ac5d382a84b7189d570277348e5d421e77f0fc8fee9d20c18511352a60ce855cdc95c178e74ff94640fc175
7
+ data.tar.gz: c8015a50c6732baf3435b7be9ebef4393f312c20d154bf15c516bcad80f8dc39d1fd093c09df6aeb70a59feabe02385dcf9ae15e4b46f3eb6a61916736f04f6a
@@ -1,9 +1,10 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "dependabot/dependency"
5
5
  require "dependabot/file_parsers"
6
6
  require "dependabot/file_parsers/base"
7
+ require "dependabot/shared_helpers"
7
8
  require "sorbet-runtime"
8
9
 
9
10
  module Dependabot
@@ -110,9 +111,14 @@ module Dependabot
110
111
  def self.pnpm_version_numeric(pnpm_lock)
111
112
  lockfile_content = pnpm_lock&.content
112
113
 
113
- return PNPM_DEFAULT_VERSION if lockfile_content.nil? || lockfile_content.strip.empty?
114
+ return PNPM_DEFAULT_VERSION if !lockfile_content || lockfile_content.strip.empty?
115
+
116
+ pnpm_lockfile_version_str = pnpm_lockfile_version(pnpm_lock)
117
+
118
+ return PNPM_FALLBACK_VERSION unless pnpm_lockfile_version_str
119
+
120
+ pnpm_lockfile_version = pnpm_lockfile_version_str.to_f
114
121
 
115
- pnpm_lockfile_version = pnpm_lockfile_version(pnpm_lock).to_f
116
122
  return PNPM_V9 if pnpm_lockfile_version >= 9.0
117
123
  return PNPM_V8 if pnpm_lockfile_version >= 6.0
118
124
  return PNPM_V7 if pnpm_lockfile_version >= 5.4
@@ -120,6 +126,7 @@ module Dependabot
120
126
  PNPM_FALLBACK_VERSION
121
127
  end
122
128
 
129
+ sig { params(key: String, default_value: String).returns(T.untyped) }
123
130
  def self.fetch_yarnrc_yml_value(key, default_value)
124
131
  if File.exist?(".yarnrc.yml") && (yarnrc = YAML.load_file(".yarnrc.yml"))
125
132
  yarnrc.fetch(key, default_value)
@@ -145,7 +152,7 @@ module Dependabot
145
152
  false
146
153
  end
147
154
 
148
- sig { returns(Integer) }
155
+ sig { returns(T.any(Integer, T.noreturn)) }
149
156
  def self.yarn_major_version
150
157
  retries = 0
151
158
  output = run_single_yarn_command("--version")
@@ -171,6 +178,7 @@ module Dependabot
171
178
  handle_subprocess_failure(e)
172
179
  end
173
180
 
181
+ sig { params(error: StandardError).returns(T.noreturn) }
174
182
  def self.handle_subprocess_failure(error)
175
183
  message = error.message
176
184
  if YARN_PATH_NOT_FOUND.match?(message)
@@ -224,6 +232,7 @@ module Dependabot
224
232
  yarn_major_version >= 4
225
233
  end
226
234
 
235
+ sig { returns(T.nilable(String)) }
227
236
  def self.setup_yarn_berry
228
237
  # Always disable immutable installs so yarn's CI detection doesn't prevent updates.
229
238
  run_single_yarn_command("config set enableImmutableInstalls false")
@@ -250,9 +259,12 @@ module Dependabot
250
259
  # set to false. Yarn commands should _not_ be ran outside of this helper
251
260
  # to ensure that postinstall scripts are never executed, as they could
252
261
  # contain malicious code.
262
+ sig { params(commands: T::Array[String]).void }
253
263
  def self.run_yarn_commands(*commands)
254
264
  setup_yarn_berry
255
- commands.each { |cmd, fingerprint| run_single_yarn_command(cmd, fingerprint: fingerprint) }
265
+ commands.each do |cmd, fingerprint|
266
+ run_single_yarn_command(cmd, fingerprint: fingerprint) if cmd
267
+ end
256
268
  end
257
269
 
258
270
  # Run single npm command returning stdout/stderr.
@@ -260,29 +272,112 @@ module Dependabot
260
272
  # NOTE: Needs to be explicitly run through corepack to respect the
261
273
  # `packageManager` setting in `package.json`, because corepack does not
262
274
  # add shims for NPM.
275
+ sig { params(command: String, fingerprint: T.nilable(String)).returns(String) }
263
276
  def self.run_npm_command(command, fingerprint: command)
264
- SharedHelpers.run_shell_command("corepack npm #{command}", fingerprint: "corepack npm #{fingerprint}")
277
+ if Dependabot::Experiments.enabled?(:enable_corepack_for_npm_and_yarn)
278
+ package_manager_run_command(NpmPackageManager::NAME, command, fingerprint: fingerprint)
279
+ else
280
+ Dependabot::SharedHelpers.run_shell_command(
281
+ "corepack npm #{command}",
282
+ fingerprint: "corepack npm #{fingerprint}"
283
+ )
284
+ end
265
285
  end
266
286
 
267
287
  # Setup yarn and run a single yarn command returning stdout/stderr
288
+ sig { params(command: String, fingerprint: T.nilable(String)).returns(String) }
268
289
  def self.run_yarn_command(command, fingerprint: nil)
269
290
  setup_yarn_berry
270
291
  run_single_yarn_command(command, fingerprint: fingerprint)
271
292
  end
272
293
 
273
294
  # Run single pnpm command returning stdout/stderr
295
+ sig { params(command: String, fingerprint: T.nilable(String)).returns(String) }
274
296
  def self.run_pnpm_command(command, fingerprint: nil)
275
- SharedHelpers.run_shell_command("pnpm #{command}", fingerprint: "pnpm #{fingerprint || command}")
297
+ if Dependabot::Experiments.enabled?(:enable_corepack_for_npm_and_yarn)
298
+ package_manager_run_command(PNPMPackageManager::NAME, command, fingerprint: fingerprint)
299
+ else
300
+ Dependabot::SharedHelpers.run_shell_command(
301
+ "pnpm #{command}",
302
+ fingerprint: "pnpm #{fingerprint || command}"
303
+ )
304
+ end
276
305
  end
277
306
 
278
307
  # Run single yarn command returning stdout/stderr
308
+ sig { params(command: String, fingerprint: T.nilable(String)).returns(String) }
279
309
  def self.run_single_yarn_command(command, fingerprint: nil)
280
- SharedHelpers.run_shell_command("yarn #{command}", fingerprint: "yarn #{fingerprint || command}")
310
+ if Dependabot::Experiments.enabled?(:enable_corepack_for_npm_and_yarn)
311
+ package_manager_run_command(YarnPackageManager::NAME, command, fingerprint: fingerprint)
312
+ else
313
+ Dependabot::SharedHelpers.run_shell_command(
314
+ "yarn #{command}",
315
+ fingerprint: "yarn #{fingerprint || command}"
316
+ )
317
+ end
318
+ end
319
+
320
+ # Install the package manager for specified version by using corepack
321
+ # and prepare it for use by using corepack
322
+ sig { params(name: String, version: String).returns(String) }
323
+ def self.install(name, version)
324
+ Dependabot.logger.info("Installing \"#{name}@#{version}\"")
325
+
326
+ package_manager_install(name, version)
327
+ package_manager_activate(name, version)
328
+ installed_version = package_manager_version(name)
329
+
330
+ Dependabot.logger.info("Installed version of #{name}: #{installed_version}")
331
+
332
+ installed_version
333
+ end
334
+
335
+ # Install the package manager for specified version by using corepack
336
+ sig { params(name: String, version: String).void }
337
+ def self.package_manager_install(name, version)
338
+ Dependabot::SharedHelpers.run_shell_command(
339
+ "corepack install #{name}@#{version} --global --cache-only",
340
+ fingerprint: "corepack install <name>@<version> --global --cache-only"
341
+ ).strip
342
+ end
343
+
344
+ # Prepare the package manager for use by using corepack
345
+ sig { params(name: String, version: String).void }
346
+ def self.package_manager_activate(name, version)
347
+ Dependabot::SharedHelpers.run_shell_command(
348
+ "corepack prepare #{name}@#{version} --activate",
349
+ fingerprint: "corepack prepare --activate"
350
+ ).strip
351
+ end
352
+
353
+ # Get the version of the package manager by using corepack
354
+ sig { params(name: String).returns(String) }
355
+ def self.package_manager_version(name)
356
+ package_manager_run_command(name, "-v")
357
+ end
358
+
359
+ # Run single command on package manager returning stdout/stderr
360
+ sig do
361
+ params(
362
+ name: String,
363
+ command: String,
364
+ fingerprint: T.nilable(String)
365
+ ).returns(String)
366
+ end
367
+ def self.package_manager_run_command(name, command, fingerprint: nil)
368
+ Dependabot::SharedHelpers.run_shell_command(
369
+ "corepack #{name} #{command}",
370
+ fingerprint: "corepack #{name} #{fingerprint || command}"
371
+ ).strip
281
372
  end
282
373
  private_class_method :run_single_yarn_command
283
374
 
375
+ sig { params(pnpm_lock: DependencyFile).returns(T.nilable(String)) }
284
376
  def self.pnpm_lockfile_version(pnpm_lock)
285
- pnpm_lock.content.match(/^lockfileVersion: ['"]?(?<version>[\d.]+)/)[:version]
377
+ match = T.must(pnpm_lock.content).match(/^lockfileVersion: ['"]?(?<version>[\d.]+)/)
378
+ return match[:version] if match
379
+
380
+ nil
286
381
  end
287
382
 
288
383
  sig { params(dependency_set: Dependabot::FileParsers::Base::DependencySet).returns(T::Array[Dependency]) }
@@ -1,4 +1,4 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "dependabot/shared_helpers"
@@ -10,6 +10,7 @@ module Dependabot
10
10
  ECOSYSTEM = "npm_and_yarn"
11
11
  MANIFEST_FILENAME = "package.json"
12
12
  LERNA_JSON_FILENAME = "lerna.json"
13
+ PACKAGE_MANAGER_VERSION_REGEX = /^(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)(?:-(?<pre_release>[a-zA-Z0-9.]+))?(?:\+(?<build>[a-zA-Z0-9.]+))?$/ # rubocop:disable Layout/LineLength
13
14
 
14
15
  MANIFEST_PACKAGE_MANAGER_KEY = "packageManager"
15
16
  MANIFEST_ENGINES_KEY = "engines"
@@ -138,11 +139,20 @@ module Dependabot
138
139
 
139
140
  DEFAULT_PACKAGE_MANAGER = NpmPackageManager::NAME
140
141
 
141
- PACKAGE_MANAGER_CLASSES = {
142
+ # Define a type alias for the expected class interface
143
+ NpmAndYarnPackageManagerClassType = T.type_alias do
144
+ T.any(
145
+ T.class_of(Dependabot::NpmAndYarn::NpmPackageManager),
146
+ T.class_of(Dependabot::NpmAndYarn::YarnPackageManager),
147
+ T.class_of(Dependabot::NpmAndYarn::PNPMPackageManager)
148
+ )
149
+ end
150
+
151
+ PACKAGE_MANAGER_CLASSES = T.let({
142
152
  NpmPackageManager::NAME => NpmPackageManager,
143
153
  YarnPackageManager::NAME => YarnPackageManager,
144
154
  PNPMPackageManager::NAME => PNPMPackageManager
145
- }.freeze
155
+ }.freeze, T::Hash[String, NpmAndYarnPackageManagerClassType])
146
156
 
147
157
  class PackageManagerDetector
148
158
  extend T::Sig
@@ -151,14 +161,14 @@ module Dependabot
151
161
  sig do
152
162
  params(
153
163
  lockfiles: T::Hash[Symbol, T.nilable(Dependabot::DependencyFile)],
154
- package_json: T::Hash[String, T.untyped]
164
+ package_json: T.nilable(T::Hash[String, T.untyped])
155
165
  ).void
156
166
  end
157
167
  def initialize(lockfiles, package_json)
158
168
  @lockfiles = lockfiles
159
169
  @package_json = package_json
160
- @manifest_package_manager = package_json["packageManager"]
161
- @engines = package_json.fetch(MANIFEST_ENGINES_KEY, nil)
170
+ @manifest_package_manager = T.let(package_json&.fetch(MANIFEST_PACKAGE_MANAGER_KEY, nil), T.nilable(String))
171
+ @engines = T.let(package_json&.fetch(MANIFEST_ENGINES_KEY, {}), T::Hash[String, T.untyped])
162
172
  end
163
173
 
164
174
  # Returns npm, yarn, or pnpm based on the lockfiles, package.json, and engines
@@ -172,18 +182,15 @@ module Dependabot
172
182
 
173
183
  sig { returns(T.nilable(String)) }
174
184
  def name_from_lockfiles
175
- PACKAGE_MANAGER_CLASSES.each_key do |manager_name| # iterates keys in order as defined in the hash
176
- return manager_name.to_s if @lockfiles[manager_name.to_sym]
177
- end
178
- nil
185
+ PACKAGE_MANAGER_CLASSES.keys.map(&:to_s).find { |manager_name| @lockfiles[manager_name.to_sym] }
179
186
  end
180
187
 
181
188
  sig { returns(T.nilable(String)) }
182
189
  def name_from_package_manager_attr
183
190
  return unless @manifest_package_manager
184
191
 
185
- PACKAGE_MANAGER_CLASSES.each_key do |manager_name| # iterates keys in order as defined in the hash
186
- return manager_name.to_s if @manifest_package_manager.start_with?("#{manager_name}@")
192
+ PACKAGE_MANAGER_CLASSES.keys.map(&:to_s).find do |manager_name|
193
+ @manifest_package_manager.start_with?("#{manager_name}@")
187
194
  end
188
195
  end
189
196
 
@@ -204,16 +211,18 @@ module Dependabot
204
211
 
205
212
  sig do
206
213
  params(
207
- package_json: T::Hash[String, T.untyped],
214
+ package_json: T.nilable(T::Hash[String, T.untyped]),
208
215
  lockfiles: T::Hash[Symbol, T.nilable(Dependabot::DependencyFile)]
209
216
  ).void
210
217
  end
211
218
  def initialize(package_json, lockfiles:)
212
219
  @package_json = package_json
213
220
  @lockfiles = lockfiles
214
- @manifest_package_manager = package_json[MANIFEST_PACKAGE_MANAGER_KEY]
215
- @engines = package_json.fetch(MANIFEST_ENGINES_KEY, nil)
216
- @package_manager_detector = PackageManagerDetector.new(@lockfiles, @package_json)
221
+ @package_manager_detector = T.let(PackageManagerDetector.new(lockfiles, package_json), PackageManagerDetector)
222
+ @manifest_package_manager = T.let(package_json&.fetch(MANIFEST_PACKAGE_MANAGER_KEY, nil), T.nilable(String))
223
+ @engines = T.let(package_json&.fetch(MANIFEST_ENGINES_KEY, nil), T.nilable(T::Hash[String, T.untyped]))
224
+
225
+ @installed_versions = T.let({}, T::Hash[String, String])
217
226
  end
218
227
 
219
228
  sig { returns(Ecosystem::VersionManager) }
@@ -225,6 +234,8 @@ module Dependabot
225
234
 
226
235
  # rubocop:disable Metrics/CyclomaticComplexity
227
236
  # rubocop:disable Metrics/PerceivedComplexity
237
+ # rubocop:disable Metrics/AbcSize
238
+ sig { params(name: String).returns(T.nilable(T.any(Integer, String))) }
228
239
  def setup(name)
229
240
  # we prioritize version mentioned in "packageManager" instead of "engines"
230
241
  # i.e. if { engines : "pnpm" : "6" } and { packageManager: "pnpm@6.0.2" },
@@ -255,42 +266,76 @@ module Dependabot
255
266
  )
256
267
  end
257
268
 
258
- version ||= requested_version(name)
259
-
260
- if version
261
- raise_if_unsupported!(name, version)
269
+ if Dependabot::Experiments.enabled?(:enable_corepack_for_npm_and_yarn)
270
+ version ||= requested_version(name) || guessed_version(name)
262
271
 
263
- install(name, version)
272
+ if version
273
+ raise_if_unsupported!(name, version.to_s)
274
+ install(name, version.to_s)
275
+ end
264
276
  else
265
- version = guessed_version(name)
277
+ version ||= requested_version(name)
266
278
 
267
279
  if version
268
280
  raise_if_unsupported!(name, version.to_s)
269
281
 
270
- install(name, version) if name == PNPMPackageManager::NAME
282
+ install(name, version)
283
+ else
284
+ version = guessed_version(name)
285
+
286
+ if version
287
+ raise_if_unsupported!(name, version.to_s)
288
+
289
+ install(name, version.to_s) if name == PNPMPackageManager::NAME
290
+ end
271
291
  end
272
292
  end
273
-
274
293
  version
275
294
  end
276
- # rubocop:enable Metrics/CyclomaticComplexity
277
- # rubocop:enable Metrics/PerceivedComplexity
278
-
279
- private
280
295
 
281
296
  sig { params(name: T.nilable(String)).returns(Ecosystem::VersionManager) }
282
297
  def package_manager_by_name(name)
283
- name = DEFAULT_PACKAGE_MANAGER if name.nil? || PACKAGE_MANAGER_CLASSES[name].nil?
298
+ name = ensure_valid_package_manager(name)
299
+
300
+ package_manager_class = T.must(PACKAGE_MANAGER_CLASSES[name])
284
301
 
285
- package_manager_class = PACKAGE_MANAGER_CLASSES[name]
302
+ installed_version = installed_version(name)
303
+
304
+ package_manager_class.new(installed_version)
305
+ end
286
306
 
287
- package_manager_class ||= PACKAGE_MANAGER_CLASSES[DEFAULT_PACKAGE_MANAGER]
307
+ # rubocop:enable Metrics/CyclomaticComplexity
308
+ # rubocop:enable Metrics/PerceivedComplexity
309
+ # rubocop:enable Metrics/AbcSize
310
+ # Retrieve the installed version of the package manager by executing
311
+ # the "corepack <name> -v" command and using the output.
312
+ # If the output does not match the expected version format (PACKAGE_MANAGER_VERSION_REGEX),
313
+ # fall back to the version inferred from the dependency files.
314
+ sig { params(name: String).returns(String) }
315
+ def installed_version(name)
316
+ # Return the memoized version if it has already been computed
317
+ return T.must(@installed_versions[name]) if @installed_versions.key?(name)
318
+
319
+ # Attempt to get the installed version through the package manager version command
320
+ @installed_versions[name] = Helpers.package_manager_version(name)
321
+
322
+ # If we can't get the installed version, we need to install the package manager and get the version
323
+ unless @installed_versions[name]&.match?(PACKAGE_MANAGER_VERSION_REGEX)
324
+ setup(name)
325
+ @installed_versions[name] = Helpers.package_manager_version(name)
326
+ end
288
327
 
289
- version = Helpers.send(:"#{name}_version_numeric", @lockfiles[name.to_sym])
328
+ # If we can't get the installed version or the version is invalid, we need to get inferred version
329
+ unless @installed_versions[name]&.match?(PACKAGE_MANAGER_VERSION_REGEX)
330
+ @installed_versions[name] = Helpers.public_send(:"#{name}_version_numeric", @lockfiles[name.to_sym]).to_s
331
+ end
290
332
 
291
- package_manager_class.new(version.to_s)
333
+ T.must(@installed_versions[name])
292
334
  end
293
335
 
336
+ private
337
+
338
+ sig { params(name: String, version: String).void }
294
339
  def raise_if_unsupported!(name, version)
295
340
  return unless name == PNPMPackageManager::NAME
296
341
  return unless Version.new(version) < Version.new("7")
@@ -298,7 +343,12 @@ module Dependabot
298
343
  raise ToolVersionNotSupported.new(PNPMPackageManager::NAME.upcase, version, "7.*, 8.*")
299
344
  end
300
345
 
346
+ sig { params(name: String, version: T.nilable(String)).void }
301
347
  def install(name, version)
348
+ if Dependabot::Experiments.enabled?(:enable_corepack_for_npm_and_yarn)
349
+ return Helpers.install(name, version.to_s)
350
+ end
351
+
302
352
  Dependabot.logger.info("Installing \"#{name}@#{version}\"")
303
353
 
304
354
  SharedHelpers.run_shell_command(
@@ -307,6 +357,13 @@ module Dependabot
307
357
  )
308
358
  end
309
359
 
360
+ sig { params(name: T.nilable(String)).returns(String) }
361
+ def ensure_valid_package_manager(name)
362
+ name = DEFAULT_PACKAGE_MANAGER if name.nil? || PACKAGE_MANAGER_CLASSES[name].nil?
363
+ name
364
+ end
365
+
366
+ sig { params(name: String).returns(T.nilable(String)) }
310
367
  def requested_version(name)
311
368
  return unless @manifest_package_manager
312
369
 
@@ -317,6 +374,7 @@ module Dependabot
317
374
  match["version"]
318
375
  end
319
376
 
377
+ sig { params(name: String).returns(T.nilable(T.any(Integer, String))) }
320
378
  def guessed_version(name)
321
379
  lockfile = @lockfiles[name.to_sym]
322
380
  return unless lockfile
@@ -330,6 +388,8 @@ module Dependabot
330
388
 
331
389
  sig { params(name: T.untyped).returns(T.nilable(String)) }
332
390
  def check_engine_version(name)
391
+ return if @package_json.nil?
392
+
333
393
  version_selector = VersionSelector.new
334
394
  engine_versions = version_selector.setup(@package_json, name)
335
395
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-npm_and_yarn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.286.0
4
+ version: 0.288.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-11-14 00:00:00.000000000 Z
11
+ date: 2024-11-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dependabot-common
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 0.286.0
19
+ version: 0.288.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 0.286.0
26
+ version: 0.288.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: debug
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -346,7 +346,7 @@ licenses:
346
346
  - MIT
347
347
  metadata:
348
348
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
349
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.286.0
349
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.288.0
350
350
  post_install_message:
351
351
  rdoc_options: []
352
352
  require_paths: