dependabot-rust_toolchain 0.321.2

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.
@@ -0,0 +1,233 @@
1
+ # typed: strong
2
+ # frozen_string_literal: true
3
+
4
+ require "dependabot/requirement"
5
+ require "dependabot/utils"
6
+
7
+ require "dependabot/rust_toolchain"
8
+ require "dependabot/rust_toolchain/version"
9
+ require "dependabot/rust_toolchain/channel_parser"
10
+ require "dependabot/rust_toolchain/channel_type"
11
+
12
+ module Dependabot
13
+ module RustToolchain
14
+ class Requirement < Dependabot::Requirement
15
+ # For consistency with other languages, we define a requirements array.
16
+ # rust-toolchain always contains a single element.
17
+ sig { override.params(requirement_string: T.nilable(String)).returns(T::Array[Dependabot::Requirement]) }
18
+ def self.requirements_array(requirement_string)
19
+ [new(requirement_string)]
20
+ end
21
+
22
+ sig do
23
+ params(obj: T.any(String, Gem::Version)).returns(T::Array[T.any(String, Dependabot::RustToolchain::Version)])
24
+ end
25
+ def self.parse(obj)
26
+ return ["=", RustToolchain::Version.new(obj.to_s)] if obj.is_a?(Gem::Version)
27
+
28
+ requirement_string = obj.to_s.strip
29
+
30
+ # Parse requirement strings with operators (e.g., ">= 1.72.0")
31
+ match = requirement_string.match(/^(>=|>|<=|<|=)\s?(.+)$/)
32
+ if match
33
+ operator = T.must(match[1])
34
+ version_string = T.must(match[2]).strip
35
+
36
+ # Special case: handle ">= 0" which is used to represent "all versions"
37
+ return [operator, RustToolchain::Version.new("0.0.0")] if version_string == "0"
38
+
39
+ # Validate the version string
40
+ if RustToolchain::Version.correct?(version_string)
41
+ return [operator, RustToolchain::Version.new(version_string)]
42
+ end
43
+ end
44
+
45
+ # Handle bare version strings (no operator)
46
+ if requirement_string == "0"
47
+ # Special case: handle bare "0" as "0.0.0"
48
+ return ["=", RustToolchain::Version.new("0.0.0")]
49
+ end
50
+
51
+ if RustToolchain::Version.correct?(requirement_string)
52
+ return ["=", RustToolchain::Version.new(requirement_string)]
53
+ end
54
+
55
+ # If it's not a valid Rust toolchain format, fall back to default
56
+ msg = "Illformed requirement [#{obj.inspect}]"
57
+ raise BadRequirementError, msg
58
+ end
59
+
60
+ # Patches Gem::Requirement to make it accept requirement strings like
61
+ # "~> 4.2.5, >= 4.2.5.1" without first needing to split them.
62
+ sig { params(requirements: T.nilable(String)).void }
63
+ def initialize(*requirements)
64
+ requirements = requirements.flatten.flat_map do |req_string|
65
+ req_string&.split(",")&.map(&:strip)
66
+ end.compact
67
+
68
+ super(requirements)
69
+ end
70
+
71
+ # rubocop:disable Metrics/AbcSize
72
+ sig { override.params(version: T.any(Gem::Version, String)).returns(T::Boolean) }
73
+ def satisfied_by?(version)
74
+ version = RustToolchain::Version.new(version.to_s) unless version.is_a?(RustToolchain::Version)
75
+
76
+ T.cast(requirements, T::Array[T::Array[T.untyped]]).all? do |req|
77
+ op = T.cast(req[0], String)
78
+ rv = T.cast(req[1], RustToolchain::Version)
79
+
80
+ case op
81
+ when "="
82
+ satisfy_exact_requirement?(version, rv)
83
+ when ">="
84
+ satisfy_greater_than_or_equal_requirement?(version, rv)
85
+ when ">"
86
+ satisfy_greater_than_requirement?(version, rv)
87
+ when "<="
88
+ satisfy_less_than_or_equal_requirement?(version, rv)
89
+ when "<"
90
+ satisfy_less_than_requirement?(version, rv)
91
+ else
92
+ # Fall back to default behavior for other operators
93
+ ops_method = T.let(OPS[op], T.nilable(T.proc.params(arg0: T.untyped, arg1: T.untyped).returns(T::Boolean)))
94
+ ops_method ||= T.cast(OPS["="], T.proc.params(arg0: T.untyped, arg1: T.untyped).returns(T::Boolean))
95
+ ops_method.call(version, rv)
96
+ end
97
+ end
98
+ end
99
+ # rubocop:enable Metrics/AbcSize
100
+
101
+ private
102
+
103
+ # Check if version satisfies exact requirement
104
+ sig { params(version: RustToolchain::Version, requirement_version: RustToolchain::Version).returns(T::Boolean) }
105
+ def satisfy_exact_requirement?(version, requirement_version)
106
+ return version == requirement_version if version.channel.nil? || requirement_version.channel.nil?
107
+
108
+ v_channel = T.must(version.channel)
109
+ r_channel = T.must(requirement_version.channel)
110
+
111
+ # Channels must be of the same type and equal
112
+ v_channel.channel_type == r_channel.channel_type && v_channel == r_channel
113
+ end
114
+
115
+ # Check if version satisfies >= requirement
116
+ sig { params(version: RustToolchain::Version, requirement_version: RustToolchain::Version).returns(T::Boolean) }
117
+ def satisfy_greater_than_or_equal_requirement?(version, requirement_version)
118
+ return version >= requirement_version if version.channel.nil? || requirement_version.channel.nil?
119
+
120
+ v_channel = T.must(version.channel)
121
+ r_channel = T.must(requirement_version.channel)
122
+
123
+ # Can only compare channels of the same type
124
+ return false unless v_channel.channel_type == r_channel.channel_type
125
+
126
+ case v_channel.channel_type
127
+ when ChannelType::Version
128
+ # Compare semantic versions
129
+ v_channel >= r_channel
130
+ when ChannelType::DatedStability
131
+ # Must be same stability level to compare dates
132
+ return false unless v_channel.stability == r_channel.stability
133
+
134
+ v_channel >= r_channel
135
+ when ChannelType::Stability
136
+ # Stability channels can be ordered: stable > beta > nightly
137
+ stability_order(v_channel.stability) >= stability_order(r_channel.stability)
138
+ else
139
+ false
140
+ end
141
+ end
142
+
143
+ # Check if version satisfies > requirement
144
+ sig { params(version: RustToolchain::Version, requirement_version: RustToolchain::Version).returns(T::Boolean) }
145
+ def satisfy_greater_than_requirement?(version, requirement_version)
146
+ return version > requirement_version if version.channel.nil? || requirement_version.channel.nil?
147
+
148
+ v_channel = T.must(version.channel)
149
+ r_channel = T.must(requirement_version.channel)
150
+
151
+ # Can only compare channels of the same type
152
+ return false unless v_channel.channel_type == r_channel.channel_type
153
+
154
+ case v_channel.channel_type
155
+ when ChannelType::Version
156
+ v_channel > r_channel
157
+ when ChannelType::DatedStability
158
+ return false unless v_channel.stability == r_channel.stability
159
+
160
+ v_channel > r_channel
161
+ when ChannelType::Stability
162
+ stability_order(v_channel.stability) > stability_order(r_channel.stability)
163
+ else
164
+ false
165
+ end
166
+ end
167
+
168
+ # Check if version satisfies <= requirement
169
+ sig { params(version: RustToolchain::Version, requirement_version: RustToolchain::Version).returns(T::Boolean) }
170
+ def satisfy_less_than_or_equal_requirement?(version, requirement_version)
171
+ return version <= requirement_version if version.channel.nil? || requirement_version.channel.nil?
172
+
173
+ v_channel = T.must(version.channel)
174
+ r_channel = T.must(requirement_version.channel)
175
+
176
+ # Can only compare channels of the same type
177
+ return false unless v_channel.channel_type == r_channel.channel_type
178
+
179
+ case v_channel.channel_type
180
+ when ChannelType::Version
181
+ v_channel <= r_channel
182
+ when ChannelType::DatedStability
183
+ return false unless v_channel.stability == r_channel.stability
184
+
185
+ v_channel <= r_channel
186
+ when ChannelType::Stability
187
+ stability_order(v_channel.stability) <= stability_order(r_channel.stability)
188
+ else
189
+ false
190
+ end
191
+ end
192
+
193
+ # Check if version satisfies < requirement
194
+ sig { params(version: RustToolchain::Version, requirement_version: RustToolchain::Version).returns(T::Boolean) }
195
+ def satisfy_less_than_requirement?(version, requirement_version)
196
+ return version < requirement_version if version.channel.nil? || requirement_version.channel.nil?
197
+
198
+ v_channel = T.must(version.channel)
199
+ r_channel = T.must(requirement_version.channel)
200
+
201
+ # Can only compare channels of the same type
202
+ return false unless v_channel.channel_type == r_channel.channel_type
203
+
204
+ case v_channel.channel_type
205
+ when ChannelType::Version
206
+ v_channel < r_channel
207
+ when ChannelType::DatedStability
208
+ return false unless v_channel.stability == r_channel.stability
209
+
210
+ v_channel < r_channel
211
+ when ChannelType::Stability
212
+ stability_order(v_channel.stability) < stability_order(r_channel.stability)
213
+ else
214
+ false
215
+ end
216
+ end
217
+
218
+ # Define stability ordering for comparison
219
+ # stable (3) > beta (2) > nightly (1)
220
+ sig { params(stability: T.nilable(String)).returns(Integer) }
221
+ def stability_order(stability)
222
+ case stability
223
+ when STABLE_CHANNEL then 3
224
+ when BETA_CHANNEL then 2
225
+ when NIGHTLY_CHANNEL then 1
226
+ else 0
227
+ end
228
+ end
229
+ end
230
+ end
231
+ end
232
+
233
+ Dependabot::Utils.register_requirement_class("rust_toolchain", Dependabot::RustToolchain::Requirement)
@@ -0,0 +1,105 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require "sorbet-runtime"
5
+
6
+ require "dependabot/update_checkers/base"
7
+ require "dependabot/package/package_latest_version_finder"
8
+
9
+ require "dependabot/rust_toolchain/channel_type"
10
+ require "dependabot/rust_toolchain/package/package_details_fetcher"
11
+ require "dependabot/rust_toolchain/version"
12
+
13
+ module Dependabot
14
+ module RustToolchain
15
+ class UpdateChecker < Dependabot::UpdateCheckers::Base
16
+ class LatestVersionFinder < Dependabot::Package::PackageLatestVersionFinder
17
+ extend T::Sig
18
+
19
+ sig { override.returns(T.nilable(Dependabot::Package::PackageDetails)) }
20
+ def package_details
21
+ @package_details ||= Dependabot::RustToolchain::Package::PackageDetailsFetcher.new(
22
+ dependency: dependency
23
+ ).fetch
24
+ end
25
+
26
+ protected
27
+
28
+ sig do
29
+ override
30
+ .params(releases: T::Array[Dependabot::Package::PackageRelease])
31
+ .returns(T::Array[Dependabot::Package::PackageRelease])
32
+ end
33
+ def apply_post_fetch_latest_versions_filter(releases)
34
+ filter_by_version_type(releases)
35
+ end
36
+
37
+ sig do
38
+ override
39
+ .params(releases: T::Array[Dependabot::Package::PackageRelease])
40
+ .returns(T::Array[Dependabot::Package::PackageRelease])
41
+ end
42
+ def apply_post_fetch_lowest_security_fix_versions_filter(releases)
43
+ filter_by_version_type(releases)
44
+ end
45
+
46
+ sig { override.returns(T::Boolean) }
47
+ def cooldown_enabled?
48
+ Dependabot::Experiments.enabled?(:enable_cooldown_for_rust_toolchain)
49
+ end
50
+
51
+ private
52
+
53
+ sig do
54
+ params(releases: T::Array[Dependabot::Package::PackageRelease])
55
+ .returns(T::Array[Dependabot::Package::PackageRelease])
56
+ end
57
+ def filter_by_version_type(releases)
58
+ current_version = T.cast(dependency.numeric_version, T.nilable(Dependabot::RustToolchain::Version))
59
+ return [] unless current_version
60
+
61
+ current_channel = current_version.channel
62
+ return [] unless current_channel
63
+
64
+ current_type = current_channel.channel_type
65
+
66
+ # There are no updates for channels
67
+ # i.e. "stable", "beta", "nightly"
68
+ return [] if current_type == ChannelType::Stability
69
+
70
+ is_current_major_minor = major_minor_format?(current_version.to_s)
71
+
72
+ channel_matched_releases = releases.filter_map do |release|
73
+ release_rust_version = T.cast(release.version, Dependabot::RustToolchain::Version)
74
+ release_channel = release_rust_version.channel
75
+ next unless release_channel
76
+
77
+ # Check that the release version is in the same channel type
78
+ next unless release_channel.channel_type == current_type
79
+
80
+ next release unless release_channel.channel_type == ChannelType::Version
81
+
82
+ # For version channels, we need to ensure that the version format matches
83
+ is_release_major_minor = major_minor_format?(release_rust_version.to_s)
84
+ case [is_current_major_minor, is_release_major_minor]
85
+ in [true, true] | [false, false]
86
+ release
87
+ else
88
+ nil
89
+ end
90
+ end
91
+
92
+ channel_matched_releases.uniq do |release|
93
+ release.version.to_s
94
+ end
95
+ end
96
+
97
+ # Check if a version string is in major.minor format (e.g., "1.72" vs "1.72.0")
98
+ sig { params(version_string: String).returns(T::Boolean) }
99
+ def major_minor_format?(version_string)
100
+ version_string.count(".") == 1
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,75 @@
1
+ # typed: strong
2
+ # frozen_string_literal: true
3
+
4
+ require "sorbet-runtime"
5
+
6
+ require "dependabot/errors"
7
+ require "dependabot/update_checkers"
8
+ require "dependabot/update_checkers/base"
9
+
10
+ module Dependabot
11
+ module RustToolchain
12
+ class UpdateChecker < Dependabot::UpdateCheckers::Base
13
+ extend T::Sig
14
+
15
+ require_relative "update_checker/latest_version_finder"
16
+
17
+ sig { override.returns(T.nilable(T.any(String, Gem::Version))) }
18
+ def latest_version
19
+ latest_version_finder.latest_version
20
+ end
21
+
22
+ sig { override.returns(T.nilable(T.any(String, Gem::Version))) }
23
+ def latest_resolvable_version
24
+ latest_version
25
+ end
26
+
27
+ sig { override.returns(T.nilable(Dependabot::Version)) }
28
+ def latest_resolvable_version_with_no_unlock
29
+ raise NotImplementedError
30
+ end
31
+
32
+ sig { override.returns(T::Array[T::Hash[Symbol, T.untyped]]) }
33
+ def updated_requirements
34
+ dependency.requirements.map do |requirement|
35
+ {
36
+ file: requirement[:file],
37
+ requirement: latest_version,
38
+ groups: requirement[:groups],
39
+ source: requirement[:source]
40
+ }
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ sig { override.returns(T::Boolean) }
47
+ def latest_version_resolvable_with_full_unlock?
48
+ false
49
+ end
50
+
51
+ sig { override.returns(T::Array[Dependabot::Dependency]) }
52
+ def updated_dependencies_after_full_unlock
53
+ raise NotImplementedError
54
+ end
55
+
56
+ sig { returns(LatestVersionFinder) }
57
+ def latest_version_finder
58
+ @latest_version_finder ||= T.let(
59
+ LatestVersionFinder.new(
60
+ dependency: dependency,
61
+ dependency_files: dependency_files,
62
+ credentials: credentials,
63
+ ignored_versions: ignored_versions,
64
+ security_advisories: security_advisories,
65
+ cooldown_options: update_cooldown,
66
+ raise_on_ignored: raise_on_ignored
67
+ ),
68
+ T.nilable(LatestVersionFinder)
69
+ )
70
+ end
71
+ end
72
+ end
73
+ end
74
+
75
+ Dependabot::UpdateCheckers.register("rust_toolchain", Dependabot::RustToolchain::UpdateChecker)
@@ -0,0 +1,64 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require "dependabot/version"
5
+ require "dependabot/utils"
6
+
7
+ require "dependabot/rust_toolchain/channel_parser"
8
+ require "dependabot/rust_toolchain/channel_type"
9
+
10
+ module Dependabot
11
+ module RustToolchain
12
+ class Version < Dependabot::Version
13
+ sig { override.params(version: VersionParameter).void }
14
+ def initialize(version)
15
+ raise BadRequirementError, "Malformed channel string - string is nil" if version.nil?
16
+
17
+ @version_string = T.let(version.to_s.strip, String)
18
+ @channel = T.let(
19
+ Dependabot::RustToolchain::ChannelParser.new(@version_string).parse,
20
+ T.nilable(Dependabot::RustToolchain::Channel)
21
+ )
22
+
23
+ super(@version_string)
24
+ end
25
+
26
+ sig { override.params(version: VersionParameter).returns(Dependabot::RustToolchain::Version) }
27
+ def self.new(version)
28
+ T.cast(super, Dependabot::RustToolchain::Version)
29
+ end
30
+
31
+ sig { override.params(version: VersionParameter).returns(T::Boolean) }
32
+ def self.correct?(version)
33
+ return false if version.to_s.empty?
34
+
35
+ !Dependabot::RustToolchain::ChannelParser.new(version.to_s).parse.nil?
36
+ rescue ArgumentError
37
+ Dependabot.logger.info("Malformed version string #{version}")
38
+ false
39
+ end
40
+
41
+ sig { override.returns(String) }
42
+ def to_s
43
+ return "" if @channel.nil?
44
+
45
+ case @channel.channel_type
46
+ in ChannelType::Version
47
+ T.must(@channel.version)
48
+ in ChannelType::DatedStability
49
+ "#{@channel.stability}-#{@channel.date}"
50
+ in ChannelType::Stability
51
+ T.must(@channel.stability)
52
+ else
53
+ ""
54
+ end
55
+ end
56
+
57
+ sig { returns(T.nilable(Dependabot::RustToolchain::Channel)) }
58
+ attr_reader :channel
59
+ end
60
+ end
61
+ end
62
+
63
+ Dependabot::Utils
64
+ .register_version_class("rust_toolchain", Dependabot::RustToolchain::Version)
@@ -0,0 +1,42 @@
1
+ # typed: strong
2
+ # frozen_string_literal: true
3
+
4
+ require "dependabot/rust_toolchain/file_fetcher"
5
+ require "dependabot/rust_toolchain/file_parser"
6
+ require "dependabot/rust_toolchain/update_checker"
7
+ require "dependabot/rust_toolchain/file_updater"
8
+ require "dependabot/rust_toolchain/metadata_finder"
9
+ require "dependabot/rust_toolchain/requirement"
10
+ require "dependabot/rust_toolchain/version"
11
+
12
+ require "dependabot/pull_request_creator/labeler"
13
+ Dependabot::PullRequestCreator::Labeler
14
+ .register_label_details("rust_toolchain", name: "rust_toolchain_package_manager", colour: "D34516")
15
+
16
+ require "dependabot/dependency"
17
+ Dependabot::Dependency
18
+ .register_production_check("rust_toolchain", ->(_) { true })
19
+
20
+ module Dependabot
21
+ module RustToolchain
22
+ RUST_TOOLCHAIN_TOML_FILENAME = "rust-toolchain.toml"
23
+
24
+ RUST_TOOLCHAIN_FILENAME = "rust-toolchain"
25
+
26
+ STABLE_CHANNEL = "stable"
27
+
28
+ BETA_CHANNEL = "beta"
29
+
30
+ NIGHTLY_CHANNEL = "nightly"
31
+
32
+ RUST_GITHUB_URL = "https://github.com/rust-lang/rust"
33
+
34
+ ECOSYSTEM = "rust"
35
+
36
+ PACKAGE_MANAGER = "rustup"
37
+
38
+ SUPPORTED_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version])
39
+
40
+ DEPRECATED_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version])
41
+ end
42
+ end