@@ -15,6 +15,7 @@ use mdbook::{
15
15
16
16
const CHANNELS : & [ & str ] = & [ "stable" , "beta" , "nightly" ] ;
17
17
const CHANNEL_URL_PREFIX : & str = "https://static.rust-lang.org/dist/channel-rust-" ;
18
+ const MANIFESTS_URL : & str = "https://static.rust-lang.org/manifests.txt" ;
18
19
const RUSTUP_URLS : & str =
19
20
"https://raw.githubusercontent.com/rust-lang/rustup.rs/stable/ci/cloudfront-invalidation.txt" ;
20
21
@@ -45,6 +46,8 @@ pub struct Blacksmith {
45
46
rustup : Vec < String > ,
46
47
stable_version : Option < String > ,
47
48
platforms : BTreeMap < String , Platform > ,
49
+ #[ serde( default ) ]
50
+ previous_stable_versions : Vec < ( String , Vec < String > ) > ,
48
51
}
49
52
50
53
impl Blacksmith {
@@ -123,6 +126,64 @@ impl Blacksmith {
123
126
}
124
127
}
125
128
129
+ let latest_stable_version = & blacksmith. stable_version . clone ( ) . unwrap ( ) ;
130
+
131
+ // Go over stable versions in https://static.rust-lang.org/manifests.txt in reverse order.
132
+ let manifests_content = reqwest:: blocking:: get ( MANIFESTS_URL ) ?. text ( ) ?;
133
+ let stable_manifest_url_regex =
134
+ regex:: Regex :: new ( r"^static\.rust-lang\.org/dist/\d{4}-\d{2}-\d{2}/channel-rust-1\.(\d+)\.(\d+)\.toml$" ) . unwrap ( ) ;
135
+ for manifest_url in manifests_content. lines ( ) . rev ( ) {
136
+ let minor;
137
+ let patch;
138
+
139
+ // Check if it's a stable version.
140
+ if let Some ( captures) = stable_manifest_url_regex. captures ( & ( manifest_url) ) {
141
+ minor = captures. get ( 1 ) . unwrap ( ) . as_str ( ) ;
142
+ patch = captures. get ( 2 ) . unwrap ( ) . as_str ( ) ;
143
+ } else {
144
+ continue
145
+ }
146
+
147
+ let full_version = format ! ( "1.{}.{}" , minor, patch) ;
148
+
149
+ // Skip latest stable version.
150
+ if & full_version == latest_stable_version {
151
+ continue
152
+ }
153
+
154
+ // Download https://static.rust-lang.org/dist/channel-rust-{major.minor.patch}.toml and process it.
155
+ let channel_url = format ! ( "{}{}.toml" , CHANNEL_URL_PREFIX , full_version) ;
156
+
157
+ let content = reqwest:: blocking:: get ( & channel_url) ?. text ( ) ?;
158
+ let rust = toml:: from_str :: < crate :: channel:: Channel > ( & content) ?
159
+ . pkg
160
+ . rust ;
161
+
162
+ log:: info!(
163
+ "Found {} targets for stable v{}" ,
164
+ rust. target. len( ) ,
165
+ rust. version
166
+ ) ;
167
+
168
+ let version = rust. version . split ( ' ' ) . next ( ) . unwrap ( ) . to_string ( ) ;
169
+
170
+ let platforms = rust
171
+ . target
172
+ . into_iter ( )
173
+ . filter_map ( |( target, content) | {
174
+ if content. available {
175
+ Some ( target)
176
+ } else {
177
+ None
178
+ }
179
+ } )
180
+ . collect :: < Vec < _ > > ( ) ;
181
+
182
+ blacksmith
183
+ . previous_stable_versions
184
+ . push ( ( version. clone ( ) , platforms) ) ;
185
+ }
186
+
126
187
blacksmith. last_update = unix_time ( ) ;
127
188
Ok ( blacksmith)
128
189
}
@@ -209,6 +270,45 @@ impl Blacksmith {
209
270
buffer
210
271
}
211
272
273
+ /// Generates tables of links to the previous stable standalone installer packages for
274
+ /// each platform.
275
+ fn generate_previous_stable_standalone_installers_tables ( & self ) -> String {
276
+ let mut buffer = String :: new ( ) ;
277
+
278
+ for ( stable_version, platforms) in & self . previous_stable_versions {
279
+ writeln ! ( buffer, "## Stable ({})" , stable_version) . unwrap ( ) ;
280
+ writeln ! ( buffer, "" ) . unwrap ( ) ;
281
+
282
+ writeln ! ( buffer, "platform | stable ({})" , stable_version) . unwrap ( ) ;
283
+ writeln ! ( buffer, "---------|--------" ) . unwrap ( ) ;
284
+
285
+ for name in platforms {
286
+ let extension = if name. contains ( "windows" ) {
287
+ "msi"
288
+ } else if name. contains ( "darwin" ) {
289
+ "pkg"
290
+ } else {
291
+ "tar.gz"
292
+ } ;
293
+
294
+ let stable_links =
295
+ generate_standalone_links ( "rust" , stable_version, name, extension) ;
296
+
297
+ writeln ! (
298
+ buffer,
299
+ "`{name}` | {stable}" ,
300
+ name = name,
301
+ stable = stable_links,
302
+ )
303
+ . unwrap ( ) ;
304
+ }
305
+
306
+ writeln ! ( buffer, "" ) . unwrap ( ) ;
307
+ }
308
+
309
+ buffer
310
+ }
311
+
212
312
/// Generates a similar table to `generate_standalone_installers_table`
213
313
/// except for the rust source code packages.
214
314
fn generate_source_code_table ( & self ) -> String {
@@ -288,16 +388,23 @@ impl Preprocessor for Blacksmith {
288
388
289
389
let rustup_init_list = self . generate_rustup_init_list ( ) ;
290
390
let standalone_installers_table = self . generate_standalone_installers_table ( ) ;
391
+ let previous_stable_standalone_installers_tables =
392
+ self . generate_previous_stable_standalone_installers_tables ( ) ;
291
393
let source_code_table = self . generate_source_code_table ( ) ;
292
394
293
395
// TODO: Currently we're performing a global search for any of the
294
396
// variables as that's the most flexible for adding more dynamic
295
- // content, and the time to traverse is fast enough to not be noticable .
397
+ // content, and the time to traverse is fast enough to not be noticeable .
296
398
// However if the processing time begins to become a bottleneck this
297
399
// should change.
298
400
for item in & mut book. sections {
299
401
recursive_replace ( item, "{{#rustup_init_list}}" , & rustup_init_list) ;
300
402
recursive_replace ( item, "{{#installer_table}}" , & standalone_installers_table) ;
403
+ recursive_replace (
404
+ item,
405
+ "{{#previous_stable_standalone_installers_tables}}" ,
406
+ & previous_stable_standalone_installers_tables,
407
+ ) ;
301
408
recursive_replace ( item, "{{#source_code_table}}" , & source_code_table) ;
302
409
}
303
410
0 commit comments