dependabot-cargo 0.332.0 → 0.333.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 +13 -2
- data/lib/dependabot/cargo/file_updater/lockfile_updater.rb +2 -1
- data/lib/dependabot/cargo/file_updater/manifest_updater.rb +71 -22
- data/lib/dependabot/cargo/metadata_finder.rb +24 -3
- data/lib/dependabot/cargo/requirement.rb +1 -1
- data/lib/dependabot/cargo/update_checker/file_preparer.rb +52 -5
- data/lib/dependabot/cargo/update_checker/requirements_updater.rb +41 -16
- data/lib/dependabot/cargo/update_checker/version_resolver.rb +2 -1
- data/lib/dependabot/cargo/update_checker.rb +96 -41
- data/lib/dependabot/cargo/version.rb +9 -2
- metadata +6 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '091190197e180945f1979a4102768e43519a054c4dcccfad73bebd41d6f08abe'
|
|
4
|
+
data.tar.gz: 3bc3403ebacc832ea65c9e7cce7fcf8bd39728548bf8bf9c516bf6d07594d9f0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3aef8d8668764a7849ea0b03ce683103151b1cbed29d8c0b405767d45805295358328e9a1105b990a8b70413f74bd1e2b045b884311ea7a0a8e6ac6f937e8a03
|
|
7
|
+
data.tar.gz: c62c275d2fee1f4477db333d62ed8bcf1a5f2eea1045356e4150a0afccdcda5a65a819b6cb5630d0943e6ebb0a49a9fc7ff82dba3fc1783dc432970de8d27294
|
|
@@ -7,6 +7,7 @@ require "toml-rb"
|
|
|
7
7
|
|
|
8
8
|
require "dependabot/file_fetchers"
|
|
9
9
|
require "dependabot/file_fetchers/base"
|
|
10
|
+
require "dependabot/file_filtering"
|
|
10
11
|
require "dependabot/cargo/file_parser"
|
|
11
12
|
|
|
12
13
|
# Docs on Cargo workspaces:
|
|
@@ -30,7 +31,7 @@ module Dependabot
|
|
|
30
31
|
sig { override.returns(T.nilable(T::Hash[Symbol, T.untyped])) }
|
|
31
32
|
def ecosystem_versions
|
|
32
33
|
channel = if rust_toolchain
|
|
33
|
-
TomlRB.parse(T.must(rust_toolchain).content).
|
|
34
|
+
TomlRB.parse(T.must(rust_toolchain).content).dig("toolchain", "channel")
|
|
34
35
|
else
|
|
35
36
|
"default"
|
|
36
37
|
end
|
|
@@ -55,7 +56,13 @@ module Dependabot
|
|
|
55
56
|
fetched_files << T.must(cargo_config) if cargo_config
|
|
56
57
|
fetched_files << T.must(rust_toolchain) if rust_toolchain
|
|
57
58
|
fetched_files += fetch_path_dependency_and_workspace_files
|
|
58
|
-
|
|
59
|
+
|
|
60
|
+
# Filter excluded files from final collection
|
|
61
|
+
filtered_files = fetched_files.reject do |file|
|
|
62
|
+
Dependabot::FileFiltering.should_exclude_path?(file.name, "file from final collection", @exclude_paths)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
filtered_files.uniq
|
|
59
66
|
end
|
|
60
67
|
|
|
61
68
|
private
|
|
@@ -125,6 +132,8 @@ module Dependabot
|
|
|
125
132
|
next if previously_fetched_files.map(&:name).include?(path)
|
|
126
133
|
next if file.name == path
|
|
127
134
|
|
|
135
|
+
next if Dependabot::FileFiltering.should_exclude_path?(path, "file from final collection", @exclude_paths)
|
|
136
|
+
|
|
128
137
|
fetched_file = fetch_file_from_host(path, fetch_submodules: true)
|
|
129
138
|
previously_fetched_files << fetched_file
|
|
130
139
|
grandchild_requirement_files =
|
|
@@ -160,6 +169,8 @@ module Dependabot
|
|
|
160
169
|
next if previously_fetched_files.map(&:name).include?(path)
|
|
161
170
|
next if file.name == path
|
|
162
171
|
|
|
172
|
+
next if Dependabot::FileFiltering.should_exclude_path?(path, "file from final collection", @exclude_paths)
|
|
173
|
+
|
|
163
174
|
fetched_file = fetch_file_from_host(path, fetch_submodules: true)
|
|
164
175
|
.tap { |f| f.support_file = true }
|
|
165
176
|
previously_fetched_files << fetched_file
|
|
@@ -16,6 +16,7 @@ module Dependabot
|
|
|
16
16
|
# rubocop:disable Metrics/ClassLength
|
|
17
17
|
class LockfileUpdater
|
|
18
18
|
extend T::Sig
|
|
19
|
+
|
|
19
20
|
LOCKFILE_ENTRY_REGEX = /
|
|
20
21
|
\[\[package\]\]\n
|
|
21
22
|
(?:(?!^\[(?:\[package|metadata)).)+
|
|
@@ -123,7 +124,7 @@ module Dependabot
|
|
|
123
124
|
dependency.version
|
|
124
125
|
end
|
|
125
126
|
|
|
126
|
-
if ver && spec_options.
|
|
127
|
+
if ver && spec_options.one? { |s| s.end_with?(ver) }
|
|
127
128
|
@custom_specification = spec_options.find { |s| s.end_with?(ver) }
|
|
128
129
|
return true
|
|
129
130
|
elsif ver && spec_options.count { |s| s.end_with?(ver) } > 1
|
|
@@ -1,22 +1,38 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strict
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
+
require "sorbet-runtime"
|
|
5
|
+
|
|
6
|
+
require "dependabot/dependency"
|
|
7
|
+
require "dependabot/dependency_file"
|
|
4
8
|
require "dependabot/cargo/file_updater"
|
|
5
9
|
|
|
6
10
|
module Dependabot
|
|
7
11
|
module Cargo
|
|
8
12
|
class FileUpdater
|
|
9
13
|
class ManifestUpdater
|
|
14
|
+
extend T::Sig
|
|
15
|
+
|
|
16
|
+
sig do
|
|
17
|
+
params(
|
|
18
|
+
dependencies: T::Array[Dependabot::Dependency],
|
|
19
|
+
manifest: Dependabot::DependencyFile
|
|
20
|
+
).void
|
|
21
|
+
end
|
|
10
22
|
def initialize(dependencies:, manifest:)
|
|
11
|
-
@dependencies = dependencies
|
|
12
|
-
@manifest = manifest
|
|
23
|
+
@dependencies = T.let(dependencies, T::Array[Dependabot::Dependency])
|
|
24
|
+
@manifest = T.let(manifest, Dependabot::DependencyFile)
|
|
13
25
|
end
|
|
14
26
|
|
|
27
|
+
sig { returns(String) }
|
|
15
28
|
def updated_manifest_content
|
|
29
|
+
content = manifest.content
|
|
30
|
+
raise "Manifest has no content" if content.nil?
|
|
31
|
+
|
|
16
32
|
dependencies
|
|
17
33
|
.select { |dep| requirement_changed?(manifest, dep) }
|
|
18
|
-
.reduce(
|
|
19
|
-
updated_content =
|
|
34
|
+
.reduce(content.dup) do |current_content, dep|
|
|
35
|
+
updated_content = current_content
|
|
20
36
|
|
|
21
37
|
updated_content = update_requirements(
|
|
22
38
|
content: updated_content,
|
|
@@ -30,7 +46,7 @@ module Dependabot
|
|
|
30
46
|
dependency: dep
|
|
31
47
|
)
|
|
32
48
|
|
|
33
|
-
raise "Expected content to change!" if
|
|
49
|
+
raise "Expected content to change!" if current_content == updated_content
|
|
34
50
|
|
|
35
51
|
updated_content
|
|
36
52
|
end
|
|
@@ -38,42 +54,51 @@ module Dependabot
|
|
|
38
54
|
|
|
39
55
|
private
|
|
40
56
|
|
|
57
|
+
sig { returns(T::Array[Dependabot::Dependency]) }
|
|
41
58
|
attr_reader :dependencies
|
|
59
|
+
|
|
60
|
+
sig { returns(Dependabot::DependencyFile) }
|
|
42
61
|
attr_reader :manifest
|
|
43
62
|
|
|
63
|
+
sig { params(file: Dependabot::DependencyFile, dependency: Dependabot::Dependency).returns(T::Boolean) }
|
|
44
64
|
def requirement_changed?(file, dependency)
|
|
45
65
|
changed_requirements =
|
|
46
|
-
dependency.requirements - dependency.previous_requirements
|
|
66
|
+
dependency.requirements - (dependency.previous_requirements || [])
|
|
47
67
|
|
|
48
68
|
changed_requirements.any? { |f| f[:file] == file.name }
|
|
49
69
|
end
|
|
50
70
|
|
|
71
|
+
sig { params(content: String, filename: String, dependency: Dependabot::Dependency).returns(String) }
|
|
51
72
|
def update_requirements(content:, filename:, dependency:)
|
|
52
|
-
updated_content = content.dup
|
|
73
|
+
updated_content = T.let(content.dup, String)
|
|
53
74
|
|
|
54
75
|
# The UpdateChecker ensures the order of requirements is preserved
|
|
55
76
|
# when updating, so we can zip them together in new/old pairs.
|
|
56
77
|
reqs = dependency.requirements
|
|
57
|
-
.zip(dependency.previous_requirements)
|
|
78
|
+
.zip(dependency.previous_requirements || [])
|
|
58
79
|
.reject { |new_req, old_req| new_req == old_req }
|
|
59
80
|
|
|
60
81
|
# Loop through each changed requirement
|
|
61
82
|
reqs.each do |new_req, old_req|
|
|
83
|
+
next if old_req.nil?
|
|
84
|
+
|
|
62
85
|
raise "Bad req match" unless new_req[:file] == old_req[:file]
|
|
63
86
|
next if new_req[:requirement] == old_req[:requirement]
|
|
64
87
|
next unless new_req[:file] == filename
|
|
65
88
|
|
|
66
|
-
updated_content =
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
89
|
+
updated_content =
|
|
90
|
+
update_manifest_req(
|
|
91
|
+
content: updated_content,
|
|
92
|
+
dep: dependency,
|
|
93
|
+
old_req: old_req.fetch(:requirement),
|
|
94
|
+
new_req: new_req.fetch(:requirement)
|
|
95
|
+
)
|
|
72
96
|
end
|
|
73
97
|
|
|
74
98
|
updated_content
|
|
75
99
|
end
|
|
76
100
|
|
|
101
|
+
sig { params(content: String, filename: String, dependency: Dependabot::Dependency).returns(String) }
|
|
77
102
|
def update_git_pin(content:, filename:, dependency:)
|
|
78
103
|
updated_pin =
|
|
79
104
|
dependency.requirements
|
|
@@ -82,7 +107,7 @@ module Dependabot
|
|
|
82
107
|
|
|
83
108
|
old_pin =
|
|
84
109
|
dependency.previous_requirements
|
|
85
|
-
|
|
110
|
+
&.find { |r| r[:file] == filename }
|
|
86
111
|
&.dig(:source, :ref)
|
|
87
112
|
|
|
88
113
|
return content unless old_pin
|
|
@@ -95,21 +120,31 @@ module Dependabot
|
|
|
95
120
|
)
|
|
96
121
|
end
|
|
97
122
|
|
|
123
|
+
sig do
|
|
124
|
+
params(
|
|
125
|
+
content: String,
|
|
126
|
+
dep: Dependabot::Dependency,
|
|
127
|
+
old_req: String,
|
|
128
|
+
new_req: String
|
|
129
|
+
).returns(String)
|
|
130
|
+
end
|
|
98
131
|
def update_manifest_req(content:, dep:, old_req:, new_req:)
|
|
99
132
|
simple_declaration = content.scan(declaration_regex(dep))
|
|
100
133
|
.find { |m| m.include?(old_req) }
|
|
101
134
|
|
|
102
135
|
if simple_declaration
|
|
103
136
|
simple_declaration_regex =
|
|
104
|
-
/(?:^|["'])#{Regexp.escape(simple_declaration)}/
|
|
137
|
+
/(?:^|["'])#{Regexp.escape(T.cast(simple_declaration, String))}/
|
|
105
138
|
old_req_escaped = Regexp.escape(old_req)
|
|
106
139
|
content.gsub(simple_declaration_regex) do |line|
|
|
107
140
|
line.gsub(/.+=.*\K(#{old_req_escaped})/, new_req)
|
|
108
141
|
end
|
|
109
142
|
elsif content.match?(feature_declaration_version_regex(dep))
|
|
110
143
|
content.gsub(feature_declaration_version_regex(dep)) do |part|
|
|
111
|
-
|
|
112
|
-
|
|
144
|
+
match_data = content.match(feature_declaration_version_regex(dep))
|
|
145
|
+
line = T.must(match_data).named_captures.fetch("version_declaration")
|
|
146
|
+
return content if line.nil?
|
|
147
|
+
|
|
113
148
|
new_line = line.gsub(old_req, new_req)
|
|
114
149
|
part.gsub(line, new_line)
|
|
115
150
|
end
|
|
@@ -118,20 +153,31 @@ module Dependabot
|
|
|
118
153
|
end
|
|
119
154
|
end
|
|
120
155
|
|
|
156
|
+
sig do
|
|
157
|
+
params(
|
|
158
|
+
content: String,
|
|
159
|
+
dep: Dependabot::Dependency,
|
|
160
|
+
old_pin: String,
|
|
161
|
+
new_pin: String
|
|
162
|
+
)
|
|
163
|
+
.returns(String)
|
|
164
|
+
end
|
|
121
165
|
def update_manifest_pin(content:, dep:, old_pin:, new_pin:)
|
|
122
166
|
simple_declaration = content.scan(declaration_regex(dep))
|
|
123
167
|
.find { |m| m.include?(old_pin) }
|
|
124
168
|
|
|
125
169
|
if simple_declaration
|
|
126
170
|
simple_declaration_regex =
|
|
127
|
-
/(?:^|["'])#{Regexp.escape(simple_declaration)}/
|
|
171
|
+
/(?:^|["'])#{Regexp.escape(T.cast(simple_declaration, String))}/
|
|
128
172
|
content.gsub(simple_declaration_regex) do |line|
|
|
129
173
|
line.gsub(old_pin, new_pin)
|
|
130
174
|
end
|
|
131
175
|
elsif content.match?(feature_declaration_pin_regex(dep))
|
|
132
176
|
content.gsub(feature_declaration_pin_regex(dep)) do |part|
|
|
133
|
-
|
|
134
|
-
|
|
177
|
+
match_data = content.match(feature_declaration_pin_regex(dep))
|
|
178
|
+
line = T.must(match_data).named_captures.fetch("pin_declaration")
|
|
179
|
+
return content if line.nil?
|
|
180
|
+
|
|
135
181
|
new_line = line.gsub(old_pin, new_pin)
|
|
136
182
|
part.gsub(line, new_line)
|
|
137
183
|
end
|
|
@@ -140,10 +186,12 @@ module Dependabot
|
|
|
140
186
|
end
|
|
141
187
|
end
|
|
142
188
|
|
|
189
|
+
sig { params(dep: Dependabot::Dependency).returns(Regexp) }
|
|
143
190
|
def declaration_regex(dep)
|
|
144
191
|
/(?:^|^\s*|["'])#{Regexp.escape(dep.name)}["']?(?:\s*\.version)?\s*=.*$/i
|
|
145
192
|
end
|
|
146
193
|
|
|
194
|
+
sig { params(dep: Dependabot::Dependency).returns(Regexp) }
|
|
147
195
|
def feature_declaration_version_regex(dep)
|
|
148
196
|
/
|
|
149
197
|
#{Regexp.quote("dependencies.#{dep.name}]")}
|
|
@@ -152,6 +200,7 @@ module Dependabot
|
|
|
152
200
|
/mx
|
|
153
201
|
end
|
|
154
202
|
|
|
203
|
+
sig { params(dep: Dependabot::Dependency).returns(Regexp) }
|
|
155
204
|
def feature_declaration_pin_regex(dep)
|
|
156
205
|
/
|
|
157
206
|
#{Regexp.quote("dependencies.#{dep.name}]")}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strict
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "excon"
|
|
5
|
+
require "sorbet-runtime"
|
|
6
|
+
|
|
5
7
|
require "dependabot/metadata_finders"
|
|
6
8
|
require "dependabot/metadata_finders/base"
|
|
7
9
|
require "dependabot/registry_client"
|
|
@@ -9,11 +11,20 @@ require "dependabot/registry_client"
|
|
|
9
11
|
module Dependabot
|
|
10
12
|
module Cargo
|
|
11
13
|
class MetadataFinder < Dependabot::MetadataFinders::Base
|
|
14
|
+
extend T::Sig
|
|
15
|
+
|
|
12
16
|
SOURCE_KEYS = %w(repository homepage documentation).freeze
|
|
13
17
|
CRATES_IO_API = "https://crates.io/api/v1/crates"
|
|
14
18
|
|
|
19
|
+
sig { params(dependency: Dependabot::Dependency, credentials: T::Array[Dependabot::Credential]).void }
|
|
20
|
+
def initialize(dependency:, credentials:)
|
|
21
|
+
super
|
|
22
|
+
@crates_listing = T.let(nil, T.nilable(T::Hash[String, T.untyped]))
|
|
23
|
+
end
|
|
24
|
+
|
|
15
25
|
private
|
|
16
26
|
|
|
27
|
+
sig { override.returns(T.nilable(Dependabot::Source)) }
|
|
17
28
|
def look_up_source
|
|
18
29
|
case new_source_type
|
|
19
30
|
when "default" then find_source_from_crates_listing
|
|
@@ -23,19 +34,22 @@ module Dependabot
|
|
|
23
34
|
end
|
|
24
35
|
end
|
|
25
36
|
|
|
37
|
+
sig { returns(T.nilable(String)) }
|
|
26
38
|
def new_source_type
|
|
27
39
|
dependency.source_type
|
|
28
40
|
end
|
|
29
41
|
|
|
42
|
+
sig { returns(T.nilable(Dependabot::Source)) }
|
|
30
43
|
def find_source_from_crates_listing
|
|
31
44
|
potential_source_urls =
|
|
32
45
|
SOURCE_KEYS
|
|
33
|
-
.filter_map { |key| crates_listing.dig("crate", key) }
|
|
46
|
+
.filter_map { |key| T.must(crates_listing).dig("crate", key) }
|
|
34
47
|
|
|
35
48
|
source_url = potential_source_urls.find { |url| Source.from_url(url) }
|
|
36
49
|
Source.from_url(source_url)
|
|
37
50
|
end
|
|
38
51
|
|
|
52
|
+
sig { returns(T.nilable(Dependabot::Source)) }
|
|
39
53
|
def find_source_from_git_url
|
|
40
54
|
info = dependency.requirements.filter_map { |r| r[:source] }.first
|
|
41
55
|
|
|
@@ -43,6 +57,7 @@ module Dependabot
|
|
|
43
57
|
Source.from_url(url)
|
|
44
58
|
end
|
|
45
59
|
|
|
60
|
+
sig { returns(T.nilable(T::Hash[String, T.untyped])) }
|
|
46
61
|
def crates_listing
|
|
47
62
|
return @crates_listing unless @crates_listing.nil?
|
|
48
63
|
|
|
@@ -56,17 +71,21 @@ module Dependabot
|
|
|
56
71
|
@crates_listing = parse_response(response, index)
|
|
57
72
|
end
|
|
58
73
|
|
|
74
|
+
sig { params(index: String, info: T.nilable(T::Hash[String, T.untyped])).returns(T::Hash[String, String]) }
|
|
59
75
|
def build_headers(index, info)
|
|
60
76
|
hdrs = { "User-Agent" => "Dependabot (dependabot.com)" }
|
|
61
77
|
return hdrs if index == CRATES_IO_API
|
|
62
78
|
|
|
63
|
-
|
|
79
|
+
return hdrs if info.nil?
|
|
80
|
+
|
|
81
|
+
credentials.find { |cred| cred["type"] == "cargo_registry" && cred["registry"] == info["name"] }&.tap do |cred|
|
|
64
82
|
hdrs["Authorization"] = "Token #{cred['token']}"
|
|
65
83
|
end
|
|
66
84
|
|
|
67
85
|
hdrs
|
|
68
86
|
end
|
|
69
87
|
|
|
88
|
+
sig { params(url: String, headers: T::Hash[String, String]).returns(Excon::Response) }
|
|
70
89
|
def fetch_metadata(url, headers)
|
|
71
90
|
Excon.get(
|
|
72
91
|
url,
|
|
@@ -75,6 +94,7 @@ module Dependabot
|
|
|
75
94
|
)
|
|
76
95
|
end
|
|
77
96
|
|
|
97
|
+
sig { params(response: Excon::Response, index: String).returns(T::Hash[String, T.untyped]) }
|
|
78
98
|
def parse_response(response, index)
|
|
79
99
|
if index.start_with?("sparse+")
|
|
80
100
|
parsed_response = response.body.lines.map { |line| JSON.parse(line) }
|
|
@@ -84,6 +104,7 @@ module Dependabot
|
|
|
84
104
|
end
|
|
85
105
|
end
|
|
86
106
|
|
|
107
|
+
sig { params(dependency: Dependabot::Dependency, index: String).returns(String) }
|
|
87
108
|
def metadata_fetch_url(dependency, index)
|
|
88
109
|
return "#{index}/#{dependency.name}" if index == CRATES_IO_API
|
|
89
110
|
|
|
@@ -89,7 +89,7 @@ module Dependabot
|
|
|
89
89
|
return req_string if parts.count >= 3
|
|
90
90
|
|
|
91
91
|
# If we have no parts then the version is completely unlocked
|
|
92
|
-
return ">= 0" if parts.
|
|
92
|
+
return ">= 0" if parts.none?
|
|
93
93
|
|
|
94
94
|
# If we have fewer than three parts we do a partial match
|
|
95
95
|
parts << "0"
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strict
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
+
require "sorbet-runtime"
|
|
4
5
|
require "toml-rb"
|
|
6
|
+
|
|
5
7
|
require "dependabot/dependency_file"
|
|
6
8
|
require "dependabot/cargo/file_parser"
|
|
7
9
|
require "dependabot/cargo/update_checker"
|
|
@@ -12,6 +14,18 @@ module Dependabot
|
|
|
12
14
|
# This class takes a set of dependency files and sanitizes them for use
|
|
13
15
|
# in UpdateCheckers::Rust::Cargo.
|
|
14
16
|
class FilePreparer
|
|
17
|
+
extend T::Sig
|
|
18
|
+
|
|
19
|
+
sig do
|
|
20
|
+
params(
|
|
21
|
+
dependency_files: T::Array[Dependabot::DependencyFile],
|
|
22
|
+
dependency: Dependabot::Dependency,
|
|
23
|
+
unlock_requirement: T::Boolean,
|
|
24
|
+
replacement_git_pin: T.nilable(String),
|
|
25
|
+
latest_allowable_version: T.nilable(T.any(String, Gem::Version))
|
|
26
|
+
)
|
|
27
|
+
.void
|
|
28
|
+
end
|
|
15
29
|
def initialize(dependency_files:, dependency:,
|
|
16
30
|
unlock_requirement: true,
|
|
17
31
|
replacement_git_pin: nil,
|
|
@@ -21,8 +35,13 @@ module Dependabot
|
|
|
21
35
|
@unlock_requirement = unlock_requirement
|
|
22
36
|
@replacement_git_pin = replacement_git_pin
|
|
23
37
|
@latest_allowable_version = latest_allowable_version
|
|
38
|
+
@lower_bound_version = T.let(nil, T.nilable(T.any(String, Integer)))
|
|
39
|
+
@manifest_files = T.let(nil, T.nilable(T::Array[Dependabot::DependencyFile]))
|
|
40
|
+
@lockfile = T.let(nil, T.nilable(Dependabot::DependencyFile))
|
|
41
|
+
@toolchain = T.let(nil, T.nilable(Dependabot::DependencyFile))
|
|
24
42
|
end
|
|
25
43
|
|
|
44
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
26
45
|
def prepared_dependency_files
|
|
27
46
|
files = []
|
|
28
47
|
files += manifest_files.map do |file|
|
|
@@ -39,21 +58,31 @@ module Dependabot
|
|
|
39
58
|
|
|
40
59
|
private
|
|
41
60
|
|
|
61
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
42
62
|
attr_reader :dependency_files
|
|
63
|
+
|
|
64
|
+
sig { returns(Dependabot::Dependency) }
|
|
43
65
|
attr_reader :dependency
|
|
66
|
+
|
|
67
|
+
sig { returns(T.nilable(String)) }
|
|
44
68
|
attr_reader :replacement_git_pin
|
|
69
|
+
|
|
70
|
+
sig { returns(T.nilable(T.any(String, Gem::Version))) }
|
|
45
71
|
attr_reader :latest_allowable_version
|
|
46
72
|
|
|
73
|
+
sig { returns(T::Boolean) }
|
|
47
74
|
def unlock_requirement?
|
|
48
75
|
@unlock_requirement
|
|
49
76
|
end
|
|
50
77
|
|
|
78
|
+
sig { returns(T::Boolean) }
|
|
51
79
|
def replace_git_pin?
|
|
52
80
|
!replacement_git_pin.nil?
|
|
53
81
|
end
|
|
54
82
|
|
|
83
|
+
sig { params(file: Dependabot::DependencyFile).returns(String) }
|
|
55
84
|
def manifest_content_for_update_check(file)
|
|
56
|
-
content = file.content
|
|
85
|
+
content = T.must(file.content)
|
|
57
86
|
|
|
58
87
|
unless file.support_file?
|
|
59
88
|
content = replace_version_constraint(content, file.name)
|
|
@@ -67,6 +96,7 @@ module Dependabot
|
|
|
67
96
|
|
|
68
97
|
# NOTE: We don't need to care about formatting in this method, since
|
|
69
98
|
# we're only using the manifest to find the latest resolvable version
|
|
99
|
+
sig { params(content: String, filename: String).returns(String) }
|
|
70
100
|
def replace_version_constraint(content, filename)
|
|
71
101
|
parsed_manifest = TomlRB.parse(content)
|
|
72
102
|
|
|
@@ -89,6 +119,7 @@ module Dependabot
|
|
|
89
119
|
TomlRB.dump(parsed_manifest)
|
|
90
120
|
end
|
|
91
121
|
|
|
122
|
+
sig { params(parsed_manifest: T::Hash[String, T.untyped], filename: String).void }
|
|
92
123
|
def replace_req_on_target_specific_deps!(parsed_manifest, filename)
|
|
93
124
|
parsed_manifest.fetch("target", {}).each do |target, _|
|
|
94
125
|
Cargo::FileParser::DEPENDENCY_TYPES.each do |type|
|
|
@@ -114,6 +145,7 @@ module Dependabot
|
|
|
114
145
|
end
|
|
115
146
|
end
|
|
116
147
|
|
|
148
|
+
sig { params(content: String).returns(String) }
|
|
117
149
|
def replace_git_pin(content)
|
|
118
150
|
parsed_manifest = TomlRB.parse(content)
|
|
119
151
|
|
|
@@ -121,7 +153,7 @@ module Dependabot
|
|
|
121
153
|
dependency_names_for_type(parsed_manifest, type).each do |name|
|
|
122
154
|
req = parsed_manifest.dig(type, name)
|
|
123
155
|
next unless req.is_a?(Hash)
|
|
124
|
-
next unless [req["tag"], req["rev"]].compact.uniq.
|
|
156
|
+
next unless [req["tag"], req["rev"]].compact.uniq.one?
|
|
125
157
|
|
|
126
158
|
parsed_manifest[type][name]["tag"] = replacement_git_pin if req["tag"]
|
|
127
159
|
|
|
@@ -134,6 +166,7 @@ module Dependabot
|
|
|
134
166
|
TomlRB.dump(parsed_manifest)
|
|
135
167
|
end
|
|
136
168
|
|
|
169
|
+
sig { params(parsed_manifest: T::Hash[String, T.untyped]).void }
|
|
137
170
|
def replace_git_pin_on_target_specific_deps!(parsed_manifest)
|
|
138
171
|
parsed_manifest.fetch("target", {}).each do |target, _|
|
|
139
172
|
Cargo::FileParser::DEPENDENCY_TYPES.each do |type|
|
|
@@ -146,7 +179,7 @@ module Dependabot
|
|
|
146
179
|
dependency_names.each do |name|
|
|
147
180
|
req = parsed_manifest.dig("target", target, type, name)
|
|
148
181
|
next unless req.is_a?(Hash)
|
|
149
|
-
next unless [req["tag"], req["rev"]].compact.uniq.
|
|
182
|
+
next unless [req["tag"], req["rev"]].compact.uniq.one?
|
|
150
183
|
|
|
151
184
|
if req["tag"]
|
|
152
185
|
parsed_manifest["target"][target][type][name]["tag"] =
|
|
@@ -162,6 +195,7 @@ module Dependabot
|
|
|
162
195
|
end
|
|
163
196
|
end
|
|
164
197
|
|
|
198
|
+
sig { params(content: String).returns(String) }
|
|
165
199
|
def replace_ssh_urls(content)
|
|
166
200
|
parsed_manifest = TomlRB.parse(content)
|
|
167
201
|
|
|
@@ -178,6 +212,7 @@ module Dependabot
|
|
|
178
212
|
TomlRB.dump(parsed_manifest)
|
|
179
213
|
end
|
|
180
214
|
|
|
215
|
+
sig { params(filename: String).returns(String) }
|
|
181
216
|
def temporary_requirement_for_resolution(filename)
|
|
182
217
|
original_req = dependency.requirements
|
|
183
218
|
.find { |r| r.fetch(:file) == filename }
|
|
@@ -201,6 +236,7 @@ module Dependabot
|
|
|
201
236
|
end
|
|
202
237
|
|
|
203
238
|
# rubocop:disable Metrics/PerceivedComplexity
|
|
239
|
+
sig { returns(T.any(String, Integer)) }
|
|
204
240
|
def lower_bound_version
|
|
205
241
|
@lower_bound_version ||=
|
|
206
242
|
if git_dependency? && git_dependency_version
|
|
@@ -221,16 +257,18 @@ module Dependabot
|
|
|
221
257
|
end
|
|
222
258
|
# rubocop:enable Metrics/PerceivedComplexity
|
|
223
259
|
|
|
260
|
+
sig { returns(T.nilable(String)) }
|
|
224
261
|
def git_dependency_version
|
|
225
262
|
return unless lockfile
|
|
226
263
|
|
|
227
|
-
TomlRB.parse(lockfile.content)
|
|
264
|
+
TomlRB.parse(T.must(lockfile).content)
|
|
228
265
|
.fetch("package", [])
|
|
229
266
|
.select { |p| p["name"] == dependency.name }
|
|
230
267
|
.find { |p| p["source"].end_with?(dependency.version) }
|
|
231
268
|
.fetch("version")
|
|
232
269
|
end
|
|
233
270
|
|
|
271
|
+
sig { params(parsed_manifest: T::Hash[String, T.untyped], type: String).returns(T::Array[String]) }
|
|
234
272
|
def dependency_names_for_type(parsed_manifest, type)
|
|
235
273
|
names = []
|
|
236
274
|
parsed_manifest.fetch(type, {}).each do |nm, req|
|
|
@@ -241,6 +279,9 @@ module Dependabot
|
|
|
241
279
|
names
|
|
242
280
|
end
|
|
243
281
|
|
|
282
|
+
sig do
|
|
283
|
+
params(parsed_manifest: T::Hash[String, T.untyped], type: String, target: String).returns(T::Array[String])
|
|
284
|
+
end
|
|
244
285
|
def dependency_names_for_type_and_target(parsed_manifest, type, target)
|
|
245
286
|
names = []
|
|
246
287
|
(parsed_manifest.dig("target", target, type) || {}).each do |nm, req|
|
|
@@ -251,13 +292,16 @@ module Dependabot
|
|
|
251
292
|
names
|
|
252
293
|
end
|
|
253
294
|
|
|
295
|
+
sig { params(name: String, declaration: T.untyped).returns(String) }
|
|
254
296
|
def name_from_declaration(name, declaration)
|
|
255
297
|
return name if declaration.is_a?(String)
|
|
298
|
+
|
|
256
299
|
raise "Unexpected dependency declaration: #{declaration}" unless declaration.is_a?(Hash)
|
|
257
300
|
|
|
258
301
|
declaration.fetch("package", name)
|
|
259
302
|
end
|
|
260
303
|
|
|
304
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
261
305
|
def manifest_files
|
|
262
306
|
@manifest_files ||=
|
|
263
307
|
dependency_files.select { |f| f.name.end_with?("Cargo.toml") }
|
|
@@ -267,15 +311,18 @@ module Dependabot
|
|
|
267
311
|
@manifest_files
|
|
268
312
|
end
|
|
269
313
|
|
|
314
|
+
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
|
270
315
|
def lockfile
|
|
271
316
|
@lockfile ||= dependency_files.find { |f| f.name == "Cargo.lock" }
|
|
272
317
|
end
|
|
273
318
|
|
|
319
|
+
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
|
274
320
|
def toolchain
|
|
275
321
|
@toolchain ||=
|
|
276
322
|
dependency_files.find { |f| f.name == "rust-toolchain" }
|
|
277
323
|
end
|
|
278
324
|
|
|
325
|
+
sig { returns(T::Boolean) }
|
|
279
326
|
def git_dependency?
|
|
280
327
|
GitCommitChecker
|
|
281
328
|
.new(dependency: dependency, credentials: [])
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strict
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
################################################################################
|
|
@@ -25,26 +25,35 @@ module Dependabot
|
|
|
25
25
|
VERSION_REGEX = /[0-9]+(?:\.[A-Za-z0-9\-*]+)*/
|
|
26
26
|
ALLOWED_UPDATE_STRATEGIES = T.let(
|
|
27
27
|
[
|
|
28
|
-
RequirementsUpdateStrategy::LockfileOnly,
|
|
29
|
-
RequirementsUpdateStrategy::BumpVersions,
|
|
30
|
-
RequirementsUpdateStrategy::BumpVersionsIfNecessary
|
|
28
|
+
Dependabot::RequirementsUpdateStrategy::LockfileOnly,
|
|
29
|
+
Dependabot::RequirementsUpdateStrategy::BumpVersions,
|
|
30
|
+
Dependabot::RequirementsUpdateStrategy::BumpVersionsIfNecessary
|
|
31
31
|
].freeze,
|
|
32
32
|
T::Array[Dependabot::RequirementsUpdateStrategy]
|
|
33
33
|
)
|
|
34
34
|
|
|
35
|
+
sig do
|
|
36
|
+
params(
|
|
37
|
+
requirements: T::Array[T::Hash[Symbol, T.untyped]],
|
|
38
|
+
updated_source: T.nilable(T::Hash[T.any(String, Symbol), T.untyped]),
|
|
39
|
+
update_strategy: Dependabot::RequirementsUpdateStrategy,
|
|
40
|
+
target_version: T.nilable(T.any(String, Gem::Version))
|
|
41
|
+
).void
|
|
42
|
+
end
|
|
35
43
|
def initialize(requirements:, updated_source:, update_strategy:,
|
|
36
44
|
target_version:)
|
|
37
|
-
@requirements = requirements
|
|
38
|
-
@updated_source = updated_source
|
|
39
|
-
@update_strategy = update_strategy
|
|
45
|
+
@requirements = T.let(requirements, T::Array[T::Hash[Symbol, T.untyped]])
|
|
46
|
+
@updated_source = T.let(updated_source, T.nilable(T::Hash[T.any(String, Symbol), T.untyped]))
|
|
47
|
+
@update_strategy = T.let(update_strategy, Dependabot::RequirementsUpdateStrategy)
|
|
40
48
|
|
|
41
49
|
check_update_strategy
|
|
42
50
|
|
|
43
51
|
return unless target_version && version_class.correct?(target_version)
|
|
44
52
|
|
|
45
|
-
@target_version = version_class.new(target_version)
|
|
53
|
+
@target_version = T.let(version_class.new(target_version), Gem::Version)
|
|
46
54
|
end
|
|
47
55
|
|
|
56
|
+
sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
|
|
48
57
|
def updated_requirements
|
|
49
58
|
return requirements if update_strategy.lockfile_only?
|
|
50
59
|
|
|
@@ -57,7 +66,7 @@ module Dependabot
|
|
|
57
66
|
next req if req[:requirement].nil?
|
|
58
67
|
|
|
59
68
|
# TODO: Add a RequirementsUpdateStrategy::WidenRanges options
|
|
60
|
-
if update_strategy == RequirementsUpdateStrategy::BumpVersionsIfNecessary
|
|
69
|
+
if update_strategy == Dependabot::RequirementsUpdateStrategy::BumpVersionsIfNecessary
|
|
61
70
|
update_version_requirement_if_needed(req)
|
|
62
71
|
else
|
|
63
72
|
update_version_requirement(req)
|
|
@@ -67,17 +76,26 @@ module Dependabot
|
|
|
67
76
|
|
|
68
77
|
private
|
|
69
78
|
|
|
79
|
+
sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
|
|
70
80
|
attr_reader :requirements
|
|
81
|
+
|
|
82
|
+
sig { returns(T.nilable(T::Hash[T.any(String, Symbol), T.untyped])) }
|
|
71
83
|
attr_reader :updated_source
|
|
84
|
+
|
|
85
|
+
sig { returns(Dependabot::RequirementsUpdateStrategy) }
|
|
72
86
|
attr_reader :update_strategy
|
|
87
|
+
|
|
88
|
+
sig { returns(T.nilable(Gem::Version)) }
|
|
73
89
|
attr_reader :target_version
|
|
74
90
|
|
|
91
|
+
sig { void }
|
|
75
92
|
def check_update_strategy
|
|
76
93
|
return if ALLOWED_UPDATE_STRATEGIES.include?(update_strategy)
|
|
77
94
|
|
|
78
95
|
raise "Unknown update strategy: #{update_strategy}"
|
|
79
96
|
end
|
|
80
97
|
|
|
98
|
+
sig { params(req: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
|
|
81
99
|
def update_version_requirement(req)
|
|
82
100
|
string_reqs = req[:requirement].split(",").map(&:strip)
|
|
83
101
|
|
|
@@ -100,15 +118,17 @@ module Dependabot
|
|
|
100
118
|
req.merge(requirement: new_requirement)
|
|
101
119
|
end
|
|
102
120
|
|
|
121
|
+
sig { params(req: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
|
|
103
122
|
def update_version_requirement_if_needed(req)
|
|
104
123
|
string_reqs = req[:requirement].split(",").map(&:strip)
|
|
105
|
-
ruby_reqs = string_reqs.map { |r| Cargo::Requirement.new(r) }
|
|
124
|
+
ruby_reqs = string_reqs.map { |r| Dependabot::Cargo::Requirement.new(r) }
|
|
106
125
|
|
|
107
126
|
return req if ruby_reqs.all? { |r| r.satisfied_by?(target_version) }
|
|
108
127
|
|
|
109
128
|
update_version_requirement(req)
|
|
110
129
|
end
|
|
111
130
|
|
|
131
|
+
sig { params(req_string: String).returns(String) }
|
|
112
132
|
def update_version_string(req_string)
|
|
113
133
|
new_target_parts = target_version.to_s.sub(/\+.*/, "").split(".")
|
|
114
134
|
req_string.sub(VERSION_REGEX) do |old_version|
|
|
@@ -123,19 +143,22 @@ module Dependabot
|
|
|
123
143
|
end
|
|
124
144
|
end
|
|
125
145
|
|
|
146
|
+
sig { params(string_reqs: T::Array[String]).returns(T.nilable(String)) }
|
|
126
147
|
def non_range_req(string_reqs)
|
|
127
148
|
string_reqs.find { |r| r.include?("*") || r.match?(/^[\d~^]/) }
|
|
128
149
|
end
|
|
129
150
|
|
|
151
|
+
sig { params(string_reqs: T::Array[String]).returns(T.nilable(String)) }
|
|
130
152
|
def exact_req(string_reqs)
|
|
131
|
-
string_reqs.find { |r| Cargo::Requirement.new(r).exact? }
|
|
153
|
+
string_reqs.find { |r| Dependabot::Cargo::Requirement.new(r).exact? }
|
|
132
154
|
end
|
|
133
155
|
|
|
156
|
+
sig { params(string_reqs: T::Array[String]).returns(T.any(String, Symbol)) }
|
|
134
157
|
def update_range_requirements(string_reqs)
|
|
135
158
|
string_reqs.map do |req|
|
|
136
159
|
next req unless req.match?(/[<>]/)
|
|
137
160
|
|
|
138
|
-
ruby_req = Cargo::Requirement.new(req)
|
|
161
|
+
ruby_req = Dependabot::Cargo::Requirement.new(req)
|
|
139
162
|
next req if ruby_req.satisfied_by?(target_version)
|
|
140
163
|
|
|
141
164
|
raise UnfixableRequirement if req.start_with?(">")
|
|
@@ -144,7 +167,7 @@ module Dependabot
|
|
|
144
167
|
if req.start_with?("<=")
|
|
145
168
|
update_version_string(old_version)
|
|
146
169
|
else
|
|
147
|
-
update_greatest_version(old_version, target_version)
|
|
170
|
+
update_greatest_version(old_version, T.must(target_version))
|
|
148
171
|
end
|
|
149
172
|
end
|
|
150
173
|
end.join(", ")
|
|
@@ -152,26 +175,28 @@ module Dependabot
|
|
|
152
175
|
:unfixable
|
|
153
176
|
end
|
|
154
177
|
|
|
178
|
+
sig { params(old_version: String, version_to_be_permitted: Gem::Version).returns(String) }
|
|
155
179
|
def update_greatest_version(old_version, version_to_be_permitted)
|
|
156
180
|
version = version_class.new(old_version)
|
|
157
181
|
version = version.release if version.prerelease?
|
|
158
182
|
|
|
159
183
|
index_to_update =
|
|
160
|
-
version.segments.map.with_index { |seg, i| seg.zero? ? 0 : i }.max
|
|
184
|
+
version.segments.map.with_index { |seg, i| seg.to_i.zero? ? 0 : i }.max
|
|
161
185
|
|
|
162
186
|
version.segments.map.with_index do |_, index|
|
|
163
187
|
if index < index_to_update
|
|
164
188
|
version_to_be_permitted.segments[index]
|
|
165
189
|
elsif index == index_to_update
|
|
166
|
-
version_to_be_permitted.segments[index] + 1
|
|
190
|
+
version_to_be_permitted.segments[index].to_i + 1
|
|
167
191
|
else
|
|
168
192
|
0
|
|
169
193
|
end
|
|
170
194
|
end.join(".")
|
|
171
195
|
end
|
|
172
196
|
|
|
197
|
+
sig { returns(T.class_of(Dependabot::Cargo::Version)) }
|
|
173
198
|
def version_class
|
|
174
|
-
Cargo::Version
|
|
199
|
+
Dependabot::Cargo::Version
|
|
175
200
|
end
|
|
176
201
|
end
|
|
177
202
|
end
|
|
@@ -14,6 +14,7 @@ module Dependabot
|
|
|
14
14
|
class UpdateChecker
|
|
15
15
|
class VersionResolver # rubocop:disable Metrics/ClassLength
|
|
16
16
|
extend T::Sig
|
|
17
|
+
|
|
17
18
|
UNABLE_TO_UPDATE = /Unable to update (?<url>.*?)$/
|
|
18
19
|
BRANCH_NOT_FOUND_REGEX = /#{UNABLE_TO_UPDATE}.*to find branch `(?<branch>[^`]+)`/m
|
|
19
20
|
REVSPEC_PATTERN = /revspec '.*' not found/
|
|
@@ -133,7 +134,7 @@ module Dependabot
|
|
|
133
134
|
dependency.version
|
|
134
135
|
end
|
|
135
136
|
|
|
136
|
-
if spec_options.
|
|
137
|
+
if spec_options.one? { |s| s.end_with?(T.must(ver)) }
|
|
137
138
|
@custom_specification = spec_options.find { |s| s.end_with?(T.must(ver)) }
|
|
138
139
|
return true
|
|
139
140
|
elsif spec_options.count { |s| s.end_with?(T.must(ver)) } > 1
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strict
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
+
require "sorbet-runtime"
|
|
5
|
+
|
|
4
6
|
require "dependabot/git_commit_checker"
|
|
5
7
|
require "dependabot/requirements_update_strategy"
|
|
6
8
|
require "dependabot/update_checkers"
|
|
@@ -9,15 +11,18 @@ require "dependabot/update_checkers/base"
|
|
|
9
11
|
module Dependabot
|
|
10
12
|
module Cargo
|
|
11
13
|
class UpdateChecker < Dependabot::UpdateCheckers::Base
|
|
14
|
+
extend T::Sig
|
|
15
|
+
|
|
12
16
|
require_relative "update_checker/latest_version_finder"
|
|
13
17
|
require_relative "update_checker/requirements_updater"
|
|
14
18
|
require_relative "update_checker/version_resolver"
|
|
15
19
|
require_relative "update_checker/file_preparer"
|
|
16
20
|
|
|
21
|
+
sig { override.returns(T.nilable(T.any(String, Gem::Version))) }
|
|
17
22
|
def latest_version
|
|
18
23
|
return if path_dependency?
|
|
19
24
|
|
|
20
|
-
@latest_version =
|
|
25
|
+
@latest_version = T.let(
|
|
21
26
|
if git_dependency?
|
|
22
27
|
latest_version_for_git_dependency
|
|
23
28
|
elsif git_subdependency?
|
|
@@ -26,48 +31,64 @@ module Dependabot
|
|
|
26
31
|
nil
|
|
27
32
|
else
|
|
28
33
|
latest_version_finder.latest_version
|
|
29
|
-
end
|
|
34
|
+
end,
|
|
35
|
+
T.nilable(T.any(String, Gem::Version))
|
|
36
|
+
)
|
|
30
37
|
end
|
|
31
38
|
|
|
39
|
+
sig { override.returns(T.nilable(T.any(String, Gem::Version))) }
|
|
32
40
|
def latest_resolvable_version
|
|
33
41
|
return if path_dependency?
|
|
34
42
|
|
|
35
|
-
@latest_resolvable_version
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
@latest_resolvable_version = T.let(
|
|
44
|
+
@latest_resolvable_version ||
|
|
45
|
+
if git_dependency?
|
|
46
|
+
latest_resolvable_version_for_git_dependency
|
|
47
|
+
elsif git_subdependency?
|
|
48
|
+
# TODO: Dependabot can't update git sub-dependencies yet, because
|
|
49
|
+
# they can't be passed to GitCommitChecker.
|
|
50
|
+
nil
|
|
51
|
+
else
|
|
52
|
+
fetch_latest_resolvable_version(unlock_requirement: true)
|
|
53
|
+
end,
|
|
54
|
+
T.nilable(T.any(String, Gem::Version))
|
|
55
|
+
)
|
|
45
56
|
end
|
|
46
57
|
|
|
58
|
+
sig { override.returns(T.nilable(Gem::Version)) }
|
|
47
59
|
def lowest_security_fix_version
|
|
48
60
|
latest_version_finder.lowest_security_fix_version
|
|
49
61
|
end
|
|
50
62
|
|
|
63
|
+
sig { override.returns(T.nilable(Gem::Version)) }
|
|
51
64
|
def lowest_resolvable_security_fix_version
|
|
52
65
|
raise "Dependency not vulnerable!" unless vulnerable?
|
|
53
66
|
|
|
54
67
|
return @lowest_resolvable_security_fix_version if defined?(@lowest_resolvable_security_fix_version)
|
|
55
68
|
|
|
56
|
-
|
|
57
|
-
|
|
69
|
+
result = fetch_lowest_resolvable_security_fix_version
|
|
70
|
+
@lowest_resolvable_security_fix_version = T.let(
|
|
71
|
+
result.is_a?(Gem::Version) ? result : nil,
|
|
72
|
+
T.nilable(Gem::Version)
|
|
73
|
+
)
|
|
58
74
|
end
|
|
59
75
|
|
|
76
|
+
sig { override.returns(T.nilable(T.any(String, Gem::Version))) }
|
|
60
77
|
def latest_resolvable_version_with_no_unlock
|
|
61
78
|
return if path_dependency?
|
|
62
79
|
|
|
63
|
-
@latest_resolvable_version_with_no_unlock
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
80
|
+
@latest_resolvable_version_with_no_unlock = T.let(
|
|
81
|
+
@latest_resolvable_version_with_no_unlock ||
|
|
82
|
+
if git_dependency?
|
|
83
|
+
latest_resolvable_commit_with_unchanged_git_source
|
|
84
|
+
else
|
|
85
|
+
fetch_latest_resolvable_version(unlock_requirement: false)
|
|
86
|
+
end,
|
|
87
|
+
T.nilable(T.any(String, Gem::Version))
|
|
88
|
+
)
|
|
69
89
|
end
|
|
70
90
|
|
|
91
|
+
sig { override.returns(T::Array[T::Hash[Symbol, T.untyped]]) }
|
|
71
92
|
def updated_requirements
|
|
72
93
|
RequirementsUpdater.new(
|
|
73
94
|
requirements: dependency.requirements,
|
|
@@ -77,10 +98,12 @@ module Dependabot
|
|
|
77
98
|
).updated_requirements
|
|
78
99
|
end
|
|
79
100
|
|
|
101
|
+
sig { override.returns(T::Boolean) }
|
|
80
102
|
def requirements_unlocked_or_can_be?
|
|
81
103
|
!requirements_update_strategy.lockfile_only?
|
|
82
104
|
end
|
|
83
105
|
|
|
106
|
+
sig { returns(Dependabot::RequirementsUpdateStrategy) }
|
|
84
107
|
def requirements_update_strategy
|
|
85
108
|
# If passed in as an option (in the base class) honour that option
|
|
86
109
|
return @requirements_update_strategy if @requirements_update_strategy
|
|
@@ -91,15 +114,18 @@ module Dependabot
|
|
|
91
114
|
|
|
92
115
|
private
|
|
93
116
|
|
|
117
|
+
sig { override.returns(T::Boolean) }
|
|
94
118
|
def latest_version_resolvable_with_full_unlock?
|
|
95
119
|
# Full unlock checks aren't implemented for Rust (yet)
|
|
96
120
|
false
|
|
97
121
|
end
|
|
98
122
|
|
|
123
|
+
sig { override.returns(T::Array[Dependabot::Dependency]) }
|
|
99
124
|
def updated_dependencies_after_full_unlock
|
|
100
125
|
raise NotImplementedError
|
|
101
126
|
end
|
|
102
127
|
|
|
128
|
+
sig { returns(T.nilable(String)) }
|
|
103
129
|
def target_version
|
|
104
130
|
# Unless we can resolve a new version, don't try to update to a latest
|
|
105
131
|
# version (even for a library) as we rely on a resolvable version being
|
|
@@ -109,29 +135,37 @@ module Dependabot
|
|
|
109
135
|
library? ? latest_version&.to_s : preferred_resolvable_version.to_s
|
|
110
136
|
end
|
|
111
137
|
|
|
138
|
+
sig { returns(T::Boolean) }
|
|
112
139
|
def library?
|
|
113
140
|
# If it has a lockfile, treat it as an application. Otherwise treat it
|
|
114
141
|
# as a library.
|
|
115
142
|
dependency_files.none? { |f| f.name == "Cargo.lock" }
|
|
116
143
|
end
|
|
117
144
|
|
|
145
|
+
sig { returns(LatestVersionFinder) }
|
|
118
146
|
def latest_version_finder
|
|
119
|
-
@latest_version_finder
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
147
|
+
@latest_version_finder = T.let(
|
|
148
|
+
@latest_version_finder ||
|
|
149
|
+
LatestVersionFinder.new(
|
|
150
|
+
dependency: dependency,
|
|
151
|
+
dependency_files: dependency_files,
|
|
152
|
+
credentials: credentials,
|
|
153
|
+
ignored_versions: ignored_versions,
|
|
154
|
+
security_advisories: security_advisories,
|
|
155
|
+
cooldown_options: update_cooldown,
|
|
156
|
+
raise_on_ignored: raise_on_ignored
|
|
157
|
+
),
|
|
158
|
+
T.nilable(LatestVersionFinder)
|
|
159
|
+
)
|
|
160
|
+
T.must(@latest_version_finder)
|
|
129
161
|
end
|
|
130
162
|
|
|
163
|
+
sig { returns(T.nilable(T.any(String, Gem::Version))) }
|
|
131
164
|
def latest_version_for_git_dependency
|
|
132
165
|
latest_git_version_sha
|
|
133
166
|
end
|
|
134
167
|
|
|
168
|
+
sig { returns(T.nilable(T.any(String, Gem::Version))) }
|
|
135
169
|
def latest_git_version_sha
|
|
136
170
|
# If the gem isn't pinned, the latest version is just the latest
|
|
137
171
|
# commit for the specified branch.
|
|
@@ -150,6 +184,7 @@ module Dependabot
|
|
|
150
184
|
dependency.version
|
|
151
185
|
end
|
|
152
186
|
|
|
187
|
+
sig { returns(T.nilable(T.any(String, Gem::Version))) }
|
|
153
188
|
def latest_resolvable_version_for_git_dependency
|
|
154
189
|
# If the gem isn't pinned, the latest version is just the latest
|
|
155
190
|
# commit for the specified branch.
|
|
@@ -161,21 +196,28 @@ module Dependabot
|
|
|
161
196
|
if git_commit_checker.pinned_ref_looks_like_version? &&
|
|
162
197
|
latest_git_tag_is_resolvable?
|
|
163
198
|
new_tag = git_commit_checker.local_tag_for_latest_version
|
|
164
|
-
return new_tag.fetch(:commit_sha)
|
|
199
|
+
return T.must(new_tag).fetch(:commit_sha)
|
|
165
200
|
end
|
|
166
201
|
|
|
167
202
|
# If the dependency is pinned then there's nothing we can do.
|
|
168
203
|
dependency.version
|
|
169
204
|
end
|
|
170
205
|
|
|
206
|
+
sig { returns(T::Boolean) }
|
|
171
207
|
def latest_git_tag_is_resolvable?
|
|
172
|
-
|
|
208
|
+
unless defined?(@latest_git_tag_is_resolvable_checked)
|
|
209
|
+
@latest_git_tag_is_resolvable_checked = T.let(nil,
|
|
210
|
+
T.nilable(T::Boolean))
|
|
211
|
+
end
|
|
212
|
+
@git_tag_resolvable = T.let(nil, T.nilable(T::Boolean)) unless defined?(@git_tag_resolvable)
|
|
213
|
+
|
|
214
|
+
return T.must(@git_tag_resolvable) if @latest_git_tag_is_resolvable_checked
|
|
173
215
|
|
|
174
216
|
@latest_git_tag_is_resolvable_checked = true
|
|
175
217
|
|
|
176
218
|
return false if git_commit_checker.local_tag_for_latest_version.nil?
|
|
177
219
|
|
|
178
|
-
replacement_tag = git_commit_checker.local_tag_for_latest_version
|
|
220
|
+
replacement_tag = T.must(git_commit_checker.local_tag_for_latest_version)
|
|
179
221
|
|
|
180
222
|
prepared_files = FilePreparer.new(
|
|
181
223
|
dependency_files: dependency_files,
|
|
@@ -197,6 +239,7 @@ module Dependabot
|
|
|
197
239
|
@git_tag_resolvable = false
|
|
198
240
|
end
|
|
199
241
|
|
|
242
|
+
sig { returns(T.nilable(T.any(String, Gem::Version))) }
|
|
200
243
|
def latest_resolvable_commit_with_unchanged_git_source
|
|
201
244
|
fetch_latest_resolvable_version(unlock_requirement: false)
|
|
202
245
|
rescue SharedHelpers::HelperSubprocessFailed => e
|
|
@@ -207,6 +250,7 @@ module Dependabot
|
|
|
207
250
|
raise e
|
|
208
251
|
end
|
|
209
252
|
|
|
253
|
+
sig { params(unlock_requirement: T::Boolean).returns(T.nilable(T.any(String, Gem::Version))) }
|
|
210
254
|
def fetch_latest_resolvable_version(unlock_requirement:)
|
|
211
255
|
prepared_files = FilePreparer.new(
|
|
212
256
|
dependency_files: dependency_files,
|
|
@@ -223,6 +267,7 @@ module Dependabot
|
|
|
223
267
|
).latest_resolvable_version
|
|
224
268
|
end
|
|
225
269
|
|
|
270
|
+
sig { returns(T.nilable(T.any(String, Gem::Version))) }
|
|
226
271
|
def fetch_lowest_resolvable_security_fix_version
|
|
227
272
|
fix_version = lowest_security_fix_version
|
|
228
273
|
return latest_resolvable_version if fix_version.nil?
|
|
@@ -248,6 +293,7 @@ module Dependabot
|
|
|
248
293
|
latest_resolvable_version
|
|
249
294
|
end
|
|
250
295
|
|
|
296
|
+
sig { returns(T.nilable(T::Hash[T.any(String, Symbol), T.untyped])) }
|
|
251
297
|
def updated_source
|
|
252
298
|
# Never need to update source, unless a git_dependency
|
|
253
299
|
return dependency_source_details unless git_dependency?
|
|
@@ -255,38 +301,47 @@ module Dependabot
|
|
|
255
301
|
# Update the git tag if updating a pinned version
|
|
256
302
|
if git_commit_checker.pinned_ref_looks_like_version? &&
|
|
257
303
|
latest_git_tag_is_resolvable?
|
|
258
|
-
new_tag = git_commit_checker.local_tag_for_latest_version
|
|
259
|
-
return dependency_source_details.merge(ref: new_tag.fetch(:tag))
|
|
304
|
+
new_tag = T.must(git_commit_checker.local_tag_for_latest_version)
|
|
305
|
+
return T.must(dependency_source_details).merge(ref: new_tag.fetch(:tag))
|
|
260
306
|
end
|
|
261
307
|
|
|
262
308
|
# Otherwise return the original source
|
|
263
309
|
dependency_source_details
|
|
264
310
|
end
|
|
265
311
|
|
|
312
|
+
sig { returns(T.nilable(T::Hash[T.any(String, Symbol), T.untyped])) }
|
|
266
313
|
def dependency_source_details
|
|
267
314
|
dependency.source_details
|
|
268
315
|
end
|
|
269
316
|
|
|
317
|
+
sig { returns(T::Boolean) }
|
|
270
318
|
def git_dependency?
|
|
271
319
|
git_commit_checker.git_dependency?
|
|
272
320
|
end
|
|
273
321
|
|
|
322
|
+
sig { returns(T::Boolean) }
|
|
274
323
|
def git_subdependency?
|
|
275
324
|
return false if dependency.top_level?
|
|
276
325
|
|
|
277
326
|
!version_class.correct?(dependency.version)
|
|
278
327
|
end
|
|
279
328
|
|
|
329
|
+
sig { returns(T::Boolean) }
|
|
280
330
|
def path_dependency?
|
|
281
331
|
dependency.source_type == "path"
|
|
282
332
|
end
|
|
283
333
|
|
|
334
|
+
sig { returns(GitCommitChecker) }
|
|
284
335
|
def git_commit_checker
|
|
285
|
-
@git_commit_checker
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
336
|
+
@git_commit_checker = T.let(
|
|
337
|
+
@git_commit_checker ||
|
|
338
|
+
GitCommitChecker.new(
|
|
339
|
+
dependency: dependency,
|
|
340
|
+
credentials: credentials
|
|
341
|
+
),
|
|
342
|
+
T.nilable(GitCommitChecker)
|
|
343
|
+
)
|
|
344
|
+
T.must(@git_commit_checker)
|
|
290
345
|
end
|
|
291
346
|
end
|
|
292
347
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strong
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
+
require "sorbet-runtime"
|
|
4
5
|
require "dependabot/version"
|
|
5
6
|
require "dependabot/utils"
|
|
6
7
|
|
|
@@ -11,26 +12,32 @@ require "dependabot/utils"
|
|
|
11
12
|
module Dependabot
|
|
12
13
|
module Cargo
|
|
13
14
|
class Version < Dependabot::Version
|
|
15
|
+
extend T::Sig
|
|
16
|
+
|
|
14
17
|
VERSION_PATTERN = '[0-9]+(?>\.[0-9a-zA-Z]+)*' \
|
|
15
18
|
'(-[0-9A-Za-z-]+(\.[0-9a-zA-Z-]+)*)?' \
|
|
16
19
|
'(\+[0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*)?'
|
|
17
20
|
ANCHORED_VERSION_PATTERN = /\A\s*(#{VERSION_PATTERN})?\s*\z/
|
|
18
21
|
|
|
22
|
+
sig { override.params(version: VersionParameter).void }
|
|
19
23
|
def initialize(version)
|
|
20
|
-
@version_string = version.to_s
|
|
24
|
+
@version_string = T.let(version.to_s, String)
|
|
21
25
|
version = version.to_s.split("+").first if version.to_s.include?("+")
|
|
22
26
|
|
|
23
27
|
super
|
|
24
28
|
end
|
|
25
29
|
|
|
30
|
+
sig { override.returns(String) }
|
|
26
31
|
def to_s
|
|
27
32
|
@version_string
|
|
28
33
|
end
|
|
29
34
|
|
|
35
|
+
sig { override.returns(String) }
|
|
30
36
|
def inspect # :nodoc:
|
|
31
37
|
"#<#{self.class} #{@version_string}>"
|
|
32
38
|
end
|
|
33
39
|
|
|
40
|
+
sig { override.params(version: VersionParameter).returns(T::Boolean) }
|
|
34
41
|
def self.correct?(version)
|
|
35
42
|
return false if version.nil?
|
|
36
43
|
|
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.333.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.333.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.333.0
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: debug
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -211,14 +211,14 @@ dependencies:
|
|
|
211
211
|
requirements:
|
|
212
212
|
- - "~>"
|
|
213
213
|
- !ruby/object:Gem::Version
|
|
214
|
-
version: '3.
|
|
214
|
+
version: '3.25'
|
|
215
215
|
type: :development
|
|
216
216
|
prerelease: false
|
|
217
217
|
version_requirements: !ruby/object:Gem::Requirement
|
|
218
218
|
requirements:
|
|
219
219
|
- - "~>"
|
|
220
220
|
- !ruby/object:Gem::Version
|
|
221
|
-
version: '3.
|
|
221
|
+
version: '3.25'
|
|
222
222
|
- !ruby/object:Gem::Dependency
|
|
223
223
|
name: webrick
|
|
224
224
|
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.333.0
|
|
270
270
|
rdoc_options: []
|
|
271
271
|
require_paths:
|
|
272
272
|
- lib
|