dependabot-cargo 0.325.1 → 0.326.1
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
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 649b2e05f391db12ac0c0a2b684c1307d08c0f70d63cda70fbcf38b684b0ced6
|
|
4
|
+
data.tar.gz: 2d99e07be08c7d16413c23a93fa05475aa8958fb32690e8685a9ffa5cd2fc3a0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7edc7ef35e787abbc520058bf77514c0ac6837cee2f1bfafe02cac7e5b698d58459f22a7a01f02d5ea00d5515a7506bdf6e64103a2675feac0d4f4841a1d7787
|
|
7
|
+
data.tar.gz: 871c65564b60b9d5a3a29a61ec56b86a5b8ddb302b6ac5db11e965fc6eb75272793bb67898ed8fe823ffbf10ff7c9f3fb3dbe361c340cb372145af65becf6f1f
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strict
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "toml-rb"
|
|
@@ -25,6 +25,7 @@ module Dependabot
|
|
|
25
25
|
DEPENDENCY_TYPES =
|
|
26
26
|
%w(dependencies dev-dependencies build-dependencies).freeze
|
|
27
27
|
|
|
28
|
+
sig { override.returns(T::Array[Dependabot::Dependency]) }
|
|
28
29
|
def parse
|
|
29
30
|
check_rust_workspace_root
|
|
30
31
|
|
|
@@ -88,10 +89,14 @@ module Dependabot
|
|
|
88
89
|
end, T.nilable(String))
|
|
89
90
|
end
|
|
90
91
|
|
|
92
|
+
sig { void }
|
|
91
93
|
def check_rust_workspace_root
|
|
92
94
|
cargo_toml = dependency_files.find { |f| f.name == "Cargo.toml" }
|
|
93
|
-
workspace_root = parsed_file(
|
|
94
|
-
return unless workspace_root
|
|
95
|
+
workspace_root = parsed_file(T.must(cargo_toml))
|
|
96
|
+
return unless workspace_root.is_a?(Hash)
|
|
97
|
+
|
|
98
|
+
workspace_config = workspace_root.dig("package", "workspace")
|
|
99
|
+
return unless workspace_config
|
|
95
100
|
|
|
96
101
|
msg = "This project is part of a Rust workspace but is not the " \
|
|
97
102
|
"workspace root." \
|
|
@@ -106,20 +111,32 @@ module Dependabot
|
|
|
106
111
|
# rubocop:disable Metrics/AbcSize
|
|
107
112
|
# rubocop:disable Metrics/CyclomaticComplexity
|
|
108
113
|
# rubocop:disable Metrics/PerceivedComplexity
|
|
114
|
+
sig { returns(DependencySet) }
|
|
109
115
|
def manifest_dependencies
|
|
110
116
|
dependency_set = DependencySet.new
|
|
111
117
|
|
|
112
118
|
manifest_files.each do |file|
|
|
119
|
+
parsed_content = parsed_file(file)
|
|
120
|
+
next unless parsed_content.is_a?(Hash)
|
|
121
|
+
|
|
113
122
|
DEPENDENCY_TYPES.each do |type|
|
|
114
|
-
|
|
123
|
+
parsed_content.fetch(type, {}).each do |name, requirement|
|
|
124
|
+
# Skip workspace-inherited dependencies (similar to pnpm catalog)
|
|
125
|
+
# Only skip if workspace is exactly boolean true
|
|
126
|
+
next if requirement.is_a?(Hash) && requirement["workspace"] == true
|
|
127
|
+
|
|
115
128
|
next unless name == name_from_declaration(name, requirement)
|
|
116
129
|
next if lockfile && !version_from_lockfile(name, requirement)
|
|
117
130
|
|
|
118
131
|
dependency_set << build_dependency(name, requirement, type, file)
|
|
119
132
|
end
|
|
120
133
|
|
|
121
|
-
|
|
134
|
+
parsed_content.fetch("target", {}).each do |_, t_details|
|
|
122
135
|
t_details.fetch(type, {}).each do |name, requirement|
|
|
136
|
+
# Skip workspace-inherited dependencies
|
|
137
|
+
# Only skip if workspace is exactly boolean true
|
|
138
|
+
next if requirement.is_a?(Hash) && requirement["workspace"] == true
|
|
139
|
+
|
|
123
140
|
next unless name == name_from_declaration(name, requirement)
|
|
124
141
|
next if lockfile && !version_from_lockfile(name, requirement)
|
|
125
142
|
|
|
@@ -129,7 +146,7 @@ module Dependabot
|
|
|
129
146
|
end
|
|
130
147
|
end
|
|
131
148
|
|
|
132
|
-
workspace =
|
|
149
|
+
workspace = parsed_content.fetch("workspace", {})
|
|
133
150
|
workspace.fetch("dependencies", {}).each do |name, requirement|
|
|
134
151
|
next unless name == name_from_declaration(name, requirement)
|
|
135
152
|
next if lockfile && !version_from_lockfile(name, requirement)
|
|
@@ -145,6 +162,10 @@ module Dependabot
|
|
|
145
162
|
# rubocop:enable Metrics/CyclomaticComplexity
|
|
146
163
|
# rubocop:enable Metrics/PerceivedComplexity
|
|
147
164
|
|
|
165
|
+
sig do
|
|
166
|
+
params(name: String, requirement: T.any(String, T::Hash[String, String]), type: String,
|
|
167
|
+
file: Dependabot::DependencyFile).returns(Dependency)
|
|
168
|
+
end
|
|
148
169
|
def build_dependency(name, requirement, type, file)
|
|
149
170
|
Dependency.new(
|
|
150
171
|
name: name,
|
|
@@ -159,11 +180,15 @@ module Dependabot
|
|
|
159
180
|
)
|
|
160
181
|
end
|
|
161
182
|
|
|
183
|
+
sig { returns(DependencySet) }
|
|
162
184
|
def lockfile_dependencies
|
|
163
185
|
dependency_set = DependencySet.new
|
|
164
186
|
return dependency_set unless lockfile
|
|
165
187
|
|
|
166
|
-
parsed_file(
|
|
188
|
+
lockfile_content = parsed_file(T.must(lockfile))
|
|
189
|
+
return dependency_set unless lockfile_content.is_a?(Hash)
|
|
190
|
+
|
|
191
|
+
lockfile_content.fetch("package", []).each do |package_details|
|
|
167
192
|
next unless package_details["source"]
|
|
168
193
|
|
|
169
194
|
# TODO: This isn't quite right, as it will only give us one
|
|
@@ -179,40 +204,49 @@ module Dependabot
|
|
|
179
204
|
dependency_set
|
|
180
205
|
end
|
|
181
206
|
|
|
207
|
+
sig { returns(T::Array[String]) }
|
|
182
208
|
def patched_dependencies
|
|
183
209
|
root_manifest = manifest_files.find { |f| f.name == "Cargo.toml" }
|
|
184
|
-
|
|
210
|
+
parsed_content = parsed_file(T.must(root_manifest))
|
|
211
|
+
return [] unless parsed_content.is_a?(Hash)
|
|
212
|
+
return [] unless parsed_content["patch"]
|
|
185
213
|
|
|
186
|
-
|
|
214
|
+
parsed_content["patch"].values.flat_map(&:keys)
|
|
187
215
|
end
|
|
188
216
|
|
|
217
|
+
sig { params(declaration: T.any(String, T::Hash[String, String])).returns(T.nilable(String)) }
|
|
189
218
|
def requirement_from_declaration(declaration)
|
|
190
219
|
if declaration.is_a?(String)
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
return declaration["version"] if declaration["version"].is_a?(String) && declaration["version"] != ""
|
|
220
|
+
declaration == "" ? nil : declaration
|
|
221
|
+
else
|
|
222
|
+
return declaration["version"] if declaration["version"].is_a?(String) && declaration["version"] != ""
|
|
195
223
|
|
|
196
|
-
|
|
224
|
+
nil
|
|
225
|
+
end
|
|
197
226
|
end
|
|
198
227
|
|
|
228
|
+
sig { params(name: String, declaration: T.any(String, T::Hash[String, String])).returns(String) }
|
|
199
229
|
def name_from_declaration(name, declaration)
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
230
|
+
if declaration.is_a?(String)
|
|
231
|
+
name
|
|
232
|
+
else
|
|
233
|
+
declaration.fetch("package", name)
|
|
234
|
+
end
|
|
204
235
|
end
|
|
205
236
|
|
|
237
|
+
sig { params(declaration: T.any(String, T::Hash[String, String])).returns(T.nilable(T::Hash[Symbol, String])) }
|
|
206
238
|
def source_from_declaration(declaration)
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
239
|
+
if declaration.is_a?(String)
|
|
240
|
+
nil
|
|
241
|
+
else
|
|
242
|
+
return git_source_details(declaration) if declaration["git"]
|
|
243
|
+
return { type: "path" } if declaration["path"]
|
|
212
244
|
|
|
213
|
-
|
|
245
|
+
registry_source_details(declaration)
|
|
246
|
+
end
|
|
214
247
|
end
|
|
215
248
|
|
|
249
|
+
sig { params(declaration: T.any(String, T::Hash[String, String])).returns(T.nilable(T::Hash[Symbol, String])) }
|
|
216
250
|
def registry_source_details(declaration)
|
|
217
251
|
registry_name = declaration["registry"]
|
|
218
252
|
return if registry_name.nil?
|
|
@@ -242,6 +276,7 @@ module Dependabot
|
|
|
242
276
|
end
|
|
243
277
|
end
|
|
244
278
|
|
|
279
|
+
sig { params(registry_name: String, index_url: String).returns(T::Hash[Symbol, String]) }
|
|
245
280
|
def sparse_registry_source_details(registry_name, index_url)
|
|
246
281
|
token = credentials.find do |cred|
|
|
247
282
|
cred["type"] == "cargo_registry" && cred["registry"] == registry_name
|
|
@@ -268,25 +303,35 @@ module Dependabot
|
|
|
268
303
|
|
|
269
304
|
# Looks up dotted key name in cargo config
|
|
270
305
|
# e.g. "registries.my_registry.index"
|
|
306
|
+
sig { params(key_name: String).returns(T.nilable(String)) }
|
|
271
307
|
def cargo_config_field(key_name)
|
|
272
308
|
cargo_config_from_env(key_name) || cargo_config_from_file(key_name)
|
|
273
309
|
end
|
|
274
310
|
|
|
311
|
+
sig { params(key_name: String).returns(T.nilable(String)) }
|
|
275
312
|
def cargo_config_from_env(key_name)
|
|
276
313
|
env_var = "CARGO_#{key_name.upcase.tr('-.', '_')}"
|
|
277
314
|
ENV.fetch(env_var, nil)
|
|
278
315
|
end
|
|
279
316
|
|
|
317
|
+
sig { params(key_name: String).returns(T.nilable(String)) }
|
|
280
318
|
def cargo_config_from_file(key_name)
|
|
281
|
-
|
|
319
|
+
config_file = cargo_config
|
|
320
|
+
return nil unless config_file
|
|
321
|
+
|
|
322
|
+
parsed_file(config_file).dig(*key_name.split("."))
|
|
282
323
|
end
|
|
283
324
|
|
|
325
|
+
sig { params(name: String, declaration: T.any(String, T::Hash[String, String])).returns(T.nilable(String)) }
|
|
284
326
|
def version_from_lockfile(name, declaration)
|
|
285
327
|
return unless lockfile
|
|
286
328
|
|
|
329
|
+
lockfile_content = parsed_file(T.must(lockfile))
|
|
330
|
+
return unless lockfile_content.is_a?(Hash)
|
|
331
|
+
|
|
287
332
|
candidate_packages =
|
|
288
|
-
|
|
289
|
-
|
|
333
|
+
lockfile_content.fetch("package", [])
|
|
334
|
+
.select { |p| p["name"] == name }
|
|
290
335
|
|
|
291
336
|
if (req = requirement_from_declaration(declaration))
|
|
292
337
|
req = Cargo::Requirement.new(req)
|
|
@@ -311,10 +356,12 @@ module Dependabot
|
|
|
311
356
|
version_from_lockfile_details(package)
|
|
312
357
|
end
|
|
313
358
|
|
|
359
|
+
sig { params(declaration: T.any(String, T::Hash[String, String])).returns(T::Boolean) }
|
|
314
360
|
def git_req?(declaration)
|
|
315
361
|
source_from_declaration(declaration)&.fetch(:type, nil) == "git"
|
|
316
362
|
end
|
|
317
363
|
|
|
364
|
+
sig { params(declaration: T.any(String, T::Hash[String, String])).returns(T::Hash[Symbol, String]) }
|
|
318
365
|
def git_source_details(declaration)
|
|
319
366
|
{
|
|
320
367
|
type: "git",
|
|
@@ -324,38 +371,47 @@ module Dependabot
|
|
|
324
371
|
}
|
|
325
372
|
end
|
|
326
373
|
|
|
374
|
+
sig { params(package_details: T::Hash[String, String]).returns(String) }
|
|
327
375
|
def version_from_lockfile_details(package_details)
|
|
328
|
-
return package_details["version"] unless package_details["source"]&.start_with?("git+")
|
|
376
|
+
return T.must(package_details["version"]) unless package_details["source"]&.start_with?("git+")
|
|
329
377
|
|
|
330
|
-
package_details["source"].split("#").last
|
|
378
|
+
T.must(T.must(package_details["source"]).split("#").last)
|
|
331
379
|
end
|
|
332
380
|
|
|
381
|
+
sig { override.void }
|
|
333
382
|
def check_required_files
|
|
334
383
|
raise "No Cargo.toml!" unless get_original_file("Cargo.toml")
|
|
335
384
|
end
|
|
336
385
|
|
|
386
|
+
sig { params(file: DependencyFile).returns(T.untyped) }
|
|
337
387
|
def parsed_file(file)
|
|
338
|
-
@parsed_file ||= {}
|
|
388
|
+
@parsed_file ||= T.let({}, T.untyped)
|
|
339
389
|
@parsed_file[file.name] ||= TomlRB.parse(file.content)
|
|
340
390
|
rescue TomlRB::ParseError, TomlRB::ValueOverwriteError
|
|
341
391
|
raise Dependabot::DependencyFileNotParseable, file.path
|
|
342
392
|
end
|
|
343
393
|
|
|
394
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
344
395
|
def manifest_files
|
|
345
|
-
@manifest_files ||=
|
|
396
|
+
@manifest_files ||= T.let(
|
|
346
397
|
dependency_files
|
|
347
|
-
|
|
348
|
-
|
|
398
|
+
.select { |f| f.name.end_with?("Cargo.toml") }
|
|
399
|
+
.reject(&:support_file?),
|
|
400
|
+
T.nilable(T::Array[Dependabot::DependencyFile])
|
|
401
|
+
)
|
|
349
402
|
end
|
|
350
403
|
|
|
404
|
+
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
|
351
405
|
def lockfile
|
|
352
|
-
@lockfile ||= get_original_file("Cargo.lock")
|
|
406
|
+
@lockfile ||= T.let(get_original_file("Cargo.lock"), T.nilable(Dependabot::DependencyFile))
|
|
353
407
|
end
|
|
354
408
|
|
|
409
|
+
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
|
355
410
|
def cargo_config
|
|
356
|
-
@cargo_config ||= get_original_file(".cargo/config.toml")
|
|
411
|
+
@cargo_config ||= T.let(get_original_file(".cargo/config.toml"), T.nilable(Dependabot::DependencyFile))
|
|
357
412
|
end
|
|
358
413
|
|
|
414
|
+
sig { returns(T.class_of(Dependabot::Version)) }
|
|
359
415
|
def version_class
|
|
360
416
|
Cargo::Version
|
|
361
417
|
end
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "sorbet-runtime"
|
|
5
|
+
require "dependabot/cargo/file_updater"
|
|
6
|
+
|
|
7
|
+
module Dependabot
|
|
8
|
+
module Cargo
|
|
9
|
+
class FileUpdater
|
|
10
|
+
class WorkspaceManifestUpdater
|
|
11
|
+
extend T::Sig
|
|
12
|
+
|
|
13
|
+
sig { params(dependencies: T::Array[Dependabot::Dependency], manifest: Dependabot::DependencyFile).void }
|
|
14
|
+
def initialize(dependencies:, manifest:)
|
|
15
|
+
@dependencies = T.let(dependencies, T::Array[Dependabot::Dependency])
|
|
16
|
+
@manifest = T.let(manifest, Dependabot::DependencyFile)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
sig { returns(String) }
|
|
20
|
+
def updated_manifest_content
|
|
21
|
+
workspace_deps = dependencies.select { |dep| workspace_dependency?(dep) }
|
|
22
|
+
|
|
23
|
+
return T.must(manifest.content) if workspace_deps.empty?
|
|
24
|
+
|
|
25
|
+
T.must(workspace_deps.reduce(manifest.content.dup) do |content, dep|
|
|
26
|
+
update_workspace_dependency(T.must(content), dep)
|
|
27
|
+
end)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
sig { returns(T::Array[Dependabot::Dependency]) }
|
|
33
|
+
attr_reader :dependencies
|
|
34
|
+
|
|
35
|
+
sig { returns(Dependabot::DependencyFile) }
|
|
36
|
+
attr_reader :manifest
|
|
37
|
+
|
|
38
|
+
sig { params(dep: Dependabot::Dependency).returns(T::Boolean) }
|
|
39
|
+
def workspace_dependency?(dep)
|
|
40
|
+
dep.requirements.any? { |r| r[:groups]&.include?("workspace.dependencies") }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
sig { params(content: String, dep: Dependabot::Dependency).returns(String) }
|
|
44
|
+
def update_workspace_dependency(content, dep)
|
|
45
|
+
old_req = find_workspace_requirement(dep.previous_requirements)
|
|
46
|
+
new_req = find_workspace_requirement(dep.requirements)
|
|
47
|
+
|
|
48
|
+
return content if old_req == new_req || !old_req || !new_req
|
|
49
|
+
|
|
50
|
+
# First try to update in the inline [workspace.dependencies] section
|
|
51
|
+
workspace_section_regex = /\[workspace\.dependencies\](.*?)(?=\n\[|\n*\z)/m
|
|
52
|
+
|
|
53
|
+
updated_content = content.gsub(workspace_section_regex) do |section|
|
|
54
|
+
update_version_in_section(section, dep.name, old_req, new_req)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# If content didn't change, try table header notation [workspace.dependencies.name]
|
|
58
|
+
if updated_content == content
|
|
59
|
+
updated_content = update_table_header_notation(content, dep.name, old_req, new_req)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
updated_content
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
sig { params(requirements: T.nilable(T::Array[T::Hash[Symbol, T.untyped]])).returns(T.nilable(String)) }
|
|
66
|
+
def find_workspace_requirement(requirements)
|
|
67
|
+
requirements&.find { |r| r[:groups]&.include?("workspace.dependencies") }
|
|
68
|
+
&.fetch(:requirement)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
sig { params(section: String, dep_name: String, old_req: String, new_req: String).returns(String) }
|
|
72
|
+
def update_version_in_section(section, dep_name, old_req, new_req)
|
|
73
|
+
# Try double-quoted version first
|
|
74
|
+
updated = section.gsub(
|
|
75
|
+
/^(\s*#{Regexp.escape(dep_name)}\s*=\s*)"#{Regexp.escape(old_req)}"/m,
|
|
76
|
+
"\\1\"#{new_req}\""
|
|
77
|
+
)
|
|
78
|
+
return updated if updated != section
|
|
79
|
+
|
|
80
|
+
# Try single-quoted version
|
|
81
|
+
updated = section.gsub(
|
|
82
|
+
/^(\s*#{Regexp.escape(dep_name)}\s*=\s*)'#{Regexp.escape(old_req)}'/m,
|
|
83
|
+
"\\1'#{new_req}'"
|
|
84
|
+
)
|
|
85
|
+
return updated if updated != section
|
|
86
|
+
|
|
87
|
+
# Try unquoted version
|
|
88
|
+
updated = section.gsub(
|
|
89
|
+
/^(\s*#{Regexp.escape(dep_name)}\s*=\s*)#{Regexp.escape(old_req)}(\s|$)/m,
|
|
90
|
+
"\\1#{new_req}\\2"
|
|
91
|
+
)
|
|
92
|
+
return updated if updated != section
|
|
93
|
+
|
|
94
|
+
# Try inline table format with double quotes
|
|
95
|
+
updated = section.gsub(
|
|
96
|
+
/^(\s*#{Regexp.escape(dep_name)}\s*=\s*\{[^}]*version\s*=\s*)"#{Regexp.escape(old_req)}"/m,
|
|
97
|
+
"\\1\"#{new_req}\""
|
|
98
|
+
)
|
|
99
|
+
return updated if updated != section
|
|
100
|
+
|
|
101
|
+
# Try inline table format with single quotes
|
|
102
|
+
section.gsub(
|
|
103
|
+
/^(\s*#{Regexp.escape(dep_name)}\s*=\s*\{[^}]*version\s*=\s*)'#{Regexp.escape(old_req)}'/m,
|
|
104
|
+
"\\1'#{new_req}'"
|
|
105
|
+
)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
sig { params(content: String, dep_name: String, old_req: String, new_req: String).returns(String) }
|
|
109
|
+
def update_table_header_notation(content, dep_name, old_req, new_req)
|
|
110
|
+
# Match [workspace.dependencies.name] section and its content until next section
|
|
111
|
+
table_header_regex = /\[workspace\.dependencies\.#{Regexp.escape(dep_name)}\](.*?)(?=\n\[|\n*\z)/m
|
|
112
|
+
|
|
113
|
+
content.gsub(table_header_regex) do |section|
|
|
114
|
+
# Update version = "..." line within this section (double quotes)
|
|
115
|
+
updated = section.gsub(
|
|
116
|
+
/^(\s*version\s*=\s*)"#{Regexp.escape(old_req)}"/m,
|
|
117
|
+
"\\1\"#{new_req}\""
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
# Try single quotes if double quotes didn't match
|
|
121
|
+
if updated == section
|
|
122
|
+
updated = section.gsub(
|
|
123
|
+
/^(\s*version\s*=\s*)'#{Regexp.escape(old_req)}'/m,
|
|
124
|
+
"\\1'#{new_req}'"
|
|
125
|
+
)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Also try unquoted version
|
|
129
|
+
if updated == section
|
|
130
|
+
updated = section.gsub(
|
|
131
|
+
/^(\s*version\s*=\s*)#{Regexp.escape(old_req)}(\s|$)/m,
|
|
132
|
+
"\\1#{new_req}\\2"
|
|
133
|
+
)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
updated
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
@@ -16,6 +16,7 @@ module Dependabot
|
|
|
16
16
|
|
|
17
17
|
require_relative "file_updater/manifest_updater"
|
|
18
18
|
require_relative "file_updater/lockfile_updater"
|
|
19
|
+
require_relative "file_updater/workspace_manifest_updater"
|
|
19
20
|
|
|
20
21
|
sig { override.returns(T::Array[Regexp]) }
|
|
21
22
|
def self.updated_files_regex
|
|
@@ -60,10 +61,18 @@ module Dependabot
|
|
|
60
61
|
|
|
61
62
|
sig { params(file: Dependabot::DependencyFile).returns(String) }
|
|
62
63
|
def updated_manifest_content(file)
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
# Use workspace updater for root workspace manifests
|
|
65
|
+
if workspace_root_manifest?(file)
|
|
66
|
+
WorkspaceManifestUpdater.new(
|
|
67
|
+
dependencies: dependencies,
|
|
68
|
+
manifest: file
|
|
69
|
+
).updated_manifest_content
|
|
70
|
+
else
|
|
71
|
+
ManifestUpdater.new(
|
|
72
|
+
dependencies: dependencies,
|
|
73
|
+
manifest: file
|
|
74
|
+
).updated_manifest_content
|
|
75
|
+
end
|
|
67
76
|
end
|
|
68
77
|
|
|
69
78
|
sig { returns(String) }
|
|
@@ -92,6 +101,16 @@ module Dependabot
|
|
|
92
101
|
def lockfile
|
|
93
102
|
@lockfile ||= T.let(get_original_file("Cargo.lock"), T.nilable(Dependabot::DependencyFile))
|
|
94
103
|
end
|
|
104
|
+
|
|
105
|
+
sig { params(file: Dependabot::DependencyFile).returns(T::Boolean) }
|
|
106
|
+
def workspace_root_manifest?(file)
|
|
107
|
+
return false unless file.name == "Cargo.toml"
|
|
108
|
+
|
|
109
|
+
parsed_file = TomlRB.parse(file.content)
|
|
110
|
+
parsed_file.key?("workspace") && parsed_file["workspace"].key?("dependencies")
|
|
111
|
+
rescue TomlRB::ParseError
|
|
112
|
+
false
|
|
113
|
+
end
|
|
95
114
|
end
|
|
96
115
|
end
|
|
97
116
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strict
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "toml-rb"
|
|
@@ -12,7 +12,8 @@ require "dependabot/errors"
|
|
|
12
12
|
module Dependabot
|
|
13
13
|
module Cargo
|
|
14
14
|
class UpdateChecker
|
|
15
|
-
class VersionResolver
|
|
15
|
+
class VersionResolver # rubocop:disable Metrics/ClassLength
|
|
16
|
+
extend T::Sig
|
|
16
17
|
UNABLE_TO_UPDATE = /Unable to update (?<url>.*?)$/
|
|
17
18
|
BRANCH_NOT_FOUND_REGEX = /#{UNABLE_TO_UPDATE}.*to find branch `(?<branch>[^`]+)`/m
|
|
18
19
|
REVSPEC_PATTERN = /revspec '.*' not found/
|
|
@@ -26,31 +27,52 @@ module Dependabot
|
|
|
26
27
|
NOT_OUR_REF = /fatal: remote error: upload-pack: not our ref/
|
|
27
28
|
NOT_OUR_REF_REGEX = /#{NOT_OUR_REF}.*#{UNABLE_TO_UPDATE}/m
|
|
28
29
|
|
|
30
|
+
sig do
|
|
31
|
+
params(
|
|
32
|
+
dependency: Dependabot::Dependency,
|
|
33
|
+
credentials: T::Array[Dependabot::Credential],
|
|
34
|
+
original_dependency_files: T::Array[Dependabot::DependencyFile],
|
|
35
|
+
prepared_dependency_files: T::Array[Dependabot::DependencyFile]
|
|
36
|
+
).void
|
|
37
|
+
end
|
|
29
38
|
def initialize(dependency:, credentials:,
|
|
30
39
|
original_dependency_files:, prepared_dependency_files:)
|
|
31
40
|
@dependency = dependency
|
|
32
41
|
@prepared_dependency_files = prepared_dependency_files
|
|
33
42
|
@original_dependency_files = original_dependency_files
|
|
34
43
|
@credentials = credentials
|
|
44
|
+
|
|
45
|
+
# Initialize instance variables with proper T.let declarations
|
|
46
|
+
@prepared_manifest_files = T.let(nil, T.nilable(T::Array[DependencyFile]))
|
|
47
|
+
@original_manifest_files = T.let(nil, T.nilable(T::Array[DependencyFile]))
|
|
35
48
|
end
|
|
36
49
|
|
|
50
|
+
sig { returns(T.nilable(T.any(String, Gem::Version))) }
|
|
37
51
|
def latest_resolvable_version
|
|
38
52
|
return @latest_resolvable_version if defined?(@latest_resolvable_version)
|
|
39
53
|
|
|
40
|
-
@latest_resolvable_version = fetch_latest_resolvable_version
|
|
41
|
-
|
|
42
|
-
|
|
54
|
+
@latest_resolvable_version = T.let(fetch_latest_resolvable_version, T.nilable(T.any(String, Gem::Version)))
|
|
55
|
+
rescue Dependabot::SharedHelpers::HelperSubprocessFailed => e
|
|
56
|
+
raise Dependabot::DependencyFileNotResolvable, e.message
|
|
43
57
|
end
|
|
44
58
|
|
|
45
59
|
private
|
|
46
60
|
|
|
61
|
+
sig { returns(Dependency) }
|
|
47
62
|
attr_reader :dependency
|
|
63
|
+
|
|
64
|
+
sig { returns(T::Array[Credential]) }
|
|
48
65
|
attr_reader :credentials
|
|
66
|
+
|
|
67
|
+
sig { returns(T::Array[DependencyFile]) }
|
|
49
68
|
attr_reader :prepared_dependency_files
|
|
69
|
+
|
|
70
|
+
sig { returns(T::Array[DependencyFile]) }
|
|
50
71
|
attr_reader :original_dependency_files
|
|
51
72
|
|
|
73
|
+
sig { returns(T.nilable(T.any(String, Gem::Version))) }
|
|
52
74
|
def fetch_latest_resolvable_version
|
|
53
|
-
base_directory = prepared_dependency_files.first.directory
|
|
75
|
+
base_directory = T.must(prepared_dependency_files.first).directory
|
|
54
76
|
SharedHelpers.in_a_temporary_directory(base_directory) do
|
|
55
77
|
write_temporary_dependency_files
|
|
56
78
|
|
|
@@ -68,8 +90,10 @@ module Dependabot
|
|
|
68
90
|
rescue SharedHelpers::HelperSubprocessFailed => e
|
|
69
91
|
retry if better_specification_needed?(e)
|
|
70
92
|
handle_cargo_errors(e)
|
|
93
|
+
nil
|
|
71
94
|
end
|
|
72
95
|
|
|
96
|
+
sig { returns(T.nilable(T.any(String, Gem::Version))) }
|
|
73
97
|
def fetch_version_from_new_lockfile
|
|
74
98
|
check_rust_workspace_root unless File.exist?("Cargo.lock")
|
|
75
99
|
lockfile_content = File.read("Cargo.lock")
|
|
@@ -95,6 +119,7 @@ module Dependabot
|
|
|
95
119
|
# rubocop:disable Metrics/PerceivedComplexity
|
|
96
120
|
# rubocop:disable Metrics/CyclomaticComplexity
|
|
97
121
|
# rubocop:disable Metrics/AbcSize
|
|
122
|
+
sig { params(error: StandardError).returns(T::Boolean) }
|
|
98
123
|
def better_specification_needed?(error)
|
|
99
124
|
return false if @custom_specification
|
|
100
125
|
return false unless error.message.match?(/specification .* is ambigu/)
|
|
@@ -108,25 +133,26 @@ module Dependabot
|
|
|
108
133
|
dependency.version
|
|
109
134
|
end
|
|
110
135
|
|
|
111
|
-
if spec_options.count { |s| s.end_with?(ver) } == 1
|
|
112
|
-
@custom_specification = spec_options.find { |s| s.end_with?(ver) }
|
|
136
|
+
if spec_options.count { |s| s.end_with?(T.must(ver)) } == 1
|
|
137
|
+
@custom_specification = spec_options.find { |s| s.end_with?(T.must(ver)) }
|
|
113
138
|
return true
|
|
114
|
-
elsif spec_options.count { |s| s.end_with?(ver) } > 1
|
|
115
|
-
spec_options.select! { |s| s.end_with?(ver) }
|
|
139
|
+
elsif spec_options.count { |s| s.end_with?(T.must(ver)) } > 1
|
|
140
|
+
spec_options.select! { |s| s.end_with?(T.must(ver)) }
|
|
116
141
|
end
|
|
117
142
|
|
|
118
143
|
if git_dependency? && git_source_url &&
|
|
119
|
-
spec_options.count { |s| s.include?(git_source_url) } >= 1
|
|
120
|
-
spec_options.select! { |s| s.include?(git_source_url) }
|
|
144
|
+
spec_options.count { |s| s.include?(T.must(git_source_url)) } >= 1
|
|
145
|
+
spec_options.select! { |s| s.include?(T.must(git_source_url)) }
|
|
121
146
|
end
|
|
122
147
|
|
|
123
|
-
@custom_specification = spec_options.first
|
|
148
|
+
@custom_specification = T.let(spec_options.first, T.nilable(String))
|
|
124
149
|
true
|
|
125
150
|
end
|
|
126
151
|
# rubocop:enable Metrics/AbcSize
|
|
127
152
|
# rubocop:enable Metrics/CyclomaticComplexity
|
|
128
153
|
# rubocop:enable Metrics/PerceivedComplexity
|
|
129
154
|
|
|
155
|
+
sig { returns(String) }
|
|
130
156
|
def dependency_spec
|
|
131
157
|
return @custom_specification if @custom_specification
|
|
132
158
|
|
|
@@ -143,6 +169,7 @@ module Dependabot
|
|
|
143
169
|
|
|
144
170
|
# Shell out to Cargo, which handles everything for us, and does
|
|
145
171
|
# so without doing an install (so it's fast).
|
|
172
|
+
sig { void }
|
|
146
173
|
def run_cargo_update_command
|
|
147
174
|
run_cargo_command(
|
|
148
175
|
"cargo update -p #{dependency_spec} -vv",
|
|
@@ -150,6 +177,7 @@ module Dependabot
|
|
|
150
177
|
)
|
|
151
178
|
end
|
|
152
179
|
|
|
180
|
+
sig { params(command: String, fingerprint: T.nilable(String)).void }
|
|
153
181
|
def run_cargo_command(command, fingerprint: nil)
|
|
154
182
|
start = Time.now
|
|
155
183
|
command = SharedHelpers.escape_command(command)
|
|
@@ -176,40 +204,43 @@ module Dependabot
|
|
|
176
204
|
)
|
|
177
205
|
end
|
|
178
206
|
|
|
207
|
+
sig { params(prepared: T::Boolean).returns(T.nilable(Integer)) }
|
|
179
208
|
def write_temporary_dependency_files(prepared: true)
|
|
180
209
|
write_manifest_files(prepared: prepared)
|
|
181
210
|
|
|
182
|
-
File.write(lockfile.name, lockfile.content) if lockfile
|
|
183
|
-
File.write(toolchain.name, toolchain.content) if toolchain
|
|
211
|
+
File.write(T.must(lockfile).name, T.must(lockfile).content) if lockfile
|
|
212
|
+
File.write(T.must(toolchain).name, T.must(toolchain).content) if toolchain
|
|
184
213
|
return unless config
|
|
185
214
|
|
|
186
|
-
FileUtils.mkdir_p(File.dirname(config.name))
|
|
187
|
-
File.write(config.name, config.content)
|
|
215
|
+
FileUtils.mkdir_p(File.dirname(T.must(config).name))
|
|
216
|
+
File.write(T.must(config).name, T.must(config).content)
|
|
188
217
|
end
|
|
189
218
|
|
|
219
|
+
sig { void }
|
|
190
220
|
def check_rust_workspace_root
|
|
191
221
|
cargo_toml = original_dependency_files
|
|
192
222
|
.select { |f| f.name.end_with?("../Cargo.toml") }
|
|
193
223
|
.max_by { |f| f.name.length }
|
|
194
|
-
return unless TomlRB.parse(cargo_toml.content)["workspace"]
|
|
224
|
+
return unless TomlRB.parse(T.must(cargo_toml).content)["workspace"]
|
|
195
225
|
|
|
196
226
|
msg = "This project is part of a Rust workspace but is not the " \
|
|
197
227
|
"workspace root." \
|
|
198
228
|
|
|
199
|
-
if cargo_toml.directory != "/"
|
|
229
|
+
if T.must(cargo_toml).directory != "/"
|
|
200
230
|
msg += "Please update your settings so Dependabot points at the " \
|
|
201
|
-
"workspace root instead of #{cargo_toml.directory}."
|
|
231
|
+
"workspace root instead of #{T.must(cargo_toml).directory}."
|
|
202
232
|
end
|
|
203
233
|
raise Dependabot::DependencyFileNotResolvable, msg
|
|
204
234
|
end
|
|
205
235
|
|
|
206
236
|
# rubocop:disable Metrics/AbcSize
|
|
207
237
|
# rubocop:disable Metrics/PerceivedComplexity
|
|
238
|
+
sig { params(error: StandardError).void }
|
|
208
239
|
def handle_cargo_errors(error)
|
|
209
240
|
if error.message.include?("does not have these features")
|
|
210
241
|
# TODO: Ideally we should update the declaration not to ask
|
|
211
242
|
# for the specified features
|
|
212
|
-
return
|
|
243
|
+
return
|
|
213
244
|
end
|
|
214
245
|
|
|
215
246
|
if error.message.include?("authenticate when downloading repo") ||
|
|
@@ -218,22 +249,24 @@ module Dependabot
|
|
|
218
249
|
# consistent error)
|
|
219
250
|
urls = unreachable_git_urls
|
|
220
251
|
|
|
221
|
-
if urls.none?
|
|
222
|
-
url = error.message.match(UNABLE_TO_UPDATE)
|
|
223
|
-
|
|
224
|
-
raise if reachable_git_urls.include?(url)
|
|
252
|
+
if T.must(urls).none?
|
|
253
|
+
url = T.must(T.must(error.message.match(UNABLE_TO_UPDATE))
|
|
254
|
+
.named_captures.fetch("url")).split(/[#?]/).first
|
|
255
|
+
raise if T.must(reachable_git_urls).include?(url)
|
|
225
256
|
|
|
226
|
-
|
|
257
|
+
# Fix: Wrap url in T.must since split().first can return nil
|
|
258
|
+
T.must(urls) << T.must(url)
|
|
227
259
|
end
|
|
228
260
|
|
|
229
|
-
raise Dependabot::GitDependenciesNotReachable, urls
|
|
261
|
+
raise Dependabot::GitDependenciesNotReachable, T.must(urls)
|
|
230
262
|
end
|
|
231
263
|
|
|
232
264
|
[BRANCH_NOT_FOUND_REGEX, REF_NOT_FOUND_REGEX, GIT_REF_NOT_FOUND_REGEX, NOT_OUR_REF_REGEX].each do |regex|
|
|
233
265
|
next unless error.message.match?(regex)
|
|
234
266
|
|
|
235
|
-
dependency_url = error.message.match(regex).named_captures.fetch("url").split(/[#?]/).first
|
|
236
|
-
|
|
267
|
+
dependency_url = T.must(T.must(error.message.match(regex)).named_captures.fetch("url")).split(/[#?]/).first
|
|
268
|
+
# Fix: Wrap dependency_url in T.must since split().first can return nil
|
|
269
|
+
raise Dependabot::GitDependencyReferenceNotFound, T.must(dependency_url)
|
|
237
270
|
end
|
|
238
271
|
|
|
239
272
|
if workspace_native_library_update_error?(error.message)
|
|
@@ -268,8 +301,9 @@ module Dependabot
|
|
|
268
301
|
# rubocop:enable Metrics/AbcSize
|
|
269
302
|
# rubocop:enable Metrics/PerceivedComplexity
|
|
270
303
|
|
|
304
|
+
sig { params(message: T.nilable(String)).returns(T.any(Dependabot::Version, T::Boolean)) }
|
|
271
305
|
def using_old_toolchain?(message)
|
|
272
|
-
return true if message.include?("usage of sparse registries requires `-Z sparse-registry`")
|
|
306
|
+
return true if T.must(message).include?("usage of sparse registries requires `-Z sparse-registry`")
|
|
273
307
|
|
|
274
308
|
version_log = /rust version (?<version>\d.\d+)/.match(message)
|
|
275
309
|
return false unless version_log
|
|
@@ -277,11 +311,12 @@ module Dependabot
|
|
|
277
311
|
version_class.new(version_log[:version]) < version_class.new("1.68")
|
|
278
312
|
end
|
|
279
313
|
|
|
314
|
+
sig { returns(T.nilable(T::Array[String])) }
|
|
280
315
|
def unreachable_git_urls
|
|
281
316
|
return @unreachable_git_urls if defined?(@unreachable_git_urls)
|
|
282
317
|
|
|
283
|
-
@unreachable_git_urls = []
|
|
284
|
-
@reachable_git_urls = []
|
|
318
|
+
@unreachable_git_urls = T.let([], T.nilable(T::Array[String]))
|
|
319
|
+
@reachable_git_urls = T.let([], T.nilable(T::Array[String]))
|
|
285
320
|
|
|
286
321
|
dependencies = FileParser.new(
|
|
287
322
|
dependency_files: original_dependency_files,
|
|
@@ -295,19 +330,20 @@ module Dependabot
|
|
|
295
330
|
)
|
|
296
331
|
next unless checker.git_dependency?
|
|
297
332
|
|
|
298
|
-
url = dep.requirements.find { |r| r.dig(:source, :type) == "git" }
|
|
299
|
-
|
|
333
|
+
url = T.must(dep.requirements.find { |r| r.dig(:source, :type) == "git" })
|
|
334
|
+
.fetch(:source).fetch(:url)
|
|
300
335
|
|
|
301
336
|
if checker.git_repo_reachable?
|
|
302
|
-
@reachable_git_urls << url
|
|
337
|
+
T.must(@reachable_git_urls) << url
|
|
303
338
|
else
|
|
304
|
-
@unreachable_git_urls << url
|
|
339
|
+
T.must(@unreachable_git_urls) << url
|
|
305
340
|
end
|
|
306
341
|
end
|
|
307
342
|
|
|
308
343
|
@unreachable_git_urls
|
|
309
344
|
end
|
|
310
345
|
|
|
346
|
+
sig { returns(T.nilable(T::Array[String])) }
|
|
311
347
|
def reachable_git_urls
|
|
312
348
|
return @reachable_git_urls if defined?(@reachable_git_urls)
|
|
313
349
|
|
|
@@ -315,6 +351,7 @@ module Dependabot
|
|
|
315
351
|
@reachable_git_urls
|
|
316
352
|
end
|
|
317
353
|
|
|
354
|
+
sig { params(message: String).returns(T::Boolean) }
|
|
318
355
|
def resolvability_error?(message)
|
|
319
356
|
return true if message.include?("failed to parse lock")
|
|
320
357
|
return true if message.include?("believes it's in a workspace")
|
|
@@ -330,8 +367,9 @@ module Dependabot
|
|
|
330
367
|
!original_requirements_resolvable
|
|
331
368
|
end
|
|
332
369
|
|
|
370
|
+
sig { returns(T.any(TrueClass, FalseClass, Symbol)) }
|
|
333
371
|
def original_requirements_resolvable?
|
|
334
|
-
base_directory = original_dependency_files.first.directory
|
|
372
|
+
base_directory = T.must(original_dependency_files.first).directory
|
|
335
373
|
SharedHelpers.in_a_temporary_directory(base_directory) do
|
|
336
374
|
write_temporary_dependency_files(prepared: false)
|
|
337
375
|
|
|
@@ -353,10 +391,11 @@ module Dependabot
|
|
|
353
391
|
end
|
|
354
392
|
end
|
|
355
393
|
|
|
394
|
+
sig { params(message: String).returns(T::Boolean) }
|
|
356
395
|
def workspace_native_library_update_error?(message)
|
|
357
396
|
return false unless message.include?("native library")
|
|
358
397
|
|
|
359
|
-
library_count = prepared_manifest_files.count do |file|
|
|
398
|
+
library_count = T.must(prepared_manifest_files).count do |file|
|
|
360
399
|
package_name = TomlRB.parse(file.content).dig("package", "name")
|
|
361
400
|
next false unless package_name
|
|
362
401
|
|
|
@@ -366,17 +405,18 @@ module Dependabot
|
|
|
366
405
|
library_count >= 2
|
|
367
406
|
end
|
|
368
407
|
|
|
408
|
+
sig { params(prepared: T::Boolean).returns(T.nilable(T::Array[Dependabot::DependencyFile])) }
|
|
369
409
|
def write_manifest_files(prepared: true)
|
|
370
410
|
manifest_files = if prepared then prepared_manifest_files
|
|
371
411
|
else
|
|
372
412
|
original_manifest_files
|
|
373
413
|
end
|
|
374
414
|
|
|
375
|
-
manifest_files.each do |file|
|
|
415
|
+
T.must(manifest_files).each do |file|
|
|
376
416
|
path = file.name
|
|
377
417
|
dir = Pathname.new(path).dirname
|
|
378
418
|
FileUtils.mkdir_p(dir)
|
|
379
|
-
File.write(file.name, sanitized_manifest_content(file.content))
|
|
419
|
+
File.write(file.name, sanitized_manifest_content(T.must(file.content)))
|
|
380
420
|
|
|
381
421
|
next if virtual_manifest?(file)
|
|
382
422
|
|
|
@@ -388,26 +428,30 @@ module Dependabot
|
|
|
388
428
|
end
|
|
389
429
|
end
|
|
390
430
|
|
|
431
|
+
sig { returns(T.nilable(String)) }
|
|
391
432
|
def git_dependency_version
|
|
392
433
|
return unless lockfile
|
|
393
434
|
|
|
394
|
-
TomlRB.parse(lockfile.content)
|
|
435
|
+
TomlRB.parse(T.must(lockfile).content)
|
|
395
436
|
.fetch("package", [])
|
|
396
437
|
.select { |p| p["name"] == dependency.name }
|
|
397
438
|
.find { |p| p["source"].end_with?(dependency.version) }
|
|
398
439
|
.fetch("version")
|
|
399
440
|
end
|
|
400
441
|
|
|
442
|
+
sig { returns(T.nilable(String)) }
|
|
401
443
|
def git_source_url
|
|
402
444
|
dependency.requirements
|
|
403
445
|
.find { |r| r.dig(:source, :type) == "git" }
|
|
404
446
|
&.dig(:source, :url)
|
|
405
447
|
end
|
|
406
448
|
|
|
449
|
+
sig { returns(String) }
|
|
407
450
|
def dummy_app_content
|
|
408
451
|
%{fn main() {\nprintln!("Hello, world!");\n}}
|
|
409
452
|
end
|
|
410
453
|
|
|
454
|
+
sig { params(content: String).returns(String) }
|
|
411
455
|
def sanitized_manifest_content(content)
|
|
412
456
|
object = TomlRB.parse(content)
|
|
413
457
|
|
|
@@ -424,32 +468,40 @@ module Dependabot
|
|
|
424
468
|
TomlRB.dump(object)
|
|
425
469
|
end
|
|
426
470
|
|
|
471
|
+
sig { returns(T.nilable(T::Array[DependencyFile])) }
|
|
427
472
|
def prepared_manifest_files
|
|
428
473
|
@prepared_manifest_files ||=
|
|
429
474
|
prepared_dependency_files
|
|
430
475
|
.select { |f| f.name.end_with?("Cargo.toml") }
|
|
431
476
|
end
|
|
432
477
|
|
|
478
|
+
sig { returns(T.nilable(T::Array[DependencyFile])) }
|
|
433
479
|
def original_manifest_files
|
|
434
480
|
@original_manifest_files ||=
|
|
435
481
|
original_dependency_files
|
|
436
482
|
.select { |f| f.name.end_with?("Cargo.toml") }
|
|
437
483
|
end
|
|
438
484
|
|
|
485
|
+
sig { returns(T.nilable(DependencyFile)) }
|
|
439
486
|
def lockfile
|
|
440
|
-
@lockfile ||= prepared_dependency_files
|
|
441
|
-
|
|
487
|
+
@lockfile ||= T.let(prepared_dependency_files
|
|
488
|
+
.find { |f| f.name == "Cargo.lock" }, T.nilable(Dependabot::DependencyFile))
|
|
442
489
|
end
|
|
443
490
|
|
|
491
|
+
sig { returns(T.nilable(DependencyFile)) }
|
|
444
492
|
def toolchain
|
|
445
|
-
@toolchain ||= original_dependency_files
|
|
446
|
-
|
|
493
|
+
@toolchain ||= T.let(original_dependency_files
|
|
494
|
+
.find { |f| f.name == "rust-toolchain" }, T.nilable(Dependabot::DependencyFile))
|
|
447
495
|
end
|
|
448
496
|
|
|
497
|
+
sig { returns(T.nilable(DependencyFile)) }
|
|
449
498
|
def config
|
|
450
|
-
@config ||= original_dependency_files.find
|
|
499
|
+
@config ||= T.let(original_dependency_files.find do |f|
|
|
500
|
+
f.name == ".cargo/config.toml"
|
|
501
|
+
end, T.nilable(Dependabot::DependencyFile))
|
|
451
502
|
end
|
|
452
503
|
|
|
504
|
+
sig { returns(T::Boolean) }
|
|
453
505
|
def git_dependency?
|
|
454
506
|
GitCommitChecker.new(
|
|
455
507
|
dependency: dependency,
|
|
@@ -460,10 +512,12 @@ module Dependabot
|
|
|
460
512
|
# When the package table is not present in a workspace manifest, it is
|
|
461
513
|
# called a virtual manifest: https://doc.rust-lang.org/cargo/reference/
|
|
462
514
|
# manifest.html#virtual-manifest
|
|
515
|
+
sig { params(file: DependencyFile).returns(T::Boolean) }
|
|
463
516
|
def virtual_manifest?(file)
|
|
464
|
-
!file.content.include?("[package]")
|
|
517
|
+
!T.must(file.content).include?("[package]")
|
|
465
518
|
end
|
|
466
519
|
|
|
520
|
+
sig { returns(T.class_of(Dependabot::Version)) }
|
|
467
521
|
def version_class
|
|
468
522
|
dependency.version_class
|
|
469
523
|
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.326.1
|
|
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.326.1
|
|
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.326.1
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: debug
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -247,6 +247,7 @@ files:
|
|
|
247
247
|
- lib/dependabot/cargo/file_updater.rb
|
|
248
248
|
- lib/dependabot/cargo/file_updater/lockfile_updater.rb
|
|
249
249
|
- lib/dependabot/cargo/file_updater/manifest_updater.rb
|
|
250
|
+
- lib/dependabot/cargo/file_updater/workspace_manifest_updater.rb
|
|
250
251
|
- lib/dependabot/cargo/helpers.rb
|
|
251
252
|
- lib/dependabot/cargo/language.rb
|
|
252
253
|
- lib/dependabot/cargo/metadata_finder.rb
|
|
@@ -265,7 +266,7 @@ licenses:
|
|
|
265
266
|
- MIT
|
|
266
267
|
metadata:
|
|
267
268
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
|
268
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
|
269
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.326.1
|
|
269
270
|
rdoc_options: []
|
|
270
271
|
require_paths:
|
|
271
272
|
- lib
|