@@ -120,7 +120,7 @@ pub enum DistError {
120
120
121
121
#[ derive( Debug , PartialEq ) ]
122
122
struct ParsedToolchainDesc {
123
- channel : String ,
123
+ channel : Channel ,
124
124
date : Option < String > ,
125
125
target : Option < String > ,
126
126
}
@@ -132,8 +132,7 @@ struct ParsedToolchainDesc {
132
132
// are nearly-arbitrary strings.
133
133
#[ derive( Debug , Clone , Eq , PartialEq , PartialOrd , Ord ) ]
134
134
pub struct PartialToolchainDesc {
135
- // Either "nightly", "stable", "beta", or an explicit version number
136
- pub channel : String ,
135
+ pub channel : Channel ,
137
136
pub date : Option < String > ,
138
137
pub target : PartialTargetTriple ,
139
138
}
@@ -146,12 +145,81 @@ pub struct PartialToolchainDesc {
146
145
/// 1.55-x86_64-pc-windows-msvc
147
146
#[ derive( Debug , Clone , Eq , PartialEq , PartialOrd , Ord ) ]
148
147
pub struct ToolchainDesc {
149
- // Either "nightly", "stable", "beta", or an explicit version number
150
- pub channel : String ,
148
+ pub channel : Channel ,
151
149
pub date : Option < String > ,
152
150
pub target : TargetTriple ,
153
151
}
154
152
153
+ #[ derive( Debug , Clone , Eq , PartialEq , PartialOrd , Ord ) ]
154
+ pub enum Channel {
155
+ Stable ,
156
+ Beta ,
157
+ Nightly ,
158
+ Version ( PartialVersion ) ,
159
+ }
160
+
161
+ impl fmt:: Display for Channel {
162
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
163
+ match self {
164
+ Self :: Stable => write ! ( f, "stable" ) ,
165
+ Self :: Beta => write ! ( f, "beta" ) ,
166
+ Self :: Nightly => write ! ( f, "nightly" ) ,
167
+ Self :: Version ( ver) => write ! ( f, "{ver}" ) ,
168
+ }
169
+ }
170
+ }
171
+
172
+ impl FromStr for Channel {
173
+ type Err = anyhow:: Error ;
174
+ fn from_str ( chan : & str ) -> Result < Self > {
175
+ match chan {
176
+ "stable" => Ok ( Self :: Stable ) ,
177
+ "beta" => Ok ( Self :: Beta ) ,
178
+ "nightly" => Ok ( Self :: Nightly ) ,
179
+ ver => ver. parse ( ) . map ( Self :: Version ) ,
180
+ }
181
+ }
182
+ }
183
+
184
+ #[ derive( Debug , Clone , Eq , PartialEq , PartialOrd , Ord ) ]
185
+ pub struct PartialVersion {
186
+ pub major : u64 ,
187
+ pub minor : Option < u64 > ,
188
+ pub patch : Option < u64 > ,
189
+ pub pre : semver:: Prerelease ,
190
+ }
191
+
192
+ impl fmt:: Display for PartialVersion {
193
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
194
+ write ! ( f, "{}" , self . major) ?;
195
+ if let Some ( minor) = self . minor {
196
+ write ! ( f, ".{minor}" ) ?;
197
+ }
198
+ if let Some ( patch) = self . patch {
199
+ write ! ( f, ".{patch}" ) ?;
200
+ }
201
+ if !self . pre . is_empty ( ) {
202
+ write ! ( f, "-{}" , self . pre) ?;
203
+ }
204
+ Ok ( ( ) )
205
+ }
206
+ }
207
+
208
+ impl FromStr for PartialVersion {
209
+ type Err = anyhow:: Error ;
210
+ fn from_str ( ver : & str ) -> Result < Self > {
211
+ let ( ver, pre) = ver. split_once ( '-' ) . unwrap_or ( ( ver, "" ) ) ;
212
+ let comparator =
213
+ semver:: Comparator :: from_str ( ver) . context ( "error parsing `PartialVersion`" ) ?;
214
+ Ok ( Self {
215
+ major : comparator. major ,
216
+ minor : comparator. minor ,
217
+ patch : comparator. patch ,
218
+ pre : semver:: Prerelease :: new ( pre) . context ( "error parsing `PartialVersion`" ) ?,
219
+ } )
220
+ }
221
+ }
222
+
155
223
#[ derive( Debug , Clone , Deserialize , Eq , PartialEq , Ord , PartialOrd , Hash , Serialize ) ]
156
224
#[ serde( transparent) ]
157
225
pub struct TargetTriple ( String ) ;
@@ -229,7 +297,7 @@ impl FromStr for ParsedToolchainDesc {
229
297
} ;
230
298
231
299
Self {
232
- channel : channel. to_owned ( ) ,
300
+ channel : Channel :: from_str ( channel) . unwrap ( ) ,
233
301
date : c. get ( 2 ) . map ( |s| s. as_str ( ) ) . and_then ( fn_map) ,
234
302
target : c. get ( 3 ) . map ( |s| s. as_str ( ) ) . and_then ( fn_map) ,
235
303
}
@@ -579,7 +647,7 @@ impl ToolchainDesc {
579
647
/// Either "$channel" or "channel-$date"
580
648
pub fn manifest_name ( & self ) -> String {
581
649
match self . date {
582
- None => self . channel . clone ( ) ,
650
+ None => self . channel . to_string ( ) ,
583
651
Some ( ref date) => format ! ( "{}-{}" , self . channel, date) ,
584
652
}
585
653
}
@@ -595,11 +663,11 @@ impl ToolchainDesc {
595
663
/// such as `stable`, or is an incomplete version such as `1.48`, and the
596
664
/// date field is empty.
597
665
pub ( crate ) fn is_tracking ( & self ) -> bool {
598
- let channels = [ "nightly" , "beta" , "stable" ] ;
599
- static TRACKING_VERSION : Lazy < Regex > =
600
- Lazy :: new ( || Regex :: new ( r"^\d{1}\.\d{1,3}$" ) . unwrap ( ) ) ;
601
- ( channels . iter ( ) . any ( |x| * x == self . channel ) || TRACKING_VERSION . is_match ( & self . channel ) )
602
- && self . date . is_none ( )
666
+ match & self . channel {
667
+ _ if self . date . is_some ( ) => false ,
668
+ Channel :: Stable | Channel :: Beta | Channel :: Nightly => true ,
669
+ Channel :: Version ( ver ) => ver . patch . is_none ( ) || & * ver . pre == "beta" ,
670
+ }
603
671
}
604
672
}
605
673
@@ -752,7 +820,7 @@ pub(crate) async fn update_from_dist(
752
820
753
821
let mut fetched = String :: new ( ) ;
754
822
let mut first_err = None ;
755
- let backtrack = opts. toolchain . channel == "nightly" && opts. toolchain . date . is_none ( ) ;
823
+ let backtrack = opts. toolchain . channel == Channel :: Nightly && opts. toolchain . date . is_none ( ) ;
756
824
// We want to limit backtracking if we do not already have a toolchain
757
825
let mut backtrack_limit: Option < i32 > = if opts. toolchain . date . is_some ( ) {
758
826
None
@@ -1099,13 +1167,10 @@ async fn dl_v1_manifest(
1099
1167
) -> Result < Vec < String > > {
1100
1168
let root_url = toolchain. package_dir ( download. dist_root ) ;
1101
1169
1102
- if ! [ "nightly" , "beta" , "stable" ] . contains ( & & * toolchain. channel ) {
1170
+ if let Channel :: Version ( ver ) = & toolchain. channel {
1103
1171
// This is an explicit version. In v1 there was no manifest,
1104
1172
// you just know the file to download, so synthesize one.
1105
- let installer_name = format ! (
1106
- "{}/rust-{}-{}.tar.gz" ,
1107
- root_url, toolchain. channel, toolchain. target
1108
- ) ;
1173
+ let installer_name = format ! ( "{}/rust-{}-{}.tar.gz" , root_url, ver, toolchain. target) ;
1109
1174
return Ok ( vec ! [ installer_name] ) ;
1110
1175
}
1111
1176
@@ -1191,7 +1256,7 @@ mod tests {
1191
1256
) ;
1192
1257
1193
1258
let expected = ParsedToolchainDesc {
1194
- channel : channel. into ( ) ,
1259
+ channel : Channel :: from_str ( channel) . unwrap ( ) ,
1195
1260
date : date. map ( String :: from) ,
1196
1261
target : target. map ( String :: from) ,
1197
1262
} ;
@@ -1226,6 +1291,9 @@ mod tests {
1226
1291
( "nightly-2020-10-04" , false ) ,
1227
1292
( "1.48" , true ) ,
1228
1293
( "1.47.0" , false ) ,
1294
+ ( "1.23-beta" , true ) ,
1295
+ ( "1.23.0-beta" , true ) ,
1296
+ ( "1.23.0-beta.2" , false ) ,
1229
1297
] ;
1230
1298
for case in CASES {
1231
1299
let full_tcn = format ! ( "{}-x86_64-unknown-linux-gnu" , case. 0 ) ;
0 commit comments