@@ -120,7 +120,7 @@ pub enum DistError {
120120
121121#[ derive( Debug , PartialEq ) ]
122122struct ParsedToolchainDesc {
123- channel : String ,
123+ channel : Channel ,
124124 date : Option < String > ,
125125 target : Option < String > ,
126126}
@@ -132,8 +132,7 @@ struct ParsedToolchainDesc {
132132// are nearly-arbitrary strings.
133133#[ derive( Debug , Clone , Eq , PartialEq , PartialOrd , Ord ) ]
134134pub struct PartialToolchainDesc {
135- // Either "nightly", "stable", "beta", or an explicit version number
136- pub channel : String ,
135+ pub channel : Channel ,
137136 pub date : Option < String > ,
138137 pub target : PartialTargetTriple ,
139138}
@@ -146,12 +145,81 @@ pub struct PartialToolchainDesc {
146145/// 1.55-x86_64-pc-windows-msvc
147146#[ derive( Debug , Clone , Eq , PartialEq , PartialOrd , Ord ) ]
148147pub struct ToolchainDesc {
149- // Either "nightly", "stable", "beta", or an explicit version number
150- pub channel : String ,
148+ pub channel : Channel ,
151149 pub date : Option < String > ,
152150 pub target : TargetTriple ,
153151}
154152
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+
155223#[ derive( Debug , Clone , Deserialize , Eq , PartialEq , Ord , PartialOrd , Hash , Serialize ) ]
156224#[ serde( transparent) ]
157225pub struct TargetTriple ( String ) ;
@@ -229,7 +297,7 @@ impl FromStr for ParsedToolchainDesc {
229297 } ;
230298
231299 Self {
232- channel : channel. to_owned ( ) ,
300+ channel : Channel :: from_str ( channel) . unwrap ( ) ,
233301 date : c. get ( 2 ) . map ( |s| s. as_str ( ) ) . and_then ( fn_map) ,
234302 target : c. get ( 3 ) . map ( |s| s. as_str ( ) ) . and_then ( fn_map) ,
235303 }
@@ -579,7 +647,7 @@ impl ToolchainDesc {
579647 /// Either "$channel" or "channel-$date"
580648 pub fn manifest_name ( & self ) -> String {
581649 match self . date {
582- None => self . channel . clone ( ) ,
650+ None => self . channel . to_string ( ) ,
583651 Some ( ref date) => format ! ( "{}-{}" , self . channel, date) ,
584652 }
585653 }
@@ -595,11 +663,11 @@ impl ToolchainDesc {
595663 /// such as `stable`, or is an incomplete version such as `1.48`, and the
596664 /// date field is empty.
597665 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+ }
603671 }
604672}
605673
@@ -752,7 +820,7 @@ pub(crate) async fn update_from_dist(
752820
753821 let mut fetched = String :: new ( ) ;
754822 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 ( ) ;
756824 // We want to limit backtracking if we do not already have a toolchain
757825 let mut backtrack_limit: Option < i32 > = if opts. toolchain . date . is_some ( ) {
758826 None
@@ -1099,13 +1167,10 @@ async fn dl_v1_manifest(
10991167) -> Result < Vec < String > > {
11001168 let root_url = toolchain. package_dir ( download. dist_root ) ;
11011169
1102- if ! [ "nightly" , "beta" , "stable" ] . contains ( & & * toolchain. channel ) {
1170+ if let Channel :: Version ( ver ) = & toolchain. channel {
11031171 // This is an explicit version. In v1 there was no manifest,
11041172 // 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) ;
11091174 return Ok ( vec ! [ installer_name] ) ;
11101175 }
11111176
@@ -1191,7 +1256,7 @@ mod tests {
11911256 ) ;
11921257
11931258 let expected = ParsedToolchainDesc {
1194- channel : channel. into ( ) ,
1259+ channel : Channel :: from_str ( channel) . unwrap ( ) ,
11951260 date : date. map ( String :: from) ,
11961261 target : target. map ( String :: from) ,
11971262 } ;
@@ -1226,6 +1291,9 @@ mod tests {
12261291 ( "nightly-2020-10-04" , false ) ,
12271292 ( "1.48" , true ) ,
12281293 ( "1.47.0" , false ) ,
1294+ ( "1.23-beta" , true ) ,
1295+ ( "1.23.0-beta" , true ) ,
1296+ ( "1.23.0-beta.2" , false ) ,
12291297 ] ;
12301298 for case in CASES {
12311299 let full_tcn = format ! ( "{}-x86_64-unknown-linux-gnu" , case. 0 ) ;
0 commit comments