dependabot-npm_and_yarn 0.293.0 → 0.294.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: 0d548c0891264c8b407f2b673e39266b3494683e431ac1e8b9ebc899319208f5
4
- data.tar.gz: b43aeb89fb1a1c1e32a9d86eee5ccc188d8fc3da548ee4cbbcfbc4c76cfd59c7
3
+ metadata.gz: 72e338772b3c3aac3cf86538fc2d70dbbc45f5f7cb854cd7fd74913b140fe056
4
+ data.tar.gz: 1856c138b871ebe80e5cc6faa5984ba80c10b342aa8bf0822e325e5a31a3f815
5
5
  SHA512:
6
- metadata.gz: 95eef6390619686a8017fc949e5a5609e34f3675920fea726975fb42c55904e9901ef55b80df005ffa43bf74e87623ed00a9a287005af9446c93b78fcb0c010d
7
- data.tar.gz: 9a104350702acef102f005bdc0c4649b7713288de3685992538f9e58384487802f48a1f1c6e57dd6ac244fb11e849fd89b72f2f3648355eb3115d1174846e21f
6
+ metadata.gz: 0e3267d0aafcf35e345505c87a23b2b783cfc36377e46f5f10875a4bd8b0c4fe201b6dea0dbed75463b75dccba175014af850451cfc52b39c0a2a410a5c5ab34
7
+ data.tar.gz: a1c6be5ccbebcf43a76a51d7871a37743428f052c734a985a48fc90d4b1e2944679a8b6eb17910a8ef7e14c69dbe46d9761319b28d6a57d7dcbac7e94fbb9c09
@@ -97,9 +97,9 @@ async function findVulnerableDependencies(directory, advisories) {
97
97
 
98
98
  for (const group of groupedFixUpdateChains.values()) {
99
99
  const fixUpdateNode = group[0].nodes[0]
100
- const groupTopLevelAncestors = group.reduce((anc, chain) => {
100
+ const groupTopLevelAncestors = group.reduce((ancestor, chain) => {
101
101
  const topLevelNode = chain.nodes[chain.nodes.length - 1]
102
- return anc.add(topLevelNode.name)
102
+ return ancestor.add(topLevelNode.name)
103
103
  }, new Set())
104
104
 
105
105
  // Add group's top-level ancestors to the set of all top-level ancestors of
@@ -269,23 +269,23 @@ const maybeReadFile = file => {
269
269
  }
270
270
 
271
271
  function loadCACerts(npmConfig) {
272
- if (npmConfig.ca) {
273
- return npmConfig.ca
274
- }
272
+ if (npmConfig.ca) {
273
+ return npmConfig.ca
274
+ }
275
275
 
276
- if (!npmConfig.cafile) {
277
- return
278
- }
276
+ if (!npmConfig.cafile) {
277
+ return
278
+ }
279
279
 
280
- const raw = maybeReadFile(npmConfig.cafile)
281
- if (!raw) {
282
- return
283
- }
280
+ const raw = maybeReadFile(npmConfig.cafile)
281
+ if (!raw) {
282
+ return
283
+ }
284
284
 
285
- const delim = '-----END CERTIFICATE-----'
286
- return raw.replace(/\r\n/g, '\n').split(delim)
287
- .filter(section => section.trim())
288
- .map(section => section.trimStart() + delim)
285
+ const delim = '-----END CERTIFICATE-----'
286
+ return raw.replace(/\r\n/g, '\n').split(delim)
287
+ .filter(section => section.trim())
288
+ .map(section => section.trimStart() + delim)
289
289
  }
290
290
 
291
291
  module.exports = { findVulnerableDependencies }
@@ -113,7 +113,7 @@ function flattenAllDependencies(manifest) {
113
113
  );
114
114
  }
115
115
 
116
- // NOTE: Re-used in npm 7 updater
116
+ // NOTE: Reused in npm 7 updater
117
117
  function installArgs(
118
118
  depName,
119
119
  desiredVersion,
@@ -39,7 +39,7 @@ module Dependabot
39
39
 
40
40
  sig { override.returns(T::Boolean) }
41
41
  def unsupported?
42
- supported_versions.all? { |supported| supported > version }
42
+ false
43
43
  end
44
44
  end
45
45
  end
@@ -213,7 +213,7 @@ module Dependabot
213
213
 
214
214
  sig { returns(T.nilable(T.any(Integer, String))) }
215
215
  def bun_version
216
- return @bun_version = nil unless Experiments.enabled?(:bun_updates)
216
+ return @bun_version = nil unless allow_beta_ecosystems?
217
217
 
218
218
  @bun_version ||= T.let(
219
219
  package_manager_helper.setup(BunPackageManager::NAME),
@@ -453,6 +453,15 @@ module Dependabot
453
453
 
454
454
  resolution_deps = resolution_objects.flat_map(&:to_a)
455
455
  .map do |path, value|
456
+ # skip dependencies that contain invalid values such as inline comments, null, etc.
457
+
458
+ unless value.is_a?(String)
459
+ Dependabot.logger.warn("File fetcher: Skipping dependency \"#{path}\" " \
460
+ "with value: \"#{value}\"")
461
+
462
+ next
463
+ end
464
+
456
465
  convert_dependency_path_to_name(path, value)
457
466
  end
458
467
 
@@ -645,8 +654,8 @@ module Dependabot
645
654
  def parsed_pnpm_workspace_yaml
646
655
  return {} unless pnpm_workspace_yaml
647
656
 
648
- YAML.safe_load(T.must(T.must(pnpm_workspace_yaml).content))
649
- rescue Psych::SyntaxError
657
+ YAML.safe_load(T.must(T.must(pnpm_workspace_yaml).content), aliases: true)
658
+ rescue Psych::SyntaxError, Psych::BadAlias
650
659
  raise Dependabot::DependencyFileNotParseable, T.must(pnpm_workspace_yaml).path
651
660
  end
652
661
 
@@ -143,56 +143,56 @@ module Dependabot
143
143
  sig { returns(T.nilable(Dependabot::DependencyFile)) }
144
144
  def shrinkwrap
145
145
  @shrinkwrap ||= T.let(dependency_files.find do |f|
146
- f.name == NpmPackageManager::SHRINKWRAP_LOCKFILE_NAME
146
+ f.name.end_with?(NpmPackageManager::SHRINKWRAP_LOCKFILE_NAME)
147
147
  end, T.nilable(Dependabot::DependencyFile))
148
148
  end
149
149
 
150
150
  sig { returns(T.nilable(Dependabot::DependencyFile)) }
151
151
  def package_lock
152
152
  @package_lock ||= T.let(dependency_files.find do |f|
153
- f.name == NpmPackageManager::LOCKFILE_NAME
153
+ f.name.end_with?(NpmPackageManager::LOCKFILE_NAME)
154
154
  end, T.nilable(Dependabot::DependencyFile))
155
155
  end
156
156
 
157
157
  sig { returns(T.nilable(Dependabot::DependencyFile)) }
158
158
  def yarn_lock
159
159
  @yarn_lock ||= T.let(dependency_files.find do |f|
160
- f.name == YarnPackageManager::LOCKFILE_NAME
160
+ f.name.end_with?(YarnPackageManager::LOCKFILE_NAME)
161
161
  end, T.nilable(Dependabot::DependencyFile))
162
162
  end
163
163
 
164
164
  sig { returns(T.nilable(Dependabot::DependencyFile)) }
165
165
  def pnpm_lock
166
166
  @pnpm_lock ||= T.let(dependency_files.find do |f|
167
- f.name == PNPMPackageManager::LOCKFILE_NAME
167
+ f.name.end_with?(PNPMPackageManager::LOCKFILE_NAME)
168
168
  end, T.nilable(Dependabot::DependencyFile))
169
169
  end
170
170
 
171
171
  sig { returns(T.nilable(Dependabot::DependencyFile)) }
172
172
  def bun_lock
173
173
  @bun_lock ||= T.let(dependency_files.find do |f|
174
- f.name == BunPackageManager::LOCKFILE_NAME
174
+ f.name.end_with?(BunPackageManager::LOCKFILE_NAME)
175
175
  end, T.nilable(Dependabot::DependencyFile))
176
176
  end
177
177
 
178
178
  sig { returns(T.nilable(Dependabot::DependencyFile)) }
179
179
  def npmrc
180
180
  @npmrc ||= T.let(dependency_files.find do |f|
181
- f.name == NpmPackageManager::RC_FILENAME
181
+ f.name.end_with?(NpmPackageManager::RC_FILENAME)
182
182
  end, T.nilable(Dependabot::DependencyFile))
183
183
  end
184
184
 
185
185
  sig { returns(T.nilable(Dependabot::DependencyFile)) }
186
186
  def yarnrc
187
187
  @yarnrc ||= T.let(dependency_files.find do |f|
188
- f.name == YarnPackageManager::RC_FILENAME
188
+ f.name.end_with?(YarnPackageManager::RC_FILENAME)
189
189
  end, T.nilable(Dependabot::DependencyFile))
190
190
  end
191
191
 
192
192
  sig { returns(T.nilable(DependencyFile)) }
193
193
  def yarnrc_yml
194
194
  @yarnrc_yml ||= T.let(dependency_files.find do |f|
195
- f.name == YarnPackageManager::RC_YML_FILENAME
195
+ f.name.end_with?(YarnPackageManager::RC_YML_FILENAME)
196
196
  end, T.nilable(Dependabot::DependencyFile))
197
197
  end
198
198
 
@@ -212,7 +212,7 @@ module Dependabot
212
212
  next unless requirement.is_a?(String)
213
213
 
214
214
  # Skip dependencies using Yarn workspace cross-references as requirements
215
- next if requirement.start_with?("workspace:")
215
+ next if requirement.start_with?("workspace:", "catalog:")
216
216
 
217
217
  requirement = "*" if requirement == ""
218
218
  dep = build_dependency(
@@ -18,6 +18,10 @@ module Dependabot
18
18
  @dependency_files = dependency_files
19
19
  @repo_contents_path = repo_contents_path
20
20
  @credentials = credentials
21
+ @error_handler = PnpmErrorHandler.new(
22
+ dependencies: dependencies,
23
+ dependency_files: dependency_files
24
+ )
21
25
  end
22
26
 
23
27
  def updated_pnpm_lock_content(pnpm_lock)
@@ -36,6 +40,7 @@ module Dependabot
36
40
  attr_reader :dependency_files
37
41
  attr_reader :repo_contents_path
38
42
  attr_reader :credentials
43
+ attr_reader :error_handler
39
44
 
40
45
  IRRESOLVABLE_PACKAGE = "ERR_PNPM_NO_MATCHING_VERSION"
41
46
  INVALID_REQUIREMENT = "ERR_PNPM_SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER"
@@ -46,12 +51,12 @@ module Dependabot
46
51
  UNAUTHORIZED_PACKAGE = /ERR_PNPM_FETCH_401[ [^:print:]]+GET (?<dependency_url>.*): Unauthorized - 401/
47
52
 
48
53
  # ERR_PNPM_FETCH ERROR CODES
49
- ERR_PNPM_FETCH_401 = /ERR_PNPM_FETCH_401.*GET (?<dependency_url>.*): - 401/
50
- ERR_PNPM_FETCH_403 = /ERR_PNPM_FETCH_403.*GET (?<dependency_url>.*): - 403/
51
- ERR_PNPM_FETCH_404 = /ERR_PNPM_FETCH_404.*GET (?<dependency_url>.*): - 404/
52
- ERR_PNPM_FETCH_500 = /ERR_PNPM_FETCH_500.*GET (?<dependency_url>.*): - 500/
53
- ERR_PNPM_FETCH_502 = /ERR_PNPM_FETCH_502.*GET (?<dependency_url>.*): - 502/
54
- ERR_PNPM_FETCH_503 = /ERR_PNPM_FETCH_503.*GET (?<dependency_url>.*): - 503/
54
+ ERR_PNPM_FETCH_401 = /ERR_PNPM_FETCH_401.*GET (?<dependency_url>.*):/
55
+ ERR_PNPM_FETCH_403 = /ERR_PNPM_FETCH_403.*GET (?<dependency_url>.*):/
56
+ ERR_PNPM_FETCH_404 = /ERR_PNPM_FETCH_404.*GET (?<dependency_url>.*):/
57
+ ERR_PNPM_FETCH_500 = /ERR_PNPM_FETCH_500.*GET (?<dependency_url>.*):/
58
+ ERR_PNPM_FETCH_502 = /ERR_PNPM_FETCH_502.*GET (?<dependency_url>.*):/
59
+ ERR_PNPM_FETCH_503 = /ERR_PNPM_FETCH_503.*GET (?<dependency_url>.*):/
55
60
 
56
61
  # ERR_PNPM_UNSUPPORTED_ENGINE
57
62
  ERR_PNPM_UNSUPPORTED_ENGINE = /ERR_PNPM_UNSUPPORTED_ENGINE/
@@ -100,7 +105,7 @@ module Dependabot
100
105
  File.write(".npmrc", npmrc_content(pnpm_lock))
101
106
 
102
107
  SharedHelpers.with_git_configured(credentials: credentials) do
103
- run_pnpm_updater
108
+ run_pnpm_update_packages
104
109
 
105
110
  write_final_package_json_files
106
111
 
@@ -111,15 +116,22 @@ module Dependabot
111
116
  end
112
117
  end
113
118
 
114
- def run_pnpm_updater
119
+ def run_pnpm_update_packages
115
120
  dependency_updates = dependencies.map do |d|
116
121
  "#{d.name}@#{d.version}"
117
122
  end.join(" ")
118
123
 
119
- Helpers.run_pnpm_command(
120
- "install #{dependency_updates} --lockfile-only --ignore-workspace-root-check",
121
- fingerprint: "install <dependency_updates> --lockfile-only --ignore-workspace-root-check"
122
- )
124
+ if Dependabot::Experiments.enabled?(:enable_fix_for_pnpm_no_change_error)
125
+ Helpers.run_pnpm_command(
126
+ "update #{dependency_updates} --lockfile-only --no-save -r",
127
+ fingerprint: "update <dependency_updates> --lockfile-only --no-save -r"
128
+ )
129
+ else
130
+ Helpers.run_pnpm_command(
131
+ "install #{dependency_updates} --lockfile-only --ignore-workspace-root-check",
132
+ fingerprint: "install <dependency_updates> --lockfile-only --ignore-workspace-root-check"
133
+ )
134
+ end
123
135
  end
124
136
 
125
137
  def run_pnpm_install
@@ -251,6 +263,8 @@ module Dependabot
251
263
  pnpm_lock)
252
264
  end
253
265
 
266
+ error_handler.handle_pnpm_error(error)
267
+
254
268
  raise
255
269
  end
256
270
  # rubocop:enable Metrics/AbcSize
@@ -360,5 +374,60 @@ module Dependabot
360
374
  end
361
375
  end
362
376
  end
377
+
378
+ class PnpmErrorHandler
379
+ extend T::Sig
380
+
381
+ # remote connection closed
382
+ ECONNRESET_ERROR = /ECONNRESET/
383
+
384
+ # socket hang up error code
385
+ SOCKET_HANG_UP = /socket hang up/
386
+
387
+ # ERR_PNPM_CATALOG_ENTRY_NOT_FOUND_FOR_SPEC error
388
+ ERR_PNPM_CATALOG_ENTRY_NOT_FOUND_FOR_SPEC = /ERR_PNPM_CATALOG_ENTRY_NOT_FOUND_FOR_SPEC/
389
+
390
+ # duplicate package error code
391
+ DUPLICATE_PACKAGE = /Found duplicates/
392
+
393
+ ERR_PNPM_NO_VERSIONS = /ERR_PNPM_NO_VERSIONS/
394
+
395
+ # Initializes the YarnErrorHandler with dependencies and dependency files
396
+ sig do
397
+ params(
398
+ dependencies: T::Array[Dependabot::Dependency],
399
+ dependency_files: T::Array[Dependabot::DependencyFile]
400
+ ).void
401
+ end
402
+ def initialize(dependencies:, dependency_files:)
403
+ @dependencies = dependencies
404
+ @dependency_files = dependency_files
405
+ end
406
+
407
+ private
408
+
409
+ sig { returns(T::Array[Dependabot::Dependency]) }
410
+ attr_reader :dependencies
411
+
412
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
413
+ attr_reader :dependency_files
414
+
415
+ public
416
+
417
+ # Handles errors with specific to yarn error codes
418
+ sig { params(error: SharedHelpers::HelperSubprocessFailed).void }
419
+ def handle_pnpm_error(error)
420
+ if error.message.match?(DUPLICATE_PACKAGE) || error.message.match?(ERR_PNPM_NO_VERSIONS) ||
421
+ error.message.match?(ERR_PNPM_CATALOG_ENTRY_NOT_FOUND_FOR_SPEC)
422
+
423
+ raise DependencyFileNotResolvable, "Error resolving dependency"
424
+ end
425
+
426
+ ## Clean error message from ANSI escape codes
427
+ return unless error.message.match?(ECONNRESET_ERROR) || error.message.match?(SOCKET_HANG_UP)
428
+
429
+ raise InconsistentRegistryResponse, "Inconsistent registry response while resolving dependency"
430
+ end
431
+ end
363
432
  end
364
433
  end
@@ -48,6 +48,7 @@ module Dependabot
48
48
  ]
49
49
  end
50
50
 
51
+ # rubocop:disable Metrics/PerceivedComplexity
51
52
  sig { override.returns(T::Array[DependencyFile]) }
52
53
  def updated_dependency_files
53
54
  updated_files = T.let([], T::Array[DependencyFile])
@@ -56,6 +57,22 @@ module Dependabot
56
57
  updated_files += updated_lockfiles
57
58
 
58
59
  if updated_files.none?
60
+
61
+ if Dependabot::Experiments.enabled?(:enable_fix_for_pnpm_no_change_error)
62
+ # when all dependencies are transitive
63
+ all_transitive = dependencies.none?(&:top_level?)
64
+ # when there is no update in package.json
65
+ no_package_json_update = package_files.empty?
66
+ # handle the no change error for transitive dependency updates
67
+ if pnpm_locks.any? && dependencies.length.positive? && all_transitive && no_package_json_update
68
+ raise ToolFeatureNotSupported.new(
69
+ tool_name: "pnpm",
70
+ tool_type: "package_manager",
71
+ feature: "updating transitive dependencies"
72
+ )
73
+ end
74
+ end
75
+
59
76
  raise NoChangeError.new(
60
77
  message: "No files were updated!",
61
78
  error_context: error_context(updated_files: updated_files)
@@ -72,6 +89,7 @@ module Dependabot
72
89
 
73
90
  vendor_updated_files(updated_files)
74
91
  end
92
+ # rubocop:enable Metrics/PerceivedComplexity
75
93
 
76
94
  private
77
95
 
@@ -40,6 +40,9 @@ module Dependabot
40
40
  YARN_DEFAULT_VERSION = YARN_V3
41
41
  YARN_FALLBACK_VERSION = YARN_V1
42
42
 
43
+ # corepack supported package managers
44
+ SUPPORTED_COREPACK_PACKAGE_MANAGERS = %w(npm yarn pnpm).freeze
45
+
43
46
  # Determines the npm version depends to the feature flag
44
47
  # If the feature flag is enabled, we are going to use the minimum version npm 8
45
48
  # Otherwise, we are going to use old versionining npm 6
@@ -324,8 +327,8 @@ module Dependabot
324
327
  package_manager_run_command(NpmPackageManager::NAME, command, fingerprint: fingerprint)
325
328
  else
326
329
  Dependabot::SharedHelpers.run_shell_command(
327
- "corepack npm #{command}",
328
- fingerprint: "corepack npm #{fingerprint}"
330
+ "npm #{command}",
331
+ fingerprint: "npm #{fingerprint}"
329
332
  )
330
333
  end
331
334
  end
@@ -484,6 +487,8 @@ module Dependabot
484
487
  .returns(String)
485
488
  end
486
489
  def self.package_manager_install(name, version, env: {})
490
+ return "Corepack does not support #{name}" unless corepack_supported_package_manager?(name)
491
+
487
492
  Dependabot::SharedHelpers.run_shell_command(
488
493
  "corepack install #{name}@#{version} --global --cache-only",
489
494
  fingerprint: "corepack install <name>@<version> --global --cache-only",
@@ -494,6 +499,8 @@ module Dependabot
494
499
  # Prepare the package manager for use by using corepack
495
500
  sig { params(name: String, version: String).returns(String) }
496
501
  def self.package_manager_activate(name, version)
502
+ return "Corepack does not support #{name}" unless corepack_supported_package_manager?(name)
503
+
497
504
  Dependabot::SharedHelpers.run_shell_command(
498
505
  "corepack prepare #{name}@#{version} --activate",
499
506
  fingerprint: "corepack prepare <name>@<version> --activate"
@@ -566,6 +573,11 @@ module Dependabot
566
573
  dependency
567
574
  end
568
575
  end
576
+
577
+ sig { params(name: String).returns(T::Boolean) }
578
+ def self.corepack_supported_package_manager?(name)
579
+ SUPPORTED_COREPACK_PACKAGE_MANAGERS.include?(name)
580
+ end
569
581
  end
570
582
  end
571
583
  end
@@ -59,14 +59,16 @@ module Dependabot
59
59
  T.any(
60
60
  T.class_of(Dependabot::NpmAndYarn::NpmPackageManager),
61
61
  T.class_of(Dependabot::NpmAndYarn::YarnPackageManager),
62
- T.class_of(Dependabot::NpmAndYarn::PNPMPackageManager)
62
+ T.class_of(Dependabot::NpmAndYarn::PNPMPackageManager),
63
+ T.class_of(Dependabot::NpmAndYarn::BunPackageManager)
63
64
  )
64
65
  end
65
66
 
66
67
  PACKAGE_MANAGER_CLASSES = T.let({
67
68
  NpmPackageManager::NAME => NpmPackageManager,
68
69
  YarnPackageManager::NAME => YarnPackageManager,
69
- PNPMPackageManager::NAME => PNPMPackageManager
70
+ PNPMPackageManager::NAME => PNPMPackageManager,
71
+ BunPackageManager::NAME => BunPackageManager
70
72
  }.freeze, T::Hash[String, NpmAndYarnPackageManagerClassType])
71
73
 
72
74
  # Error malformed version number string
@@ -80,6 +80,10 @@ module Dependabot
80
80
  # Matches @ followed by x.y.z (digits separated by dots)
81
81
  if (match = version.match(/@(\d+\.\d+\.\d+)/))
82
82
  version = match[1] # Just "4.5.3"
83
+
84
+ # Extract version in case the output contains Corepack verbose data
85
+ elsif version.include?("Corepack")
86
+ version = T.must(T.must(version.tr("\n", " ").match(/(\d+\.\d+\.\d+)/))[-1])
83
87
  end
84
88
  version = version&.gsub(/^v/, "")
85
89
  end
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.293.0
4
+ version: 0.294.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-01-16 00:00:00.000000000 Z
11
+ date: 2025-01-23 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.293.0
19
+ version: 0.294.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.293.0
26
+ version: 0.294.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: debug
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -354,7 +354,7 @@ licenses:
354
354
  - MIT
355
355
  metadata:
356
356
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
357
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.293.0
357
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.294.0
358
358
  post_install_message:
359
359
  rdoc_options: []
360
360
  require_paths: