dependabot-cargo 0.385.0 → 0.386.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/cargo/file_fetcher.rb +87 -65
- data/lib/dependabot/cargo/file_parser.rb +52 -26
- data/lib/dependabot/cargo/file_updater/lockfile_updater.rb +23 -6
- data/lib/dependabot/cargo/metadata_finder.rb +25 -11
- data/lib/dependabot/cargo/package/package_details_fetcher.rb +28 -22
- data/lib/dependabot/cargo/update_checker/file_preparer.rb +107 -42
- data/lib/dependabot/cargo/update_checker/requirements_updater.rb +3 -3
- data/lib/dependabot/cargo/update_checker.rb +2 -2
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 342398b3a35a615f1b23ae103f2a61e3c11ab24fb92b2eb3f6227b68cdae6600
|
|
4
|
+
data.tar.gz: a087cc721a765e9b8fd424a6972e1f110895947e36048906832a6f7acc59baed
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 236e947dcc2a2a2674432ac934826740dd42591dd0568211059e11bc79d5f3875c70f63aedab2f03f5351170e3d2a9dd7537385e2c3fd240f5c02621a4624973
|
|
7
|
+
data.tar.gz: affa0255ca4605212a1a233cc636893532aa5b5743d94fd4a1fb1d75e70bc52ce36fb245c92cd19e5c13787906702137be32492cbc5b08327bb19875ff7ecfe0
|
|
@@ -28,7 +28,7 @@ module Dependabot
|
|
|
28
28
|
"Repo must contain a Cargo.toml."
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
-
sig { override.returns(T.nilable(T::Hash[Symbol, T.
|
|
31
|
+
sig { override.returns(T.nilable(T::Hash[Symbol, T.anything])) }
|
|
32
32
|
def ecosystem_versions
|
|
33
33
|
channel = if rust_toolchain
|
|
34
34
|
TomlRB.parse(T.must(rust_toolchain).content).dig("toolchain", "channel")
|
|
@@ -180,12 +180,14 @@ module Dependabot
|
|
|
180
180
|
find_workspace_root(file)
|
|
181
181
|
end
|
|
182
182
|
|
|
183
|
-
sig { params(dependencies: T::Hash[
|
|
183
|
+
sig { params(dependencies: T::Hash[String, T.anything]).returns(T::Array[String]) }
|
|
184
184
|
def collect_path_dependencies_paths(dependencies)
|
|
185
185
|
dependencies.filter_map do |_, details|
|
|
186
|
-
|
|
186
|
+
details = toml_table(details)
|
|
187
|
+
path = T.cast(details&.fetch("path", nil), T.nilable(String))
|
|
188
|
+
next unless path
|
|
187
189
|
|
|
188
|
-
File.join(
|
|
190
|
+
File.join(path, "Cargo.toml").delete_prefix("/")
|
|
189
191
|
end
|
|
190
192
|
end
|
|
191
193
|
|
|
@@ -194,18 +196,19 @@ module Dependabot
|
|
|
194
196
|
def path_dependency_paths_from_file(file)
|
|
195
197
|
paths = T.let([], T::Array[String])
|
|
196
198
|
|
|
197
|
-
workspace = parsed_file(file).fetch("workspace", {})
|
|
199
|
+
workspace = toml_table_or_empty(parsed_file(file).fetch("workspace", {}))
|
|
198
200
|
Cargo::FileParser::DEPENDENCY_TYPES.each do |type|
|
|
199
201
|
# Paths specified in dependency declaration
|
|
200
|
-
paths += collect_path_dependencies_paths(parsed_file(file).fetch(type, {}))
|
|
202
|
+
paths += collect_path_dependencies_paths(toml_table_or_empty(parsed_file(file).fetch(type, {})))
|
|
201
203
|
# Paths specified as workspace dependencies in workspace root
|
|
202
|
-
paths += collect_path_dependencies_paths(workspace.fetch(type, {}))
|
|
204
|
+
paths += collect_path_dependencies_paths(toml_table_or_empty(workspace.fetch(type, {})))
|
|
203
205
|
end
|
|
204
206
|
|
|
205
207
|
# Paths specified for target-specific dependencies
|
|
206
|
-
parsed_file(file).fetch("target", {}).each do |_, t_details|
|
|
208
|
+
toml_table_or_empty(parsed_file(file).fetch("target", {})).each do |_, t_details|
|
|
209
|
+
t_details = toml_table_or_empty(t_details)
|
|
207
210
|
Cargo::FileParser::DEPENDENCY_TYPES.each do |type|
|
|
208
|
-
paths += collect_path_dependencies_paths(t_details.fetch(type, {}))
|
|
211
|
+
paths += collect_path_dependencies_paths(toml_table_or_empty(t_details.fetch(type, {})))
|
|
209
212
|
end
|
|
210
213
|
end
|
|
211
214
|
|
|
@@ -217,20 +220,25 @@ module Dependabot
|
|
|
217
220
|
paths = []
|
|
218
221
|
|
|
219
222
|
# Paths specified as replacements
|
|
220
|
-
parsed_file(file).fetch("replace", {}).each do |_, details|
|
|
221
|
-
|
|
223
|
+
toml_table_or_empty(parsed_file(file).fetch("replace", {})).each do |_, details|
|
|
224
|
+
details = toml_table(details)
|
|
225
|
+
path = T.cast(details&.fetch("path", nil), T.nilable(String))
|
|
226
|
+
next unless path
|
|
222
227
|
|
|
223
|
-
paths << File.join(
|
|
228
|
+
paths << File.join(path, "Cargo.toml")
|
|
224
229
|
end
|
|
225
230
|
|
|
226
231
|
# Paths specified as patches
|
|
227
|
-
parsed_file(file).fetch("patch", {}).each do |_, details|
|
|
228
|
-
|
|
232
|
+
toml_table_or_empty(parsed_file(file).fetch("patch", {})).each do |_, details|
|
|
233
|
+
details = toml_table(details)
|
|
234
|
+
next unless details
|
|
229
235
|
|
|
230
236
|
details.each do |_, dep_details|
|
|
231
|
-
|
|
237
|
+
dep_details = toml_table(dep_details)
|
|
238
|
+
path = T.cast(dep_details&.fetch("path", nil), T.nilable(String))
|
|
239
|
+
next unless path
|
|
232
240
|
|
|
233
|
-
paths << File.join(
|
|
241
|
+
paths << File.join(path, "Cargo.toml")
|
|
234
242
|
end
|
|
235
243
|
end
|
|
236
244
|
|
|
@@ -239,28 +247,31 @@ module Dependabot
|
|
|
239
247
|
|
|
240
248
|
# Check if this Cargo manifest uses workspace dependencies
|
|
241
249
|
# (e.g. dependency = { workspace = true }).
|
|
242
|
-
sig { params(parsed_manifest: T::Hash[
|
|
250
|
+
sig { params(parsed_manifest: T::Hash[String, T.anything]).returns(T::Boolean) }
|
|
243
251
|
def uses_workspace_dependencies?(parsed_manifest)
|
|
244
252
|
# Check regular dependencies
|
|
245
253
|
workspace_deps = Cargo::FileParser::DEPENDENCY_TYPES.any? do |type|
|
|
246
|
-
deps = parsed_manifest.fetch(type, {})
|
|
254
|
+
deps = toml_table_or_empty(parsed_manifest.fetch(type, {}))
|
|
247
255
|
deps.any? do |_, details|
|
|
248
|
-
|
|
256
|
+
details = toml_table(details)
|
|
257
|
+
next false unless details
|
|
249
258
|
|
|
250
|
-
details["workspace"] == true
|
|
259
|
+
T.cast(details["workspace"], T.nilable(Object)) == true
|
|
251
260
|
end
|
|
252
261
|
end
|
|
253
262
|
|
|
254
263
|
return true if workspace_deps
|
|
255
264
|
|
|
256
265
|
# Check target-specific dependencies
|
|
257
|
-
parsed_manifest.fetch("target", {}).any? do |_, target_details|
|
|
266
|
+
toml_table_or_empty(parsed_manifest.fetch("target", {})).any? do |_, target_details|
|
|
267
|
+
target_details = toml_table_or_empty(target_details)
|
|
258
268
|
Cargo::FileParser::DEPENDENCY_TYPES.any? do |type|
|
|
259
|
-
deps = target_details.fetch(type, {})
|
|
269
|
+
deps = toml_table_or_empty(target_details.fetch(type, {}))
|
|
260
270
|
deps.any? do |_, details|
|
|
261
|
-
|
|
271
|
+
details = toml_table(details)
|
|
272
|
+
next false unless details
|
|
262
273
|
|
|
263
|
-
details["workspace"] == true
|
|
274
|
+
T.cast(details["workspace"], T.nilable(Object)) == true
|
|
264
275
|
end
|
|
265
276
|
end
|
|
266
277
|
end
|
|
@@ -268,13 +279,14 @@ module Dependabot
|
|
|
268
279
|
|
|
269
280
|
# See if this Cargo manifest inherits any property from a workspace
|
|
270
281
|
# (e.g. edition = { workspace = true }).
|
|
271
|
-
sig { params(hash: T::Hash[
|
|
282
|
+
sig { params(hash: T::Hash[String, T.anything]).returns(T::Boolean) }
|
|
272
283
|
def workspace_member?(hash)
|
|
273
284
|
hash.each do |key, value|
|
|
285
|
+
value = T.cast(value, T.nilable(Object))
|
|
274
286
|
if key == "workspace" && value == true
|
|
275
287
|
return true
|
|
276
288
|
elsif value.is_a?(Hash)
|
|
277
|
-
return workspace_member?(value)
|
|
289
|
+
return workspace_member?(toml_table_or_empty(value))
|
|
278
290
|
end
|
|
279
291
|
end
|
|
280
292
|
false
|
|
@@ -289,7 +301,8 @@ module Dependabot
|
|
|
289
301
|
def find_workspace_root(workspace_member)
|
|
290
302
|
current_dir = workspace_member.name.rpartition("/").first
|
|
291
303
|
|
|
292
|
-
|
|
304
|
+
package = toml_table_or_empty(parsed_file(workspace_member)["package"])
|
|
305
|
+
workspace_root_dir = T.cast(package["workspace"], T.nilable(String))
|
|
293
306
|
unless workspace_root_dir.nil?
|
|
294
307
|
workspace_root = fetch_file_from_host(
|
|
295
308
|
File.join(current_dir, workspace_root_dir, "Cargo.toml"),
|
|
@@ -322,11 +335,10 @@ module Dependabot
|
|
|
322
335
|
|
|
323
336
|
sig { params(file: Dependabot::DependencyFile).returns(T::Array[String]) }
|
|
324
337
|
def workspace_dependency_paths_from_file(file)
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
end
|
|
338
|
+
workspace = toml_table(parsed_file(file)["workspace"])
|
|
339
|
+
return path_dependency_paths_from_file(file) if workspace && !workspace.key?("members")
|
|
328
340
|
|
|
329
|
-
workspace_paths =
|
|
341
|
+
workspace_paths = T.cast(workspace&.fetch("members", nil), T.nilable(T::Array[String]))
|
|
330
342
|
return [] unless workspace_paths&.any?
|
|
331
343
|
|
|
332
344
|
# Expand any workspace paths that specify a `*`
|
|
@@ -335,9 +347,7 @@ module Dependabot
|
|
|
335
347
|
end
|
|
336
348
|
|
|
337
349
|
# Excluded paths, to be subtracted for the workspaces array
|
|
338
|
-
excluded_paths =
|
|
339
|
-
(parsed_file(file).dig("workspace", "excluded_paths") || []) +
|
|
340
|
-
(parsed_file(file).dig("workspace", "exclude") || [])
|
|
350
|
+
excluded_paths = workspace_excluded_paths(workspace)
|
|
341
351
|
|
|
342
352
|
(workspace_paths - excluded_paths).map do |path|
|
|
343
353
|
File.join(path, "Cargo.toml")
|
|
@@ -346,59 +356,40 @@ module Dependabot
|
|
|
346
356
|
|
|
347
357
|
# Check whether a path is required or not. It will not be required if
|
|
348
358
|
# an alternative source (i.e., a git source) is also specified
|
|
349
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
|
350
359
|
# rubocop:disable Metrics/PerceivedComplexity
|
|
351
|
-
# rubocop:disable Metrics/AbcSize
|
|
352
360
|
sig { params(file: Dependabot::DependencyFile, path: String).returns(T::Boolean) }
|
|
353
361
|
def required_path?(file, path)
|
|
354
362
|
# Paths specified in dependency declaration
|
|
355
363
|
Cargo::FileParser::DEPENDENCY_TYPES.each do |type|
|
|
356
|
-
parsed_file(file).fetch(type, {}).each do |_, details|
|
|
357
|
-
|
|
358
|
-
next unless details["path"]
|
|
359
|
-
next unless path == File.join(details["path"], "Cargo.toml")
|
|
360
|
-
|
|
361
|
-
return true if details["git"].nil?
|
|
364
|
+
toml_table_or_empty(parsed_file(file).fetch(type, {})).each do |_, details|
|
|
365
|
+
return true if required_dependency_details?(details, path)
|
|
362
366
|
end
|
|
363
367
|
end
|
|
364
368
|
|
|
365
369
|
# Paths specified for target-specific dependencies
|
|
366
|
-
parsed_file(file).fetch("target", {}).each do |_, t_details|
|
|
370
|
+
toml_table_or_empty(parsed_file(file).fetch("target", {})).each do |_, t_details|
|
|
371
|
+
t_details = toml_table_or_empty(t_details)
|
|
367
372
|
Cargo::FileParser::DEPENDENCY_TYPES.each do |type|
|
|
368
|
-
t_details.fetch(type, {}).each do |_, details|
|
|
369
|
-
|
|
370
|
-
next unless details["path"]
|
|
371
|
-
next unless path == File.join(details["path"], "Cargo.toml")
|
|
372
|
-
|
|
373
|
-
return true if details["git"].nil?
|
|
373
|
+
toml_table_or_empty(t_details.fetch(type, {})).each do |_, details|
|
|
374
|
+
return true if required_dependency_details?(details, path)
|
|
374
375
|
end
|
|
375
376
|
end
|
|
376
377
|
end
|
|
377
378
|
|
|
378
379
|
# Paths specified for workspace-wide dependencies
|
|
379
|
-
workspace = parsed_file(file).fetch("workspace", {})
|
|
380
|
-
workspace.fetch("dependencies", {}).each do |_, details|
|
|
381
|
-
|
|
382
|
-
next unless details["path"]
|
|
383
|
-
next unless path == File.join(details["path"], "Cargo.toml")
|
|
384
|
-
|
|
385
|
-
return true if details["git"].nil?
|
|
380
|
+
workspace = toml_table_or_empty(parsed_file(file).fetch("workspace", {}))
|
|
381
|
+
toml_table_or_empty(workspace.fetch("dependencies", {})).each do |_, details|
|
|
382
|
+
return true if required_dependency_details?(details, path)
|
|
386
383
|
end
|
|
387
384
|
|
|
388
385
|
# Paths specified as replacements
|
|
389
|
-
parsed_file(file).fetch("replace", {}).each do |_, details|
|
|
390
|
-
|
|
391
|
-
next unless details["path"]
|
|
392
|
-
next unless path == File.join(details["path"], "Cargo.toml")
|
|
393
|
-
|
|
394
|
-
return true if details["git"].nil?
|
|
386
|
+
toml_table_or_empty(parsed_file(file).fetch("replace", {})).each do |_, details|
|
|
387
|
+
return true if required_dependency_details?(details, path)
|
|
395
388
|
end
|
|
396
389
|
|
|
397
390
|
false
|
|
398
391
|
end
|
|
399
|
-
# rubocop:enable Metrics/AbcSize
|
|
400
392
|
# rubocop:enable Metrics/PerceivedComplexity
|
|
401
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
|
402
393
|
|
|
403
394
|
sig { params(path: String).returns(T::Array[String]) }
|
|
404
395
|
def expand_workspaces(path)
|
|
@@ -411,13 +402,44 @@ module Dependabot
|
|
|
411
402
|
.select { |filename| File.fnmatch?(path, filename) }
|
|
412
403
|
end
|
|
413
404
|
|
|
414
|
-
sig { params(file: Dependabot::DependencyFile).returns(T::Hash[
|
|
405
|
+
sig { params(file: Dependabot::DependencyFile).returns(T::Hash[String, T.anything]) }
|
|
415
406
|
def parsed_file(file)
|
|
416
407
|
TomlRB.parse(file.content)
|
|
417
408
|
rescue TomlRB::ParseError, TomlRB::ValueOverwriteError
|
|
418
409
|
raise Dependabot::DependencyFileNotParseable, file.path
|
|
419
410
|
end
|
|
420
411
|
|
|
412
|
+
sig { params(workspace: T.nilable(T::Hash[String, T.anything])).returns(T::Array[String]) }
|
|
413
|
+
def workspace_excluded_paths(workspace)
|
|
414
|
+
(T.cast(workspace&.fetch("excluded_paths", nil), T.nilable(T::Array[String])) || []) +
|
|
415
|
+
(T.cast(workspace&.fetch("exclude", nil), T.nilable(T::Array[String])) || [])
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
sig { params(details: T.anything, path: String).returns(T::Boolean) }
|
|
419
|
+
def required_dependency_details?(details, path)
|
|
420
|
+
details = toml_table(details)
|
|
421
|
+
dependency_path = T.cast(details&.fetch("path", nil), T.nilable(String))
|
|
422
|
+
return false unless details && dependency_path
|
|
423
|
+
return false unless path == File.join(dependency_path, "Cargo.toml")
|
|
424
|
+
|
|
425
|
+
T.cast(details["git"], T.nilable(Object)).nil?
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
# Returns the value as a TOML table (Hash) when it is one, otherwise nil.
|
|
429
|
+
# TOML dependency values are polymorphic (e.g. `foo = "1.0"` is a String
|
|
430
|
+
# while `foo = { version = "1.0" }` is a table), so callers must narrow at
|
|
431
|
+
# runtime rather than assert a type with T.cast (which would raise).
|
|
432
|
+
sig { params(value: T.anything).returns(T.nilable(T::Hash[String, T.anything])) }
|
|
433
|
+
def toml_table(value)
|
|
434
|
+
obj = T.cast(value, T.nilable(Object))
|
|
435
|
+
obj.is_a?(Hash) ? obj : nil
|
|
436
|
+
end
|
|
437
|
+
|
|
438
|
+
sig { params(value: T.anything).returns(T::Hash[String, T.anything]) }
|
|
439
|
+
def toml_table_or_empty(value)
|
|
440
|
+
toml_table(value) || {}
|
|
441
|
+
end
|
|
442
|
+
|
|
421
443
|
sig { returns(Dependabot::DependencyFile) }
|
|
422
444
|
def cargo_toml
|
|
423
445
|
@cargo_toml ||= T.let(fetch_file_from_host("Cargo.toml"), T.nilable(Dependabot::DependencyFile))
|
|
@@ -105,9 +105,8 @@ module Dependabot
|
|
|
105
105
|
def check_rust_workspace_root
|
|
106
106
|
cargo_toml = dependency_files.find { |f| f.name == "Cargo.toml" }
|
|
107
107
|
workspace_root = parsed_file(T.must(cargo_toml))
|
|
108
|
-
return unless workspace_root.is_a?(Hash)
|
|
109
108
|
|
|
110
|
-
workspace_config =
|
|
109
|
+
workspace_config = T.cast(toml_table_or_empty(workspace_root["package"])["workspace"], T.nilable(String))
|
|
111
110
|
return unless workspace_config
|
|
112
111
|
|
|
113
112
|
msg = "This project is part of a Rust workspace but is not the " \
|
|
@@ -129,10 +128,10 @@ module Dependabot
|
|
|
129
128
|
|
|
130
129
|
manifest_files.each do |file|
|
|
131
130
|
parsed_content = parsed_file(file)
|
|
132
|
-
next unless parsed_content.is_a?(Hash)
|
|
133
131
|
|
|
134
132
|
DEPENDENCY_TYPES.each do |type|
|
|
135
|
-
parsed_content.fetch(type, {}).each do |name, requirement|
|
|
133
|
+
toml_table_or_empty(parsed_content.fetch(type, {})).each do |name, requirement|
|
|
134
|
+
requirement = dependency_declaration(requirement)
|
|
136
135
|
# Skip workspace-inherited dependencies (similar to pnpm catalog)
|
|
137
136
|
# Only skip if workspace is exactly boolean true
|
|
138
137
|
next if requirement.is_a?(Hash) && requirement["workspace"] == true
|
|
@@ -143,8 +142,10 @@ module Dependabot
|
|
|
143
142
|
dependency_set << build_dependency(name, requirement, type, file)
|
|
144
143
|
end
|
|
145
144
|
|
|
146
|
-
parsed_content.fetch("target", {}).each do |_, t_details|
|
|
147
|
-
t_details
|
|
145
|
+
toml_table_or_empty(parsed_content.fetch("target", {})).each do |_, t_details|
|
|
146
|
+
t_details = toml_table_or_empty(t_details)
|
|
147
|
+
toml_table_or_empty(t_details.fetch(type, {})).each do |name, requirement|
|
|
148
|
+
requirement = dependency_declaration(requirement)
|
|
148
149
|
# Skip workspace-inherited dependencies
|
|
149
150
|
# Only skip if workspace is exactly boolean true
|
|
150
151
|
next if requirement.is_a?(Hash) && requirement["workspace"] == true
|
|
@@ -158,8 +159,9 @@ module Dependabot
|
|
|
158
159
|
end
|
|
159
160
|
end
|
|
160
161
|
|
|
161
|
-
workspace = parsed_content.fetch("workspace", {})
|
|
162
|
-
workspace.fetch("dependencies", {}).each do |name, requirement|
|
|
162
|
+
workspace = toml_table_or_empty(parsed_content.fetch("workspace", {}))
|
|
163
|
+
toml_table_or_empty(workspace.fetch("dependencies", {})).each do |name, requirement|
|
|
164
|
+
requirement = dependency_declaration(requirement)
|
|
163
165
|
next unless name == name_from_declaration(name, requirement)
|
|
164
166
|
next if lockfile && !version_from_lockfile(name, requirement)
|
|
165
167
|
|
|
@@ -202,15 +204,14 @@ module Dependabot
|
|
|
202
204
|
return dependency_set unless lockfile
|
|
203
205
|
|
|
204
206
|
lockfile_content = parsed_file(T.must(lockfile))
|
|
205
|
-
return dependency_set unless lockfile_content.is_a?(Hash)
|
|
206
207
|
|
|
207
|
-
lockfile_content.fetch("package", []).each do |package_details|
|
|
208
|
-
next unless package_details["source"]
|
|
208
|
+
T.cast(lockfile_content.fetch("package", []), T::Array[T::Hash[String, T.anything]]).each do |package_details|
|
|
209
|
+
next unless T.cast(package_details["source"], T.nilable(String))
|
|
209
210
|
|
|
210
211
|
# TODO: This isn't quite right, as it will only give us one
|
|
211
212
|
# version of each dependency (when in fact there are many)
|
|
212
213
|
dependency_set << Dependency.new(
|
|
213
|
-
name: package_details["name"],
|
|
214
|
+
name: T.cast(package_details["name"], String),
|
|
214
215
|
version: version_from_lockfile_details(package_details),
|
|
215
216
|
package_manager: "cargo",
|
|
216
217
|
requirements: []
|
|
@@ -224,10 +225,9 @@ module Dependabot
|
|
|
224
225
|
def patched_dependencies
|
|
225
226
|
root_manifest = manifest_files.find { |f| f.name == "Cargo.toml" }
|
|
226
227
|
parsed_content = parsed_file(T.must(root_manifest))
|
|
227
|
-
return [] unless parsed_content.is_a?(Hash)
|
|
228
228
|
return [] unless parsed_content["patch"]
|
|
229
229
|
|
|
230
|
-
parsed_content["patch"].values.flat_map(
|
|
230
|
+
toml_table_or_empty(parsed_content["patch"]).values.flat_map { |patch| toml_table_or_empty(patch).keys }
|
|
231
231
|
end
|
|
232
232
|
|
|
233
233
|
sig { params(declaration: T.any(String, T::Hash[String, String])).returns(T.nilable(String)) }
|
|
@@ -336,7 +336,10 @@ module Dependabot
|
|
|
336
336
|
# taking precedence over ancestors. Search the package-directory config
|
|
337
337
|
# first, then each ancestor config, returning the first match.
|
|
338
338
|
cargo_config_files.each do |config_file|
|
|
339
|
-
value =
|
|
339
|
+
value = key_name.split(".").reduce(parsed_file(config_file)) do |current, key|
|
|
340
|
+
toml_table_or_empty(current)[key]
|
|
341
|
+
end
|
|
342
|
+
value = T.cast(value, T.nilable(String))
|
|
340
343
|
return value if value
|
|
341
344
|
end
|
|
342
345
|
|
|
@@ -348,29 +351,28 @@ module Dependabot
|
|
|
348
351
|
return unless lockfile
|
|
349
352
|
|
|
350
353
|
lockfile_content = parsed_file(T.must(lockfile))
|
|
351
|
-
return unless lockfile_content.is_a?(Hash)
|
|
352
354
|
|
|
353
355
|
candidate_packages =
|
|
354
|
-
lockfile_content
|
|
355
|
-
|
|
356
|
+
lockfile_packages(lockfile_content)
|
|
357
|
+
.select { |p| package_field(p, "name") == name }
|
|
356
358
|
|
|
357
359
|
if (req = requirement_from_declaration(declaration))
|
|
358
360
|
req = Cargo::Requirement.new(req)
|
|
359
361
|
|
|
360
362
|
candidate_packages =
|
|
361
363
|
candidate_packages
|
|
362
|
-
.select { |p| req.satisfied_by?(version_class.new(p
|
|
364
|
+
.select { |p| req.satisfied_by?(version_class.new(T.must(package_field(p, "version")))) }
|
|
363
365
|
end
|
|
364
366
|
|
|
365
367
|
candidate_packages =
|
|
366
368
|
candidate_packages
|
|
367
369
|
.select do |p|
|
|
368
|
-
git_req?(declaration) ^ !p
|
|
370
|
+
git_req?(declaration) ^ !package_field(p, "source")&.start_with?("git+")
|
|
369
371
|
end
|
|
370
372
|
|
|
371
373
|
package =
|
|
372
374
|
candidate_packages
|
|
373
|
-
.max_by { |p| version_class.new(p
|
|
375
|
+
.max_by { |p| version_class.new(T.must(package_field(p, "version"))) }
|
|
374
376
|
|
|
375
377
|
return unless package
|
|
376
378
|
|
|
@@ -392,11 +394,13 @@ module Dependabot
|
|
|
392
394
|
}
|
|
393
395
|
end
|
|
394
396
|
|
|
395
|
-
sig { params(package_details: T::Hash[String,
|
|
397
|
+
sig { params(package_details: T::Hash[String, T.anything]).returns(String) }
|
|
396
398
|
def version_from_lockfile_details(package_details)
|
|
397
|
-
|
|
399
|
+
source = T.cast(package_details["source"], T.nilable(String))
|
|
400
|
+
version = T.cast(package_details["version"], String)
|
|
401
|
+
return version unless source&.start_with?("git+")
|
|
398
402
|
|
|
399
|
-
T.must(
|
|
403
|
+
T.must(source.split("#").last)
|
|
400
404
|
end
|
|
401
405
|
|
|
402
406
|
sig { override.void }
|
|
@@ -404,14 +408,36 @@ module Dependabot
|
|
|
404
408
|
raise "No Cargo.toml!" unless get_original_file("Cargo.toml")
|
|
405
409
|
end
|
|
406
410
|
|
|
407
|
-
sig { params(file: DependencyFile).returns(T.
|
|
411
|
+
sig { params(file: DependencyFile).returns(T::Hash[String, T.anything]) }
|
|
408
412
|
def parsed_file(file)
|
|
409
|
-
@parsed_file ||= T.let({}, T.nilable(T::Hash[String, T.
|
|
413
|
+
@parsed_file ||= T.let({}, T.nilable(T::Hash[String, T::Hash[String, T.anything]]))
|
|
410
414
|
@parsed_file[file.name] ||= TomlRB.parse(file.content)
|
|
411
415
|
rescue TomlRB::ParseError, TomlRB::ValueOverwriteError
|
|
412
416
|
raise Dependabot::DependencyFileNotParseable, file.path
|
|
413
417
|
end
|
|
414
418
|
|
|
419
|
+
sig { params(lockfile_content: T::Hash[String, T.anything]).returns(T::Array[T::Hash[String, T.anything]]) }
|
|
420
|
+
def lockfile_packages(lockfile_content)
|
|
421
|
+
T.cast(lockfile_content.fetch("package", []), T::Array[T::Hash[String, T.anything]])
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
sig { params(package_details: T::Hash[String, T.anything], field: String).returns(T.nilable(String)) }
|
|
425
|
+
def package_field(package_details, field)
|
|
426
|
+
T.cast(package_details[field], T.nilable(String))
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
sig { params(value: T.anything).returns(T::Hash[String, T.anything]) }
|
|
430
|
+
def toml_table_or_empty(value)
|
|
431
|
+
(obj = T.cast(value, T.nilable(Object))).is_a?(Hash) ? obj : {}
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
sig { params(value: T.anything).returns(T.any(String, T::Hash[String, String])) }
|
|
435
|
+
def dependency_declaration(value)
|
|
436
|
+
return T.cast(value, String) if T.cast(value, T.nilable(Object)).is_a?(String)
|
|
437
|
+
|
|
438
|
+
T.cast(value, T::Hash[String, String])
|
|
439
|
+
end
|
|
440
|
+
|
|
415
441
|
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
416
442
|
def manifest_files
|
|
417
443
|
@manifest_files ||= T.let(
|
|
@@ -392,20 +392,31 @@ module Dependabot
|
|
|
392
392
|
TomlRB.dump(parsed_manifest)
|
|
393
393
|
end
|
|
394
394
|
|
|
395
|
-
sig { params(parsed_manifest: T::Hash[String, T.
|
|
395
|
+
sig { params(parsed_manifest: T::Hash[String, T.anything]).void }
|
|
396
396
|
def pin_target_specific_dependencies!(parsed_manifest)
|
|
397
|
-
parsed_manifest.fetch("target", {}).each do |target, t_details|
|
|
397
|
+
toml_table_or_empty(parsed_manifest.fetch("target", {})).each do |target, t_details|
|
|
398
|
+
t_details = toml_table_or_empty(t_details)
|
|
398
399
|
Cargo::FileParser::DEPENDENCY_TYPES.each do |type|
|
|
399
|
-
t_details.fetch(type, {}).each do |name, requirement|
|
|
400
|
+
toml_table_or_empty(t_details.fetch(type, {})).each do |name, requirement|
|
|
400
401
|
next unless name == dependency.name
|
|
401
402
|
|
|
402
403
|
updated_req = "=#{dependency.version}"
|
|
403
404
|
|
|
404
|
-
if requirement.is_a?(Hash)
|
|
405
|
-
|
|
405
|
+
if T.cast(requirement, T.nilable(Object)).is_a?(Hash)
|
|
406
|
+
toml_table_or_empty(
|
|
407
|
+
toml_table_or_empty(
|
|
408
|
+
toml_table_or_empty(
|
|
409
|
+
toml_table_or_empty(parsed_manifest["target"])[target]
|
|
410
|
+
)[type]
|
|
411
|
+
)[name]
|
|
412
|
+
)["version"] =
|
|
406
413
|
updated_req
|
|
407
414
|
else
|
|
408
|
-
|
|
415
|
+
toml_table_or_empty(
|
|
416
|
+
toml_table_or_empty(
|
|
417
|
+
toml_table_or_empty(parsed_manifest["target"])[target]
|
|
418
|
+
)[type]
|
|
419
|
+
)[name] = updated_req
|
|
409
420
|
end
|
|
410
421
|
end
|
|
411
422
|
end
|
|
@@ -498,6 +509,12 @@ module Dependabot
|
|
|
498
509
|
lockfile_content
|
|
499
510
|
end
|
|
500
511
|
|
|
512
|
+
sig { params(value: T.anything).returns(T::Hash[String, T.anything]) }
|
|
513
|
+
def toml_table_or_empty(value)
|
|
514
|
+
obj = T.cast(value, T.nilable(Object))
|
|
515
|
+
obj.is_a?(Hash) ? obj : {}
|
|
516
|
+
end
|
|
517
|
+
|
|
501
518
|
sig { returns(String) }
|
|
502
519
|
def dummy_app_content
|
|
503
520
|
%{fn main() {\nprintln!("Hello, world!");\n}}
|
|
@@ -19,7 +19,7 @@ module Dependabot
|
|
|
19
19
|
sig { params(dependency: Dependabot::Dependency, credentials: T::Array[Dependabot::Credential]).void }
|
|
20
20
|
def initialize(dependency:, credentials:)
|
|
21
21
|
super
|
|
22
|
-
@crates_listing = T.let(nil, T.nilable(T::Hash[String, T.
|
|
22
|
+
@crates_listing = T.let(nil, T.nilable(T::Hash[String, T.anything]))
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
private
|
|
@@ -43,7 +43,10 @@ module Dependabot
|
|
|
43
43
|
def find_source_from_crates_listing
|
|
44
44
|
potential_source_urls =
|
|
45
45
|
SOURCE_KEYS
|
|
46
|
-
.filter_map
|
|
46
|
+
.filter_map do |key|
|
|
47
|
+
crate = T.cast(T.must(crates_listing)["crate"], T.nilable(T::Hash[String, T.anything]))
|
|
48
|
+
T.cast(crate&.fetch(key, nil), T.nilable(String))
|
|
49
|
+
end
|
|
47
50
|
|
|
48
51
|
source_url = potential_source_urls.find { |url| Source.from_url(url) }
|
|
49
52
|
Source.from_url(source_url)
|
|
@@ -51,18 +54,25 @@ module Dependabot
|
|
|
51
54
|
|
|
52
55
|
sig { returns(T.nilable(Dependabot::Source)) }
|
|
53
56
|
def find_source_from_git_url
|
|
54
|
-
info =
|
|
57
|
+
info = T.cast(
|
|
58
|
+
dependency.requirements.filter_map { |r| r[:source] }.first,
|
|
59
|
+
T.nilable(T::Hash[T.any(String, Symbol), T.anything])
|
|
60
|
+
)
|
|
61
|
+
return unless info
|
|
55
62
|
|
|
56
|
-
url = info[:url] || info
|
|
57
|
-
Source.from_url(url)
|
|
63
|
+
url = info[:url] || info["url"]
|
|
64
|
+
Source.from_url(T.cast(url, T.nilable(String)))
|
|
58
65
|
end
|
|
59
66
|
|
|
60
|
-
sig { returns(T.nilable(T::Hash[String, T.
|
|
67
|
+
sig { returns(T.nilable(T::Hash[String, T.anything])) }
|
|
61
68
|
def crates_listing
|
|
62
69
|
return @crates_listing unless @crates_listing.nil?
|
|
63
70
|
|
|
64
|
-
info =
|
|
65
|
-
|
|
71
|
+
info = T.cast(
|
|
72
|
+
dependency.requirements.filter_map { |r| r[:source] }.first,
|
|
73
|
+
T.nilable(T::Hash[T.any(String, Symbol), T.anything])
|
|
74
|
+
)
|
|
75
|
+
index = T.cast((info && (info[:index] || info["index"])) || CRATES_IO_API, String)
|
|
66
76
|
hdrs = build_headers(index, info)
|
|
67
77
|
|
|
68
78
|
url = metadata_fetch_url(dependency, index)
|
|
@@ -71,14 +81,18 @@ module Dependabot
|
|
|
71
81
|
@crates_listing = parse_response(response, index)
|
|
72
82
|
end
|
|
73
83
|
|
|
74
|
-
sig
|
|
84
|
+
sig do
|
|
85
|
+
params(index: String, info: T.nilable(T::Hash[T.any(String, Symbol), T.anything]))
|
|
86
|
+
.returns(T::Hash[String, String])
|
|
87
|
+
end
|
|
75
88
|
def build_headers(index, info)
|
|
76
89
|
hdrs = { "User-Agent" => "Dependabot (dependabot.com)" }
|
|
77
90
|
return hdrs if index == CRATES_IO_API
|
|
78
91
|
|
|
79
92
|
return hdrs if info.nil?
|
|
80
93
|
|
|
81
|
-
|
|
94
|
+
registry_name = T.cast(info["name"] || info[:name], T.nilable(String))
|
|
95
|
+
credentials.find { |cred| cred["type"] == "cargo_registry" && cred["registry"] == registry_name }&.tap do |cred|
|
|
82
96
|
hdrs["Authorization"] = "Token #{cred['token']}"
|
|
83
97
|
end
|
|
84
98
|
|
|
@@ -94,7 +108,7 @@ module Dependabot
|
|
|
94
108
|
)
|
|
95
109
|
end
|
|
96
110
|
|
|
97
|
-
sig { params(response: Excon::Response, index: String).returns(T::Hash[String, T.
|
|
111
|
+
sig { params(response: Excon::Response, index: String).returns(T::Hash[String, T.anything]) }
|
|
98
112
|
def parse_response(response, index)
|
|
99
113
|
if index.start_with?("sparse+")
|
|
100
114
|
parsed_response = response.body.lines.map { |line| JSON.parse(line) }
|
|
@@ -42,23 +42,25 @@ module Dependabot
|
|
|
42
42
|
sig { returns(Dependabot::Dependency) }
|
|
43
43
|
attr_reader :dependency
|
|
44
44
|
|
|
45
|
-
sig { returns(T::Array[
|
|
45
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
46
46
|
attr_reader :dependency_files
|
|
47
47
|
|
|
48
|
-
sig { returns(T::Array[
|
|
48
|
+
sig { returns(T::Array[Dependabot::Credential]) }
|
|
49
49
|
attr_reader :credentials
|
|
50
50
|
|
|
51
51
|
sig do
|
|
52
52
|
returns(T.nilable(Dependabot::Package::PackageDetails))
|
|
53
53
|
end
|
|
54
54
|
def fetch
|
|
55
|
-
|
|
55
|
+
releases = T.cast(crates_listing.fetch("versions", []), T::Array[T::Hash[String, T.anything]])
|
|
56
|
+
package_releases = releases.reject { |v| v["yanked"] }.map do |release|
|
|
57
|
+
created_at = T.cast(release["created_at"], T.nilable(String))
|
|
56
58
|
package_release(
|
|
57
|
-
version: release["num"] || release["vers"],
|
|
58
|
-
released_at:
|
|
59
|
-
downloads: release["downloads"],
|
|
60
|
-
url: "#{CRATES_IO_API}/#{release['dl_path']}",
|
|
61
|
-
rust_version: release["rust"]
|
|
59
|
+
version: T.cast(release["num"], T.nilable(String)) || T.cast(release["vers"], String),
|
|
60
|
+
released_at: created_at ? Time.parse(created_at) : nil,
|
|
61
|
+
downloads: T.cast(release["downloads"], T.nilable(Integer)),
|
|
62
|
+
url: "#{CRATES_IO_API}/#{T.cast(release['dl_path'], T.nilable(String))}",
|
|
63
|
+
rust_version: T.cast(release["rust"], T.nilable(String))
|
|
62
64
|
)
|
|
63
65
|
end
|
|
64
66
|
|
|
@@ -68,7 +70,7 @@ module Dependabot
|
|
|
68
70
|
private
|
|
69
71
|
|
|
70
72
|
sig do
|
|
71
|
-
returns(T.
|
|
73
|
+
returns(T::Hash[String, T.anything])
|
|
72
74
|
end
|
|
73
75
|
def crates_listing
|
|
74
76
|
return @crates_listing unless @crates_listing.nil?
|
|
@@ -86,41 +88,45 @@ module Dependabot
|
|
|
86
88
|
response = fetch_response(url, hdrs)
|
|
87
89
|
return {} if response.status == 404
|
|
88
90
|
|
|
89
|
-
@crates_listing = T.let(parse_response(response, index), T.nilable(T::Hash[
|
|
91
|
+
@crates_listing = T.let(parse_response(response, index), T.nilable(T::Hash[String, T.anything]))
|
|
90
92
|
|
|
91
93
|
Dependabot.logger.info("Fetched metadata for #{dependency.name} from #{index} successfully")
|
|
92
94
|
|
|
93
|
-
@crates_listing
|
|
95
|
+
T.must(@crates_listing)
|
|
94
96
|
end
|
|
95
97
|
|
|
96
|
-
sig { returns(T.nilable(T::Hash[T.
|
|
98
|
+
sig { returns(T.nilable(T::Hash[T.any(String, Symbol), T.anything])) }
|
|
97
99
|
def fetch_dependency_info
|
|
98
|
-
|
|
100
|
+
T.cast(
|
|
101
|
+
dependency.requirements.filter_map { |r| r[:source] }.first,
|
|
102
|
+
T.nilable(T::Hash[T.any(String, Symbol), T.anything])
|
|
103
|
+
)
|
|
99
104
|
end
|
|
100
105
|
|
|
101
|
-
sig { params(info: T.
|
|
106
|
+
sig { params(info: T.nilable(T::Hash[T.any(String, Symbol), T.anything])).returns(String) }
|
|
102
107
|
def fetch_index(info)
|
|
103
|
-
(info && info[:index]) || CRATES_IO_API
|
|
108
|
+
T.cast((info && (info[:index] || info["index"])) || CRATES_IO_API, String)
|
|
104
109
|
end
|
|
105
110
|
|
|
106
|
-
sig { returns(T::Hash[
|
|
111
|
+
sig { returns(T::Hash[String, String]) }
|
|
107
112
|
def default_headers
|
|
108
113
|
{ "User-Agent" => "Dependabot (dependabot.com)" }
|
|
109
114
|
end
|
|
110
115
|
|
|
111
|
-
sig { params(info: T.
|
|
116
|
+
sig { params(info: T.nilable(T::Hash[T.any(String, Symbol), T.anything])).returns(T::Hash[String, String]) }
|
|
112
117
|
def auth_headers(info)
|
|
118
|
+
registry_name = T.cast(info && (info[:name] || info["name"]), T.nilable(String))
|
|
113
119
|
registry_creds = credentials.find do |cred|
|
|
114
|
-
cred["type"] == "cargo_registry" && cred["registry"] ==
|
|
120
|
+
cred["type"] == "cargo_registry" && cred["registry"] == registry_name
|
|
115
121
|
end
|
|
116
122
|
|
|
117
|
-
return {}
|
|
123
|
+
return {} unless registry_creds
|
|
118
124
|
|
|
119
125
|
token = registry_creds["token"] || "placeholder_token"
|
|
120
126
|
{ "Authorization" => token }
|
|
121
127
|
end
|
|
122
128
|
|
|
123
|
-
sig { params(url: String, headers: T
|
|
129
|
+
sig { params(url: String, headers: T::Hash[String, String]).returns(Excon::Response) }
|
|
124
130
|
def fetch_response(url, headers)
|
|
125
131
|
Excon.get(
|
|
126
132
|
url,
|
|
@@ -129,7 +135,7 @@ module Dependabot
|
|
|
129
135
|
)
|
|
130
136
|
end
|
|
131
137
|
|
|
132
|
-
sig { params(response: Excon::Response, index:
|
|
138
|
+
sig { params(response: Excon::Response, index: String).returns(T::Hash[String, T.anything]) }
|
|
133
139
|
def parse_response(response, index)
|
|
134
140
|
if index.start_with?("sparse+")
|
|
135
141
|
parsed_response = response.body.lines
|
|
@@ -148,7 +154,7 @@ module Dependabot
|
|
|
148
154
|
end
|
|
149
155
|
end
|
|
150
156
|
|
|
151
|
-
sig { params(dependency:
|
|
157
|
+
sig { params(dependency: Dependabot::Dependency, index: String).returns(String) }
|
|
152
158
|
def metadata_fetch_url(dependency, index)
|
|
153
159
|
return "#{index}/#{dependency.name}" if index == CRATES_IO_API
|
|
154
160
|
|
|
@@ -123,9 +123,9 @@ module Dependabot
|
|
|
123
123
|
TomlRB.dump(parsed_manifest)
|
|
124
124
|
end
|
|
125
125
|
|
|
126
|
-
sig { params(parsed_manifest: T::Hash[String, T.
|
|
126
|
+
sig { params(parsed_manifest: T::Hash[String, T.anything], filename: String).void }
|
|
127
127
|
def replace_req_on_target_specific_deps!(parsed_manifest, filename)
|
|
128
|
-
parsed_manifest.fetch("target", {}).each do |target, _|
|
|
128
|
+
toml_table_or_empty(parsed_manifest.fetch("target", {})).each do |target, _|
|
|
129
129
|
Cargo::FileParser::DEPENDENCY_TYPES.each do |type|
|
|
130
130
|
dependency_names = dependency_names_for_type_and_target(
|
|
131
131
|
parsed_manifest,
|
|
@@ -134,35 +134,39 @@ module Dependabot
|
|
|
134
134
|
)
|
|
135
135
|
|
|
136
136
|
dependency_names.each do |name|
|
|
137
|
-
req = parsed_manifest
|
|
137
|
+
req = target_dependency_declaration(parsed_manifest, target, type, name)
|
|
138
138
|
|
|
139
139
|
updated_req = temporary_requirement_for_resolution(filename)
|
|
140
140
|
|
|
141
141
|
if req.is_a?(Hash)
|
|
142
|
-
parsed_manifest
|
|
143
|
-
updated_req
|
|
142
|
+
target_dependency_table(parsed_manifest, target, type, name)["version"] = updated_req
|
|
144
143
|
else
|
|
145
|
-
parsed_manifest
|
|
144
|
+
target_dependency_type_table(parsed_manifest, target, type)[name] = updated_req
|
|
146
145
|
end
|
|
147
146
|
end
|
|
148
147
|
end
|
|
149
148
|
end
|
|
150
149
|
end
|
|
151
150
|
|
|
152
|
-
sig { params(parsed_manifest: T::Hash[String, T.
|
|
151
|
+
sig { params(parsed_manifest: T::Hash[String, T.anything], filename: String).void }
|
|
153
152
|
def replace_req_on_workspace_deps!(parsed_manifest, filename)
|
|
154
|
-
workspace = parsed_manifest.fetch("workspace", {})
|
|
155
|
-
workspace_deps = workspace.fetch("dependencies", {})
|
|
153
|
+
workspace = toml_table_or_empty(parsed_manifest.fetch("workspace", {}))
|
|
154
|
+
workspace_deps = toml_table_or_empty(workspace.fetch("dependencies", {}))
|
|
156
155
|
|
|
157
156
|
workspace_deps.each do |name, req|
|
|
157
|
+
req = dependency_declaration(req)
|
|
158
158
|
next unless dependency.name == name_from_declaration(name, req)
|
|
159
159
|
|
|
160
160
|
updated_req = temporary_requirement_for_resolution(filename)
|
|
161
161
|
|
|
162
162
|
if req.is_a?(Hash)
|
|
163
|
-
|
|
163
|
+
toml_table_or_empty(
|
|
164
|
+
toml_table_or_empty(
|
|
165
|
+
toml_table_or_empty(parsed_manifest["workspace"])["dependencies"]
|
|
166
|
+
)[name]
|
|
167
|
+
)["version"] = updated_req
|
|
164
168
|
else
|
|
165
|
-
parsed_manifest["workspace"]["dependencies"][name] = updated_req
|
|
169
|
+
toml_table_or_empty(toml_table_or_empty(parsed_manifest["workspace"])["dependencies"])[name] = updated_req
|
|
166
170
|
end
|
|
167
171
|
end
|
|
168
172
|
end
|
|
@@ -173,13 +177,14 @@ module Dependabot
|
|
|
173
177
|
|
|
174
178
|
Cargo::FileParser::DEPENDENCY_TYPES.each do |type|
|
|
175
179
|
dependency_names_for_type(parsed_manifest, type).each do |name|
|
|
176
|
-
req = parsed_manifest.dig(type, name)
|
|
180
|
+
req = T.cast(parsed_manifest.dig(type, name), T.any(String, T::Hash[String, T.anything]))
|
|
177
181
|
next unless req.is_a?(Hash)
|
|
178
182
|
next unless [req["tag"], req["rev"]].compact.uniq.one?
|
|
179
183
|
|
|
180
|
-
parsed_manifest[type][name]
|
|
184
|
+
dependency_options = toml_table_or_empty(toml_table_or_empty(parsed_manifest[type])[name])
|
|
185
|
+
dependency_options["tag"] = replacement_git_pin if req["tag"]
|
|
181
186
|
|
|
182
|
-
|
|
187
|
+
dependency_options["rev"] = replacement_git_pin if req["rev"]
|
|
183
188
|
end
|
|
184
189
|
end
|
|
185
190
|
|
|
@@ -188,9 +193,9 @@ module Dependabot
|
|
|
188
193
|
TomlRB.dump(parsed_manifest)
|
|
189
194
|
end
|
|
190
195
|
|
|
191
|
-
sig { params(parsed_manifest: T::Hash[String, T.
|
|
196
|
+
sig { params(parsed_manifest: T::Hash[String, T.anything]).void }
|
|
192
197
|
def replace_git_pin_on_target_specific_deps!(parsed_manifest)
|
|
193
|
-
parsed_manifest.fetch("target", {}).each do |target, _|
|
|
198
|
+
toml_table_or_empty(parsed_manifest.fetch("target", {})).each do |target, _|
|
|
194
199
|
Cargo::FileParser::DEPENDENCY_TYPES.each do |type|
|
|
195
200
|
dependency_names = dependency_names_for_type_and_target(
|
|
196
201
|
parsed_manifest,
|
|
@@ -199,19 +204,15 @@ module Dependabot
|
|
|
199
204
|
)
|
|
200
205
|
|
|
201
206
|
dependency_names.each do |name|
|
|
202
|
-
req = parsed_manifest
|
|
207
|
+
req = target_dependency_declaration(parsed_manifest, target, type, name)
|
|
203
208
|
next unless req.is_a?(Hash)
|
|
204
209
|
next unless [req["tag"], req["rev"]].compact.uniq.one?
|
|
205
210
|
|
|
206
|
-
if req["tag"]
|
|
207
|
-
parsed_manifest["target"][target][type][name]["tag"] =
|
|
208
|
-
replacement_git_pin
|
|
209
|
-
end
|
|
211
|
+
target_dependency_table(parsed_manifest, target, type, name)["tag"] = replacement_git_pin if req["tag"]
|
|
210
212
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
end
|
|
213
|
+
next unless req["rev"]
|
|
214
|
+
|
|
215
|
+
target_dependency_table(parsed_manifest, target, type, name)["rev"] = replacement_git_pin
|
|
215
216
|
end
|
|
216
217
|
end
|
|
217
218
|
end
|
|
@@ -222,12 +223,12 @@ module Dependabot
|
|
|
222
223
|
parsed_manifest = TomlRB.parse(content)
|
|
223
224
|
|
|
224
225
|
Cargo::FileParser::DEPENDENCY_TYPES.each do |type|
|
|
225
|
-
(parsed_manifest[type]
|
|
226
|
-
|
|
227
|
-
|
|
226
|
+
toml_table_or_empty(parsed_manifest[type]).each do |_, details|
|
|
227
|
+
details = toml_table_or_empty(details)
|
|
228
|
+
git = T.cast(details.fetch("git", nil), T.nilable(String))
|
|
229
|
+
next unless git
|
|
228
230
|
|
|
229
|
-
details["git"] =
|
|
230
|
-
.gsub(%r{ssh://git@(.*?)/}, 'https://\1/')
|
|
231
|
+
details["git"] = git.gsub(%r{ssh://git@(.*?)/}, 'https://\1/')
|
|
231
232
|
end
|
|
232
233
|
end
|
|
233
234
|
|
|
@@ -283,17 +284,29 @@ module Dependabot
|
|
|
283
284
|
def git_dependency_version
|
|
284
285
|
return unless lockfile
|
|
285
286
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
287
|
+
version = dependency.version
|
|
288
|
+
return unless version
|
|
289
|
+
|
|
290
|
+
packages = T.cast(
|
|
291
|
+
TomlRB.parse(T.must(lockfile).content).fetch("package", []),
|
|
292
|
+
T::Array[T::Hash[String, T.anything]]
|
|
293
|
+
)
|
|
294
|
+
package = packages
|
|
295
|
+
.select { |p| T.cast(p["name"], T.nilable(String)) == dependency.name }
|
|
296
|
+
.find do |p|
|
|
297
|
+
source = T.cast(p["source"], T.nilable(String))
|
|
298
|
+
source&.end_with?(version)
|
|
299
|
+
end
|
|
300
|
+
return unless package
|
|
301
|
+
|
|
302
|
+
T.cast(package.fetch("version"), String)
|
|
291
303
|
end
|
|
292
304
|
|
|
293
|
-
sig { params(parsed_manifest: T::Hash[String, T.
|
|
305
|
+
sig { params(parsed_manifest: T::Hash[String, T.anything], type: String).returns(T::Array[String]) }
|
|
294
306
|
def dependency_names_for_type(parsed_manifest, type)
|
|
295
307
|
names = []
|
|
296
|
-
parsed_manifest.fetch(type, {}).each do |nm, req|
|
|
308
|
+
toml_table_or_empty(parsed_manifest.fetch(type, {})).each do |nm, req|
|
|
309
|
+
req = dependency_declaration(req)
|
|
297
310
|
next unless dependency.name == name_from_declaration(nm, req)
|
|
298
311
|
|
|
299
312
|
names << nm
|
|
@@ -302,11 +315,13 @@ module Dependabot
|
|
|
302
315
|
end
|
|
303
316
|
|
|
304
317
|
sig do
|
|
305
|
-
params(parsed_manifest: T::Hash[String, T.
|
|
318
|
+
params(parsed_manifest: T::Hash[String, T.anything], type: String, target: String).returns(T::Array[String])
|
|
306
319
|
end
|
|
307
320
|
def dependency_names_for_type_and_target(parsed_manifest, type, target)
|
|
308
321
|
names = []
|
|
309
|
-
(parsed_manifest
|
|
322
|
+
target_details = toml_table_or_empty(toml_table_or_empty(parsed_manifest["target"])[target])
|
|
323
|
+
toml_table_or_empty(target_details[type]).each do |nm, req|
|
|
324
|
+
req = dependency_declaration(req)
|
|
310
325
|
next unless dependency.name == name_from_declaration(nm, req)
|
|
311
326
|
|
|
312
327
|
names << nm
|
|
@@ -314,13 +329,63 @@ module Dependabot
|
|
|
314
329
|
names
|
|
315
330
|
end
|
|
316
331
|
|
|
317
|
-
sig { params(name: String, declaration: T.
|
|
332
|
+
sig { params(name: String, declaration: T.any(String, T::Hash[String, T.anything])).returns(String) }
|
|
318
333
|
def name_from_declaration(name, declaration)
|
|
319
334
|
return name if declaration.is_a?(String)
|
|
320
335
|
|
|
321
|
-
|
|
336
|
+
T.cast(declaration.fetch("package", name), String)
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
sig do
|
|
340
|
+
params(
|
|
341
|
+
parsed_manifest: T::Hash[String, T.anything],
|
|
342
|
+
target: String,
|
|
343
|
+
type: String
|
|
344
|
+
).returns(T::Hash[String, T.anything])
|
|
345
|
+
end
|
|
346
|
+
def target_dependency_type_table(parsed_manifest, target, type)
|
|
347
|
+
target_details = toml_table_or_empty(toml_table_or_empty(parsed_manifest["target"])[target])
|
|
348
|
+
toml_table_or_empty(target_details[type])
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
sig do
|
|
352
|
+
params(
|
|
353
|
+
parsed_manifest: T::Hash[String, T.anything],
|
|
354
|
+
target: String,
|
|
355
|
+
type: String,
|
|
356
|
+
name: String
|
|
357
|
+
).returns(T.any(String, T::Hash[String, T.anything]))
|
|
358
|
+
end
|
|
359
|
+
def target_dependency_declaration(parsed_manifest, target, type, name)
|
|
360
|
+
T.cast(
|
|
361
|
+
target_dependency_type_table(parsed_manifest, target, type)[name],
|
|
362
|
+
T.any(String, T::Hash[String, T.anything])
|
|
363
|
+
)
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
sig do
|
|
367
|
+
params(
|
|
368
|
+
parsed_manifest: T::Hash[String, T.anything],
|
|
369
|
+
target: String,
|
|
370
|
+
type: String,
|
|
371
|
+
name: String
|
|
372
|
+
).returns(T::Hash[String, T.anything])
|
|
373
|
+
end
|
|
374
|
+
def target_dependency_table(parsed_manifest, target, type, name)
|
|
375
|
+
toml_table_or_empty(target_dependency_type_table(parsed_manifest, target, type)[name])
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
sig { params(value: T.anything).returns(T::Hash[String, T.anything]) }
|
|
379
|
+
def toml_table_or_empty(value)
|
|
380
|
+
obj = T.cast(value, T.nilable(Object))
|
|
381
|
+
obj.is_a?(Hash) ? obj : {}
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
sig { params(value: T.anything).returns(T.any(String, T::Hash[String, T.anything])) }
|
|
385
|
+
def dependency_declaration(value)
|
|
386
|
+
return T.cast(value, String) if T.cast(value, T.nilable(Object)).is_a?(String)
|
|
322
387
|
|
|
323
|
-
|
|
388
|
+
T.cast(value, T::Hash[String, T.anything])
|
|
324
389
|
end
|
|
325
390
|
|
|
326
391
|
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
@@ -36,7 +36,7 @@ module Dependabot
|
|
|
36
36
|
sig do
|
|
37
37
|
params(
|
|
38
38
|
requirements: T::Array[Dependabot::DependencyRequirement],
|
|
39
|
-
updated_source: T.nilable(T::Hash[T.any(String, Symbol), T.
|
|
39
|
+
updated_source: T.nilable(T::Hash[T.any(String, Symbol), T.anything]),
|
|
40
40
|
update_strategy: Dependabot::RequirementsUpdateStrategy,
|
|
41
41
|
target_version: T.nilable(T.any(String, Gem::Version))
|
|
42
42
|
).void
|
|
@@ -51,7 +51,7 @@ module Dependabot
|
|
|
51
51
|
requirements.map { |req| Dependabot::DependencyRequirement.create(req) },
|
|
52
52
|
T::Array[Dependabot::DependencyRequirement]
|
|
53
53
|
)
|
|
54
|
-
@updated_source = T.let(updated_source, T.nilable(T::Hash[T.any(String, Symbol), T.
|
|
54
|
+
@updated_source = T.let(updated_source, T.nilable(T::Hash[T.any(String, Symbol), T.anything]))
|
|
55
55
|
@update_strategy = T.let(update_strategy, Dependabot::RequirementsUpdateStrategy)
|
|
56
56
|
|
|
57
57
|
check_update_strategy
|
|
@@ -87,7 +87,7 @@ module Dependabot
|
|
|
87
87
|
sig { returns(T::Array[Dependabot::DependencyRequirement]) }
|
|
88
88
|
attr_reader :requirements
|
|
89
89
|
|
|
90
|
-
sig { returns(T.nilable(T::Hash[T.any(String, Symbol), T.
|
|
90
|
+
sig { returns(T.nilable(T::Hash[T.any(String, Symbol), T.anything])) }
|
|
91
91
|
attr_reader :updated_source
|
|
92
92
|
|
|
93
93
|
sig { returns(Dependabot::RequirementsUpdateStrategy) }
|
|
@@ -311,7 +311,7 @@ module Dependabot
|
|
|
311
311
|
latest_resolvable_version
|
|
312
312
|
end
|
|
313
313
|
|
|
314
|
-
sig { returns(T.nilable(T::Hash[T.any(String, Symbol), T.
|
|
314
|
+
sig { returns(T.nilable(T::Hash[T.any(String, Symbol), T.anything])) }
|
|
315
315
|
def updated_source
|
|
316
316
|
# Never need to update source, unless a git_dependency
|
|
317
317
|
return dependency_source_details unless git_dependency?
|
|
@@ -327,7 +327,7 @@ module Dependabot
|
|
|
327
327
|
dependency_source_details
|
|
328
328
|
end
|
|
329
329
|
|
|
330
|
-
sig { returns(T.nilable(T::Hash[T.any(String, Symbol), T.
|
|
330
|
+
sig { returns(T.nilable(T::Hash[T.any(String, Symbol), T.anything])) }
|
|
331
331
|
def dependency_source_details
|
|
332
332
|
dependency.source_details
|
|
333
333
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dependabot-cargo
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.386.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dependabot
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - '='
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 0.
|
|
18
|
+
version: 0.386.0
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - '='
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 0.
|
|
25
|
+
version: 0.386.0
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: debug
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -266,7 +266,7 @@ licenses:
|
|
|
266
266
|
- MIT
|
|
267
267
|
metadata:
|
|
268
268
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
|
269
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
|
269
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.386.0
|
|
270
270
|
rdoc_options: []
|
|
271
271
|
require_paths:
|
|
272
272
|
- lib
|