@@ -4,6 +4,7 @@ use anyhow::{Context, Error};
4
4
use build_helper:: stage0_parser:: { Stage0Config , VersionMetadata , parse_stage0_file} ;
5
5
use curl:: easy:: Easy ;
6
6
use indexmap:: IndexMap ;
7
+ use sha2:: { Digest , Sha256 } ;
7
8
8
9
const PATH : & str = "src/stage0" ;
9
10
const COMPILER_COMPONENTS : & [ & str ] = & [ "rustc" , "rust-std" , "cargo" , "clippy-preview" ] ;
@@ -13,13 +14,14 @@ struct Tool {
13
14
config : Stage0Config ,
14
15
15
16
channel : Channel ,
16
- date : Option < String > ,
17
+ compiler_date : Option < String > ,
18
+ rustfmt_date : Option < String > ,
17
19
version : [ u16 ; 3 ] ,
18
20
checksums : IndexMap < String , String > ,
19
21
}
20
22
21
23
impl Tool {
22
- fn new ( date : Option < String > ) -> Result < Self , Error > {
24
+ fn new ( compiler_date : Option < String > , rustfmt_date : Option < String > ) -> Result < Self , Error > {
23
25
let channel = match std:: fs:: read_to_string ( "src/ci/channel" ) ?. trim ( ) {
24
26
"stable" => Channel :: Stable ,
25
27
"beta" => Channel :: Beta ,
@@ -38,7 +40,14 @@ impl Tool {
38
40
39
41
let existing = parse_stage0_file ( ) ;
40
42
41
- Ok ( Self { channel, version, date, config : existing. config , checksums : IndexMap :: new ( ) } )
43
+ Ok ( Self {
44
+ channel,
45
+ version,
46
+ compiler_date,
47
+ rustfmt_date,
48
+ config : existing. config ,
49
+ checksums : IndexMap :: new ( ) ,
50
+ } )
42
51
}
43
52
44
53
fn update_stage0_file ( mut self ) -> Result < ( ) , Error > {
@@ -78,10 +87,21 @@ impl Tool {
78
87
file_content. push_str ( "\n " ) ;
79
88
80
89
let compiler = self . detect_compiler ( ) ?;
90
+ file_content. push_str ( & format ! (
91
+ "compiler_channel_manifest_hash={}\n " ,
92
+ compiler. channel_manifest_hash
93
+ ) ) ;
94
+ file_content. push_str ( & format ! ( "compiler_git_commit_hash={}\n " , compiler. git_commit_hash) ) ;
81
95
file_content. push_str ( & format ! ( "compiler_date={}\n " , compiler. date) ) ;
82
96
file_content. push_str ( & format ! ( "compiler_version={}\n " , compiler. version) ) ;
83
97
84
98
if let Some ( rustfmt) = self . detect_rustfmt ( ) ? {
99
+ file_content. push_str ( & format ! (
100
+ "rustfmt_channel_manifest_hash={}\n " ,
101
+ rustfmt. channel_manifest_hash
102
+ ) ) ;
103
+ file_content
104
+ . push_str ( & format ! ( "rustfmt_git_commit_hash={}\n " , rustfmt. git_commit_hash) ) ;
85
105
file_content. push_str ( & format ! ( "rustfmt_date={}\n " , rustfmt. date) ) ;
86
106
file_content. push_str ( & format ! ( "rustfmt_version={}\n " , rustfmt. version) ) ;
87
107
}
@@ -112,9 +132,16 @@ impl Tool {
112
132
Channel :: Nightly => "beta" . to_string ( ) ,
113
133
} ;
114
134
115
- let manifest = fetch_manifest ( & self . config , & channel, self . date . as_deref ( ) ) ?;
135
+ let ( manifest, manifest_hash) =
136
+ fetch_manifest ( & self . config , & channel, self . compiler_date . as_deref ( ) ) ?;
116
137
self . collect_checksums ( & manifest, COMPILER_COMPONENTS ) ?;
117
138
Ok ( VersionMetadata {
139
+ channel_manifest_hash : manifest_hash,
140
+ git_commit_hash : manifest. pkg [ "rust" ]
141
+ . git_commit_hash
142
+ . as_ref ( )
143
+ . expect ( "invalid git_commit_hash" )
144
+ . into ( ) ,
118
145
date : manifest. date ,
119
146
version : if self . channel == Channel :: Nightly {
120
147
"beta" . to_string ( )
@@ -138,9 +165,19 @@ impl Tool {
138
165
return Ok ( None ) ;
139
166
}
140
167
141
- let manifest = fetch_manifest ( & self . config , "nightly" , self . date . as_deref ( ) ) ?;
168
+ let ( manifest, manifest_hash) =
169
+ fetch_manifest ( & self . config , "nightly" , self . rustfmt_date . as_deref ( ) ) ?;
142
170
self . collect_checksums ( & manifest, RUSTFMT_COMPONENTS ) ?;
143
- Ok ( Some ( VersionMetadata { date : manifest. date , version : "nightly" . into ( ) } ) )
171
+ Ok ( Some ( VersionMetadata {
172
+ channel_manifest_hash : manifest_hash,
173
+ git_commit_hash : manifest. pkg [ "rust" ]
174
+ . git_commit_hash
175
+ . as_ref ( )
176
+ . expect ( "invalid git_commit_hash" )
177
+ . into ( ) ,
178
+ date : manifest. date ,
179
+ version : "nightly" . into ( ) ,
180
+ } ) )
144
181
}
145
182
146
183
fn collect_checksums ( & mut self , manifest : & Manifest , components : & [ & str ] ) -> Result < ( ) , Error > {
@@ -164,12 +201,29 @@ impl Tool {
164
201
}
165
202
}
166
203
}
204
+ for artifact in manifest. artifacts . values ( ) {
205
+ for targets in artifact. target . values ( ) {
206
+ for target in targets {
207
+ let url = target
208
+ . url
209
+ . strip_prefix ( & prefix)
210
+ . ok_or_else ( || {
211
+ anyhow:: anyhow!(
212
+ "url doesn't start with dist server base: {}" ,
213
+ target. url
214
+ )
215
+ } ) ?
216
+ . to_string ( ) ;
217
+ self . checksums . insert ( url, target. hash_sha256 . clone ( ) ) ;
218
+ }
219
+ }
220
+ }
167
221
Ok ( ( ) )
168
222
}
169
223
}
170
224
171
225
fn main ( ) -> Result < ( ) , Error > {
172
- let tool = Tool :: new ( std:: env:: args ( ) . nth ( 1 ) ) ?;
226
+ let tool = Tool :: new ( std:: env:: args ( ) . nth ( 1 ) , std :: env :: args ( ) . nth ( 2 ) ) ?;
173
227
tool. update_stage0_file ( ) ?;
174
228
Ok ( ( ) )
175
229
}
@@ -178,18 +232,24 @@ fn fetch_manifest(
178
232
config : & Stage0Config ,
179
233
channel : & str ,
180
234
date : Option < & str > ,
181
- ) -> Result < Manifest , Error > {
235
+ ) -> Result < ( Manifest , String ) , Error > {
182
236
let url = if let Some ( date) = date {
183
237
format ! ( "{}/dist/{}/channel-rust-{}.toml" , config. dist_server, date, channel)
184
238
} else {
185
239
format ! ( "{}/dist/channel-rust-{}.toml" , config. dist_server, channel)
186
240
} ;
187
241
242
+ let manifest_bytes = http_get ( & url) ?;
243
+
244
+ let mut sha256 = Sha256 :: new ( ) ;
245
+ sha256. update ( & manifest_bytes) ;
246
+ let manifest_hash = hex:: encode ( sha256. finalize ( ) ) ;
247
+
188
248
// FIXME: on newer `toml` (>= `0.9.*`), use `toml::from_slice`. For now, we use the most recent
189
249
// `toml` available in-tree which is `0.8.*`, so we have to do an additional dance here.
190
- let response = http_get ( & url ) ?;
191
- let response = String :: from_utf8 ( response ) ?;
192
- Ok ( toml :: from_str ( & response ) ? )
250
+ let manifest_str = String :: from_utf8 ( manifest_bytes ) ?;
251
+ let manifest = toml :: from_str ( & manifest_str ) ?;
252
+ Ok ( ( manifest , manifest_hash ) )
193
253
}
194
254
195
255
fn http_get ( url : & str ) -> Result < Vec < u8 > , Error > {
@@ -219,11 +279,14 @@ enum Channel {
219
279
struct Manifest {
220
280
date : String ,
221
281
pkg : IndexMap < String , ManifestPackage > ,
282
+ artifacts : IndexMap < String , ManifestArtifact > ,
222
283
}
223
284
224
285
#[ derive( Debug , serde:: Serialize , serde:: Deserialize ) ]
225
286
struct ManifestPackage {
226
287
version : String ,
288
+ #[ serde( default ) ]
289
+ git_commit_hash : Option < String > ,
227
290
target : IndexMap < String , ManifestTargetPackage > ,
228
291
}
229
292
@@ -234,3 +297,15 @@ struct ManifestTargetPackage {
234
297
xz_url : Option < String > ,
235
298
xz_hash : Option < String > ,
236
299
}
300
+
301
+ #[ derive( Debug , serde:: Serialize , serde:: Deserialize ) ]
302
+ struct ManifestArtifact {
303
+ target : IndexMap < String , Vec < ManifestTargetArtifact > > ,
304
+ }
305
+
306
+ #[ derive( Debug , serde:: Serialize , serde:: Deserialize ) ]
307
+ #[ serde( rename_all = "kebab-case" ) ]
308
+ struct ManifestTargetArtifact {
309
+ url : String ,
310
+ hash_sha256 : String ,
311
+ }
0 commit comments