dependabot-cargo 0.384.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 +143 -81
- data/lib/dependabot/cargo/file_parser.rb +71 -31
- data/lib/dependabot/cargo/file_updater/lockfile_updater.rb +37 -15
- data/lib/dependabot/cargo/helpers.rb +14 -7
- 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/version_resolver.rb +19 -12
- data/lib/dependabot/cargo/update_checker.rb +7 -7
- metadata +4 -4
|
@@ -41,7 +41,7 @@ module Dependabot
|
|
|
41
41
|
@path_dependency_files = T.let(nil, T.nilable(T::Array[Dependabot::DependencyFile]))
|
|
42
42
|
@lockfile = T.let(nil, T.nilable(Dependabot::DependencyFile))
|
|
43
43
|
@toolchain = T.let(nil, T.nilable(Dependabot::DependencyFile))
|
|
44
|
-
@
|
|
44
|
+
@config_files = T.let(nil, T.nilable(T::Array[Dependabot::DependencyFile]))
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
sig { returns(T.any(String, T.noreturn)) }
|
|
@@ -305,11 +305,13 @@ module Dependabot
|
|
|
305
305
|
|
|
306
306
|
File.write(lockfile.name, replace_ssh_urls(T.must(lockfile.content)))
|
|
307
307
|
File.write(T.must(toolchain).name, T.must(toolchain).content) if toolchain
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
308
|
+
config_files.each do |config_file|
|
|
309
|
+
FileUtils.mkdir_p(File.dirname(config_file.name))
|
|
310
|
+
File.write(
|
|
311
|
+
config_file.name,
|
|
312
|
+
Helpers.sanitize_cargo_config(T.must(config_file.content), file_name: config_file.name)
|
|
313
|
+
)
|
|
314
|
+
end
|
|
313
315
|
end
|
|
314
316
|
|
|
315
317
|
sig { void }
|
|
@@ -390,20 +392,31 @@ module Dependabot
|
|
|
390
392
|
TomlRB.dump(parsed_manifest)
|
|
391
393
|
end
|
|
392
394
|
|
|
393
|
-
sig { params(parsed_manifest: T::Hash[String, T.
|
|
395
|
+
sig { params(parsed_manifest: T::Hash[String, T.anything]).void }
|
|
394
396
|
def pin_target_specific_dependencies!(parsed_manifest)
|
|
395
|
-
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)
|
|
396
399
|
Cargo::FileParser::DEPENDENCY_TYPES.each do |type|
|
|
397
|
-
t_details.fetch(type, {}).each do |name, requirement|
|
|
400
|
+
toml_table_or_empty(t_details.fetch(type, {})).each do |name, requirement|
|
|
398
401
|
next unless name == dependency.name
|
|
399
402
|
|
|
400
403
|
updated_req = "=#{dependency.version}"
|
|
401
404
|
|
|
402
|
-
if requirement.is_a?(Hash)
|
|
403
|
-
|
|
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"] =
|
|
404
413
|
updated_req
|
|
405
414
|
else
|
|
406
|
-
|
|
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
|
|
407
420
|
end
|
|
408
421
|
end
|
|
409
422
|
end
|
|
@@ -496,6 +509,12 @@ module Dependabot
|
|
|
496
509
|
lockfile_content
|
|
497
510
|
end
|
|
498
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
|
+
|
|
499
518
|
sig { returns(String) }
|
|
500
519
|
def dummy_app_content
|
|
501
520
|
%{fn main() {\nprintln!("Hello, world!");\n}}
|
|
@@ -537,9 +556,12 @@ module Dependabot
|
|
|
537
556
|
dependency_files.find { |f| f.name == "rust-toolchain" }
|
|
538
557
|
end
|
|
539
558
|
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
559
|
+
# Cargo merges `.cargo/config.toml` hierarchically (package directory plus
|
|
560
|
+
# every ancestor up to the repo root), so we materialise all of them and
|
|
561
|
+
# let Cargo perform the merge with its own precedence rules.
|
|
562
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
563
|
+
def config_files
|
|
564
|
+
@config_files ||= dependency_files.select { |f| f.name.end_with?(".cargo/config.toml") }
|
|
543
565
|
end
|
|
544
566
|
|
|
545
567
|
sig { params(file: Dependabot::DependencyFile).returns(T::Boolean) }
|
|
@@ -19,8 +19,8 @@ module Dependabot
|
|
|
19
19
|
# These per-registry settings override the global CARGO_REGISTRY_GLOBAL_CREDENTIAL_PROVIDERS env var,
|
|
20
20
|
# causing Cargo to look up tokens locally. Since the dependabot proxy handles all registry authentication
|
|
21
21
|
# transparently, we remove these so Cargo makes plain unauthenticated requests that the proxy can intercept.
|
|
22
|
-
sig { params(config_content: String).returns(String) }
|
|
23
|
-
def self.sanitize_cargo_config(config_content)
|
|
22
|
+
sig { params(config_content: String, file_name: String).returns(String) }
|
|
23
|
+
def self.sanitize_cargo_config(config_content, file_name: ".cargo/config.toml")
|
|
24
24
|
parsed = TomlRB.parse(config_content)
|
|
25
25
|
return config_content unless parsed.is_a?(Hash)
|
|
26
26
|
|
|
@@ -40,7 +40,7 @@ module Dependabot
|
|
|
40
40
|
TomlRB.dump(parsed)
|
|
41
41
|
rescue TomlRB::Error => e
|
|
42
42
|
raise Dependabot::DependencyFileNotParseable.new(
|
|
43
|
-
|
|
43
|
+
file_name,
|
|
44
44
|
"Failed to parse Cargo config file: #{e.message}"
|
|
45
45
|
)
|
|
46
46
|
end
|
|
@@ -109,10 +109,17 @@ module Dependabot
|
|
|
109
109
|
).returns(T::Hash[String, String])
|
|
110
110
|
end
|
|
111
111
|
def self.registry_token_env_from_files(dependency_files, credentials)
|
|
112
|
-
|
|
113
|
-
return {}
|
|
114
|
-
|
|
115
|
-
|
|
112
|
+
config_files = dependency_files.select { |f| f.name.end_with?(".cargo/config.toml") }
|
|
113
|
+
return {} if config_files.empty?
|
|
114
|
+
|
|
115
|
+
# Cargo gives nearer configs precedence over ancestors on key collisions.
|
|
116
|
+
# A config's `../` depth (how many parent hops appear in its name)
|
|
117
|
+
# indicates how far up the tree it lives, so merge farthest-first and let
|
|
118
|
+
# the nearest config (fewest `../`) win.
|
|
119
|
+
ordered = config_files.sort_by { |f| -f.name.scan("../").count }
|
|
120
|
+
ordered.each_with_object({}) do |config_file, env|
|
|
121
|
+
env.merge!(registry_token_env(T.must(config_file.content), credentials))
|
|
122
|
+
end
|
|
116
123
|
end
|
|
117
124
|
|
|
118
125
|
# Builds the complete environment variable hash for running cargo commands:
|
|
@@ -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) }
|