dependabot-npm_and_yarn 0.309.0 → 0.311.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.
- checksums.yaml +4 -4
- data/lib/dependabot/npm_and_yarn/file_parser/json_lock.rb +1 -1
- data/lib/dependabot/npm_and_yarn/file_parser/pnpm_lock.rb +60 -19
- data/lib/dependabot/npm_and_yarn/file_parser/yarn_lock.rb +37 -16
- data/lib/dependabot/npm_and_yarn/file_updater/bun_lockfile_updater.rb +60 -19
- data/lib/dependabot/npm_and_yarn/file_updater/npm_lockfile_updater.rb +4 -50
- data/lib/dependabot/npm_and_yarn/file_updater/package_json_preparer.rb +16 -4
- data/lib/dependabot/npm_and_yarn/file_updater/pnpm_lockfile_updater.rb +161 -51
- data/lib/dependabot/npm_and_yarn/file_updater/yarn_lockfile_updater.rb +211 -60
- data/lib/dependabot/npm_and_yarn/file_updater.rb +1 -1
- data/lib/dependabot/npm_and_yarn/helpers.rb +12 -59
- data/lib/dependabot/npm_and_yarn/metadata_finder.rb +64 -15
- data/lib/dependabot/npm_and_yarn/native_helpers.rb +8 -1
- data/lib/dependabot/npm_and_yarn/package/registry_finder.rb +1 -1
- data/lib/dependabot/npm_and_yarn/requirement.rb +23 -9
- data/lib/dependabot/npm_and_yarn/update_checker/conflicting_dependency_resolver.rb +36 -9
- data/lib/dependabot/npm_and_yarn/update_checker/dependency_files_builder.rb +82 -24
- data/lib/dependabot/npm_and_yarn/update_checker/library_detector.rb +35 -5
- data/lib/dependabot/npm_and_yarn/update_checker/requirements_updater.rb +61 -24
- data/lib/dependabot/npm_and_yarn/update_checker/subdependency_version_resolver.rb +66 -37
- data/lib/dependabot/npm_and_yarn/update_checker/version_resolver.rb +1 -1
- data/lib/dependabot/npm_and_yarn/update_checker/vulnerability_auditor.rb +60 -7
- data/lib/dependabot/npm_and_yarn/update_checker.rb +18 -8
- metadata +9 -9
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require "dependabot/npm_and_yarn/helpers"
|
@@ -9,24 +9,47 @@ require "dependabot/shared_helpers"
|
|
9
9
|
module Dependabot
|
10
10
|
module NpmAndYarn
|
11
11
|
class FileUpdater < Dependabot::FileUpdaters::Base
|
12
|
+
# rubocop:disable Metrics/ClassLength
|
12
13
|
class PnpmLockfileUpdater
|
14
|
+
extend T::Sig
|
15
|
+
|
13
16
|
require_relative "npmrc_builder"
|
14
17
|
require_relative "package_json_updater"
|
15
18
|
|
19
|
+
sig do
|
20
|
+
params(
|
21
|
+
dependencies: T::Array[Dependabot::Dependency],
|
22
|
+
dependency_files: T::Array[Dependabot::DependencyFile],
|
23
|
+
repo_contents_path: T.nilable(String),
|
24
|
+
credentials: T::Array[Dependabot::Credential]
|
25
|
+
).void
|
26
|
+
end
|
16
27
|
def initialize(dependencies:, dependency_files:, repo_contents_path:, credentials:)
|
17
28
|
@dependencies = dependencies
|
18
29
|
@dependency_files = dependency_files
|
19
30
|
@repo_contents_path = repo_contents_path
|
20
31
|
@credentials = credentials
|
21
|
-
@error_handler =
|
22
|
-
|
23
|
-
|
32
|
+
@error_handler = T.let(
|
33
|
+
PnpmErrorHandler.new(
|
34
|
+
dependencies: dependencies,
|
35
|
+
dependency_files: dependency_files
|
36
|
+
),
|
37
|
+
PnpmErrorHandler
|
24
38
|
)
|
25
39
|
end
|
26
40
|
|
41
|
+
sig do
|
42
|
+
params(
|
43
|
+
pnpm_lock: Dependabot::DependencyFile,
|
44
|
+
updated_pnpm_workspace_content: T.nilable(T::Hash[String, T.nilable(String)])
|
45
|
+
).returns(String)
|
46
|
+
end
|
27
47
|
def updated_pnpm_lock_content(pnpm_lock, updated_pnpm_workspace_content: nil)
|
28
|
-
@updated_pnpm_lock_content ||=
|
29
|
-
|
48
|
+
@updated_pnpm_lock_content ||= T.let(
|
49
|
+
{},
|
50
|
+
T.nilable(T::Hash[String, String])
|
51
|
+
)
|
52
|
+
return T.must(@updated_pnpm_lock_content[pnpm_lock.name]) if @updated_pnpm_lock_content[pnpm_lock.name]
|
30
53
|
|
31
54
|
new_content = run_pnpm_update(
|
32
55
|
pnpm_lock: pnpm_lock,
|
@@ -39,10 +62,19 @@ module Dependabot
|
|
39
62
|
|
40
63
|
private
|
41
64
|
|
65
|
+
sig { returns(T::Array[Dependabot::Dependency]) }
|
42
66
|
attr_reader :dependencies
|
67
|
+
|
68
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
43
69
|
attr_reader :dependency_files
|
70
|
+
|
71
|
+
sig { returns(T.nilable(String)) }
|
44
72
|
attr_reader :repo_contents_path
|
73
|
+
|
74
|
+
sig { returns(T::Array[Dependabot::Credential]) }
|
45
75
|
attr_reader :credentials
|
76
|
+
|
77
|
+
sig { returns(PnpmErrorHandler) }
|
46
78
|
attr_reader :error_handler
|
47
79
|
|
48
80
|
IRRESOLVABLE_PACKAGE = "ERR_PNPM_NO_MATCHING_VERSION"
|
@@ -103,6 +135,13 @@ module Dependabot
|
|
103
135
|
# Peer dependencies configuration error
|
104
136
|
ERR_PNPM_PEER_DEP_ISSUES = /ERR_PNPM_PEER_DEP_ISSUES/
|
105
137
|
|
138
|
+
sig do
|
139
|
+
params(
|
140
|
+
pnpm_lock: Dependabot::DependencyFile,
|
141
|
+
updated_pnpm_workspace_content: T.nilable(T::Hash[String, T.nilable(String)])
|
142
|
+
)
|
143
|
+
.returns(String)
|
144
|
+
end
|
106
145
|
def run_pnpm_update(pnpm_lock:, updated_pnpm_workspace_content: nil)
|
107
146
|
SharedHelpers.in_a_temporary_repo_directory(base_dir, repo_contents_path) do
|
108
147
|
File.write(".npmrc", npmrc_content(pnpm_lock))
|
@@ -122,6 +161,7 @@ module Dependabot
|
|
122
161
|
end
|
123
162
|
end
|
124
163
|
|
164
|
+
sig { returns(T.nilable(String)) }
|
125
165
|
def run_pnpm_update_packages
|
126
166
|
dependency_updates = dependencies.map do |d|
|
127
167
|
"#{d.name}@#{d.version}"
|
@@ -133,18 +173,24 @@ module Dependabot
|
|
133
173
|
)
|
134
174
|
end
|
135
175
|
|
176
|
+
sig { returns(T.nilable(String)) }
|
136
177
|
def run_pnpm_install
|
137
178
|
Helpers.run_pnpm_command(
|
138
179
|
"install --lockfile-only"
|
139
180
|
)
|
140
181
|
end
|
141
182
|
|
183
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
142
184
|
def workspace_files
|
143
|
-
@workspace_files ||=
|
185
|
+
@workspace_files ||= T.let(
|
186
|
+
dependency_files.select { |f| f.name.end_with?("pnpm-workspace.yaml") },
|
187
|
+
T.nilable(T::Array[Dependabot::DependencyFile])
|
188
|
+
)
|
144
189
|
end
|
145
190
|
|
191
|
+
sig { params(lockfile: Dependabot::DependencyFile).returns(T::Array[Dependabot::Dependency]) }
|
146
192
|
def lockfile_dependencies(lockfile)
|
147
|
-
@lockfile_dependencies ||= {}
|
193
|
+
@lockfile_dependencies ||= T.let({}, T.nilable(T::Hash[String, T::Array[Dependabot::Dependency]]))
|
148
194
|
@lockfile_dependencies[lockfile.name] ||=
|
149
195
|
NpmAndYarn::FileParser.new(
|
150
196
|
dependency_files: [lockfile, *package_files, *workspace_files],
|
@@ -157,6 +203,13 @@ module Dependabot
|
|
157
203
|
# rubocop:disable Metrics/PerceivedComplexity
|
158
204
|
# rubocop:disable Metrics/MethodLength
|
159
205
|
# rubocop:disable Metrics/CyclomaticComplexity
|
206
|
+
sig do
|
207
|
+
params(
|
208
|
+
error: SharedHelpers::HelperSubprocessFailed,
|
209
|
+
pnpm_lock: Dependabot::DependencyFile
|
210
|
+
)
|
211
|
+
.returns(T.noreturn)
|
212
|
+
end
|
160
213
|
def handle_pnpm_lock_updater_error(error, pnpm_lock)
|
161
214
|
error_message = error.message
|
162
215
|
|
@@ -165,15 +218,15 @@ module Dependabot
|
|
165
218
|
end
|
166
219
|
|
167
220
|
if error_message.match?(UNREACHABLE_GIT)
|
168
|
-
url = error_message.match(UNREACHABLE_GIT)
|
221
|
+
url = error_message.match(UNREACHABLE_GIT)&.named_captures&.fetch("url")&.gsub("git+ssh://git@", "https://")&.delete_suffix(".git")
|
169
222
|
|
170
|
-
raise Dependabot::GitDependenciesNotReachable, url
|
223
|
+
raise Dependabot::GitDependenciesNotReachable, T.must(url)
|
171
224
|
end
|
172
225
|
|
173
226
|
if error_message.match?(UNREACHABLE_GIT_V8)
|
174
|
-
url = error_message.match(UNREACHABLE_GIT_V8)
|
227
|
+
url = error_message.match(UNREACHABLE_GIT_V8)&.named_captures&.fetch("url")&.gsub("codeload.", "")
|
175
228
|
|
176
|
-
raise Dependabot::GitDependenciesNotReachable, url
|
229
|
+
raise Dependabot::GitDependenciesNotReachable, T.must(url)
|
177
230
|
end
|
178
231
|
|
179
232
|
[FORBIDDEN_PACKAGE, MISSING_PACKAGE, UNAUTHORIZED_PACKAGE, ERR_PNPM_FETCH_401,
|
@@ -181,14 +234,13 @@ module Dependabot
|
|
181
234
|
.each do |regexp|
|
182
235
|
next unless error_message.match?(regexp)
|
183
236
|
|
184
|
-
dependency_url = error_message.match(regexp)
|
237
|
+
dependency_url = T.must(error_message.match(regexp)&.named_captures&.[]("dependency_url"))
|
185
238
|
raise_package_access_error(error_message, dependency_url, pnpm_lock)
|
186
239
|
end
|
187
240
|
|
188
241
|
# TO-DO : subclassifcation of ERR_PNPM_TARBALL_INTEGRITY errors
|
189
242
|
if error_message.match?(ERR_PNPM_TARBALL_INTEGRITY)
|
190
243
|
dependency_names = dependencies.map(&:name).join(", ")
|
191
|
-
|
192
244
|
msg = "Error (ERR_PNPM_TARBALL_INTEGRITY) while resolving \"#{dependency_names}\"."
|
193
245
|
Dependabot.logger.warn(error_message)
|
194
246
|
raise Dependabot::DependencyFileNotResolvable, msg
|
@@ -197,20 +249,17 @@ module Dependabot
|
|
197
249
|
# TO-DO : investigate "packageManager" allowed regex
|
198
250
|
if error_message.match?(INVALID_PACKAGE_SPEC)
|
199
251
|
dependency_names = dependencies.map(&:name).join(", ")
|
200
|
-
|
201
252
|
msg = "Invalid package manager specification in package.json while resolving \"#{dependency_names}\"."
|
202
253
|
raise Dependabot::DependencyFileNotResolvable, msg
|
203
254
|
end
|
204
255
|
|
205
256
|
if error_message.match?(ERR_PNPM_META_FETCH_FAIL)
|
206
|
-
|
207
257
|
msg = error_message.split(ERR_PNPM_META_FETCH_FAIL).last
|
208
258
|
raise Dependabot::DependencyFileNotResolvable, msg
|
209
259
|
end
|
210
260
|
|
211
261
|
if error_message.match?(ERR_PNPM_WORKSPACE_PKG_NOT_FOUND)
|
212
262
|
dependency_names = dependencies.map(&:name).join(", ")
|
213
|
-
|
214
263
|
msg = "No package named \"#{dependency_names}\" present in workspace."
|
215
264
|
Dependabot.logger.warn(error_message)
|
216
265
|
raise Dependabot::DependencyFileNotResolvable, msg
|
@@ -223,8 +272,8 @@ module Dependabot
|
|
223
272
|
end
|
224
273
|
|
225
274
|
if error_message.match?(ERR_PNPM_LINKED_PKG_DIR_NOT_FOUND)
|
226
|
-
dir = error_message.match(ERR_PNPM_LINKED_PKG_DIR_NOT_FOUND)
|
227
|
-
msg = "Could not find linked package installation directory \"#{dir
|
275
|
+
dir = error_message.match(ERR_PNPM_LINKED_PKG_DIR_NOT_FOUND)&.named_captures&.fetch("dir")
|
276
|
+
msg = "Could not find linked package installation directory \"#{dir&.split('/')&.last}\""
|
228
277
|
raise Dependabot::DependencyFileNotResolvable, msg
|
229
278
|
end
|
230
279
|
|
@@ -246,13 +295,11 @@ module Dependabot
|
|
246
295
|
|
247
296
|
if error_message.match?(ERR_PNPM_PEER_DEP_ISSUES)
|
248
297
|
msg = "Missing or invalid configuration while installing peer dependencies."
|
249
|
-
|
250
298
|
Dependabot.logger.warn(error_message)
|
251
299
|
raise Dependabot::DependencyFileNotResolvable, msg
|
252
300
|
end
|
253
301
|
|
254
302
|
raise_patch_dependency_error(error_message) if error_message.match?(ERR_PNPM_PATCH_NOT_APPLIED)
|
255
|
-
|
256
303
|
raise_unsupported_engine_error(error_message, pnpm_lock) if error_message.match?(ERR_PNPM_UNSUPPORTED_ENGINE)
|
257
304
|
|
258
305
|
if error_message.match?(ERR_INVALID_THIS) && error_message.match?(URL_SEARCH_PARAMS)
|
@@ -262,8 +309,7 @@ module Dependabot
|
|
262
309
|
end
|
263
310
|
|
264
311
|
if error_message.match?(ERR_PNPM_UNSUPPORTED_PLATFORM)
|
265
|
-
raise_unsupported_platform_error(error_message,
|
266
|
-
pnpm_lock)
|
312
|
+
raise_unsupported_platform_error(error_message, pnpm_lock)
|
267
313
|
end
|
268
314
|
|
269
315
|
error_handler.handle_pnpm_error(error)
|
@@ -275,6 +321,7 @@ module Dependabot
|
|
275
321
|
# rubocop:enable Metrics/MethodLength
|
276
322
|
# rubocop:enable Metrics/CyclomaticComplexity
|
277
323
|
|
324
|
+
sig { params(error_message: String, pnpm_lock: Dependabot::DependencyFile).returns(T.noreturn) }
|
278
325
|
def raise_resolvability_error(error_message, pnpm_lock)
|
279
326
|
dependency_names = dependencies.map(&:name).join(", ")
|
280
327
|
msg = "Error whilst updating #{dependency_names} in " \
|
@@ -282,6 +329,7 @@ module Dependabot
|
|
282
329
|
raise Dependabot::DependencyFileNotResolvable, msg
|
283
330
|
end
|
284
331
|
|
332
|
+
sig { params(error_message: String).returns(T.noreturn) }
|
285
333
|
def raise_patch_dependency_error(error_message)
|
286
334
|
dependency_names = dependencies.map(&:name).join(", ")
|
287
335
|
msg = "Error while updating \"#{dependency_names}\" in " \
|
@@ -290,21 +338,50 @@ module Dependabot
|
|
290
338
|
raise Dependabot::DependencyFileNotResolvable, msg
|
291
339
|
end
|
292
340
|
|
341
|
+
sig do
|
342
|
+
params(
|
343
|
+
error_message: String,
|
344
|
+
_pnpm_lock: Dependabot::DependencyFile
|
345
|
+
).returns(T.nilable(T.noreturn))
|
346
|
+
end
|
293
347
|
def raise_unsupported_engine_error(error_message, _pnpm_lock)
|
294
|
-
|
295
|
-
|
296
|
-
|
348
|
+
match_pkg_mgr = error_message.match(PACAKGE_MANAGER)
|
349
|
+
match_version = error_message.match(VERSION_REQUIREMENT)
|
350
|
+
|
351
|
+
unless match_pkg_mgr && match_version &&
|
352
|
+
match_pkg_mgr.named_captures && match_version.named_captures
|
353
|
+
return nil
|
297
354
|
end
|
298
355
|
|
299
|
-
|
300
|
-
|
301
|
-
|
356
|
+
captures_pkg_mgr = match_pkg_mgr.named_captures
|
357
|
+
captures_version = match_version.named_captures
|
358
|
+
|
359
|
+
pkg_mgr = captures_pkg_mgr["pkg_mgr"]
|
360
|
+
supported_ver = captures_version["supported_ver"]
|
361
|
+
detected_ver = captures_version["detected_ver"]
|
362
|
+
|
363
|
+
if pkg_mgr && supported_ver && detected_ver
|
364
|
+
raise Dependabot::ToolVersionNotSupported.new(
|
365
|
+
pkg_mgr,
|
366
|
+
supported_ver,
|
367
|
+
detected_ver
|
368
|
+
)
|
369
|
+
end
|
302
370
|
|
303
|
-
|
371
|
+
nil
|
304
372
|
end
|
305
373
|
|
374
|
+
sig do
|
375
|
+
params(
|
376
|
+
error_message: String,
|
377
|
+
dependency_url: String,
|
378
|
+
pnpm_lock: Dependabot::DependencyFile
|
379
|
+
)
|
380
|
+
.returns(T.noreturn)
|
381
|
+
end
|
306
382
|
def raise_package_access_error(error_message, dependency_url, pnpm_lock)
|
307
|
-
package_name = RegistryParser.new(resolved_url: dependency_url,
|
383
|
+
package_name = RegistryParser.new(resolved_url: dependency_url,
|
384
|
+
credentials: credentials).dependency_name
|
308
385
|
missing_dep = lockfile_dependencies(pnpm_lock)
|
309
386
|
.find { |dep| dep.name == package_name }
|
310
387
|
raise DependencyNotFound, package_name unless missing_dep
|
@@ -318,6 +395,7 @@ module Dependabot
|
|
318
395
|
raise PrivateSourceAuthenticationFailure, reg
|
319
396
|
end
|
320
397
|
|
398
|
+
sig { void }
|
321
399
|
def write_final_package_json_files
|
322
400
|
package_files.each do |file|
|
323
401
|
path = file.name
|
@@ -326,57 +404,88 @@ module Dependabot
|
|
326
404
|
end
|
327
405
|
end
|
328
406
|
|
407
|
+
sig do
|
408
|
+
params(
|
409
|
+
error_message: String,
|
410
|
+
_pnpm_lock: Dependabot::DependencyFile
|
411
|
+
)
|
412
|
+
.returns(T.nilable(T.noreturn))
|
413
|
+
end
|
329
414
|
def raise_unsupported_platform_error(error_message, _pnpm_lock)
|
330
|
-
|
331
|
-
|
332
|
-
|
415
|
+
match_dep = error_message.match(PLATFORM_PACAKGE_DEP)
|
416
|
+
match_version = error_message.match(PLATFORM_VERSION_REQUIREMENT)
|
417
|
+
|
418
|
+
unless match_dep && match_version &&
|
419
|
+
match_dep.named_captures && match_version.named_captures
|
420
|
+
return nil
|
333
421
|
end
|
334
422
|
|
335
|
-
|
336
|
-
.named_captures["supported_ver"]
|
337
|
-
.then { sanitize_message(_1) }
|
338
|
-
detected_version = error_message.match(PLATFORM_VERSION_REQUIREMENT)
|
339
|
-
.named_captures["detected_ver"]
|
340
|
-
.then { sanitize_message(_1) }
|
423
|
+
captures_version = match_version.named_captures
|
341
424
|
|
342
|
-
|
343
|
-
|
425
|
+
supported_ver = captures_version["supported_ver"]
|
426
|
+
detected_ver = captures_version["detected_ver"]
|
427
|
+
|
428
|
+
if supported_ver && detected_ver
|
429
|
+
supported_version = sanitize_message(supported_ver)
|
430
|
+
detected_version = sanitize_message(detected_ver)
|
431
|
+
|
432
|
+
Dependabot.logger.warn(error_message)
|
433
|
+
raise Dependabot::ToolVersionNotSupported.new(
|
434
|
+
PLATFORM_PACAKGE_MANAGER,
|
435
|
+
supported_version,
|
436
|
+
detected_version
|
437
|
+
)
|
438
|
+
end
|
439
|
+
|
440
|
+
nil
|
344
441
|
end
|
345
442
|
|
443
|
+
sig { params(pnpm_lock: Dependabot::DependencyFile).returns(String) }
|
346
444
|
def npmrc_content(pnpm_lock)
|
347
445
|
NpmrcBuilder.new(
|
348
|
-
credentials: credentials,
|
446
|
+
credentials: T.unsafe(credentials),
|
349
447
|
dependency_files: dependency_files,
|
350
448
|
dependencies: lockfile_dependencies(pnpm_lock)
|
351
449
|
).npmrc_content
|
352
450
|
end
|
353
451
|
|
452
|
+
sig { params(file: Dependabot::DependencyFile).returns(String) }
|
354
453
|
def updated_package_json_content(file)
|
355
|
-
@updated_package_json_content ||= {}
|
454
|
+
@updated_package_json_content ||= T.let({}, T.nilable(T::Hash[String, String]))
|
356
455
|
@updated_package_json_content[file.name] ||=
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
456
|
+
T.must(
|
457
|
+
PackageJsonUpdater.new(
|
458
|
+
package_json: file,
|
459
|
+
dependencies: dependencies
|
460
|
+
).updated_package_json.content
|
461
|
+
)
|
361
462
|
end
|
362
463
|
|
464
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
363
465
|
def package_files
|
364
|
-
@package_files ||=
|
466
|
+
@package_files ||= T.let(
|
467
|
+
dependency_files.select { |f| f.name.end_with?("package.json") },
|
468
|
+
T.nilable(T::Array[Dependabot::DependencyFile])
|
469
|
+
)
|
365
470
|
end
|
366
471
|
|
472
|
+
sig { returns(String) }
|
367
473
|
def base_dir
|
368
|
-
dependency_files.first.directory
|
474
|
+
T.must(dependency_files.first).directory
|
369
475
|
end
|
370
476
|
|
477
|
+
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
371
478
|
def npmrc_file
|
372
479
|
dependency_files.find { |f| f.name == ".npmrc" }
|
373
480
|
end
|
374
481
|
|
482
|
+
sig { params(message: String).returns(String) }
|
375
483
|
def sanitize_message(message)
|
376
484
|
message.gsub(/"|\[|\]|\}|\{/, "")
|
377
485
|
end
|
378
486
|
end
|
379
487
|
end
|
488
|
+
# rubocop:enable Metrics/ClassLength
|
380
489
|
|
381
490
|
class PnpmErrorHandler
|
382
491
|
extend T::Sig
|
@@ -400,7 +509,8 @@ module Dependabot
|
|
400
509
|
params(
|
401
510
|
dependencies: T::Array[Dependabot::Dependency],
|
402
511
|
dependency_files: T::Array[Dependabot::DependencyFile]
|
403
|
-
)
|
512
|
+
)
|
513
|
+
.void
|
404
514
|
end
|
405
515
|
def initialize(dependencies:, dependency_files:)
|
406
516
|
@dependencies = dependencies
|