]> git.proxmox.com Git - rustc.git/blame - src/tools/build-manifest/src/main.rs
New upstream version 1.34.2+dfsg1
[rustc.git] / src / tools / build-manifest / src / main.rs
CommitLineData
9fa01778
XL
1#![deny(rust_2018_idioms)]
2
3use toml;
4use serde::Serialize;
32a655c1 5
cc61c64b 6use std::collections::BTreeMap;
32a655c1 7use std::env;
0731742a 8use std::fs;
32a655c1
SL
9use std::io::{self, Read, Write};
10use std::path::{PathBuf, Path};
11use std::process::{Command, Stdio};
12
13static HOSTS: &'static [&'static str] = &[
14 "aarch64-unknown-linux-gnu",
15 "arm-unknown-linux-gnueabi",
16 "arm-unknown-linux-gnueabihf",
17 "armv7-unknown-linux-gnueabihf",
18 "i686-apple-darwin",
19 "i686-pc-windows-gnu",
20 "i686-pc-windows-msvc",
21 "i686-unknown-linux-gnu",
22 "mips-unknown-linux-gnu",
23 "mips64-unknown-linux-gnuabi64",
24 "mips64el-unknown-linux-gnuabi64",
25 "mipsel-unknown-linux-gnu",
26 "powerpc-unknown-linux-gnu",
27 "powerpc64-unknown-linux-gnu",
28 "powerpc64le-unknown-linux-gnu",
29 "s390x-unknown-linux-gnu",
30 "x86_64-apple-darwin",
31 "x86_64-pc-windows-gnu",
32 "x86_64-pc-windows-msvc",
33 "x86_64-unknown-freebsd",
34 "x86_64-unknown-linux-gnu",
35 "x86_64-unknown-netbsd",
36];
37
38static TARGETS: &'static [&'static str] = &[
39 "aarch64-apple-ios",
8faf50e0 40 "aarch64-fuchsia",
32a655c1 41 "aarch64-linux-android",
a1dfa0c6 42 "aarch64-pc-windows-msvc",
ff7c6d11 43 "aarch64-unknown-cloudabi",
32a655c1 44 "aarch64-unknown-linux-gnu",
ea8adc8c 45 "aarch64-unknown-linux-musl",
32a655c1
SL
46 "arm-linux-androideabi",
47 "arm-unknown-linux-gnueabi",
48 "arm-unknown-linux-gnueabihf",
49 "arm-unknown-linux-musleabi",
50 "arm-unknown-linux-musleabihf",
ff7c6d11 51 "armv5te-unknown-linux-gnueabi",
83c7162d 52 "armv5te-unknown-linux-musleabi",
32a655c1
SL
53 "armv7-apple-ios",
54 "armv7-linux-androideabi",
0731742a 55 "thumbv7neon-linux-androideabi",
32a655c1 56 "armv7-unknown-linux-gnueabihf",
0731742a 57 "thumbv7neon-unknown-linux-gnueabihf",
32a655c1 58 "armv7-unknown-linux-musleabihf",
b7449926 59 "armebv7r-none-eabi",
94b46f34 60 "armebv7r-none-eabihf",
b7449926
XL
61 "armv7r-none-eabi",
62 "armv7r-none-eabihf",
32a655c1
SL
63 "armv7s-apple-ios",
64 "asmjs-unknown-emscripten",
65 "i386-apple-ios",
66 "i586-pc-windows-msvc",
67 "i586-unknown-linux-gnu",
2c00a5a8 68 "i586-unknown-linux-musl",
32a655c1
SL
69 "i686-apple-darwin",
70 "i686-linux-android",
71 "i686-pc-windows-gnu",
72 "i686-pc-windows-msvc",
73 "i686-unknown-freebsd",
74 "i686-unknown-linux-gnu",
75 "i686-unknown-linux-musl",
76 "mips-unknown-linux-gnu",
77 "mips-unknown-linux-musl",
78 "mips64-unknown-linux-gnuabi64",
79 "mips64el-unknown-linux-gnuabi64",
80 "mipsel-unknown-linux-gnu",
81 "mipsel-unknown-linux-musl",
9fa01778 82 "nvptx64-nvidia-cuda",
32a655c1
SL
83 "powerpc-unknown-linux-gnu",
84 "powerpc64-unknown-linux-gnu",
85 "powerpc64le-unknown-linux-gnu",
b7449926
XL
86 "riscv32imc-unknown-none-elf",
87 "riscv32imac-unknown-none-elf",
9fa01778
XL
88 "riscv64imac-unknown-none-elf",
89 "riscv64gc-unknown-none-elf",
32a655c1 90 "s390x-unknown-linux-gnu",
8bb4bdeb 91 "sparc64-unknown-linux-gnu",
ea8adc8c 92 "sparcv9-sun-solaris",
83c7162d
XL
93 "thumbv6m-none-eabi",
94 "thumbv7em-none-eabi",
95 "thumbv7em-none-eabihf",
96 "thumbv7m-none-eabi",
0731742a 97 "thumbv8m.main-none-eabi",
32a655c1 98 "wasm32-unknown-emscripten",
ff7c6d11 99 "wasm32-unknown-unknown",
32a655c1
SL
100 "x86_64-apple-darwin",
101 "x86_64-apple-ios",
0731742a 102 "x86_64-fortanix-unknown-sgx",
8faf50e0 103 "x86_64-fuchsia",
ff7c6d11 104 "x86_64-linux-android",
32a655c1
SL
105 "x86_64-pc-windows-gnu",
106 "x86_64-pc-windows-msvc",
107 "x86_64-rumprun-netbsd",
ea8adc8c 108 "x86_64-sun-solaris",
ff7c6d11 109 "x86_64-unknown-cloudabi",
32a655c1
SL
110 "x86_64-unknown-freebsd",
111 "x86_64-unknown-linux-gnu",
abe05a73 112 "x86_64-unknown-linux-gnux32",
32a655c1
SL
113 "x86_64-unknown-linux-musl",
114 "x86_64-unknown-netbsd",
3b2f2976 115 "x86_64-unknown-redox",
32a655c1
SL
116];
117
b7449926
XL
118static DOCS_TARGETS: &'static [&'static str] = &[
119 "i686-apple-darwin",
120 "i686-pc-windows-gnu",
121 "i686-pc-windows-msvc",
122 "i686-unknown-linux-gnu",
123 "x86_64-apple-darwin",
124 "x86_64-pc-windows-gnu",
125 "x86_64-pc-windows-msvc",
126 "x86_64-unknown-linux-gnu",
127];
128
32a655c1
SL
129static MINGW: &'static [&'static str] = &[
130 "i686-pc-windows-gnu",
131 "x86_64-pc-windows-gnu",
132];
133
3b2f2976
XL
134#[derive(Serialize)]
135#[serde(rename_all = "kebab-case")]
32a655c1
SL
136struct Manifest {
137 manifest_version: String,
138 date: String,
cc61c64b 139 pkg: BTreeMap<String, Package>,
0731742a
XL
140 renames: BTreeMap<String, Rename>,
141 profiles: BTreeMap<String, Vec<String>>,
32a655c1
SL
142}
143
3b2f2976 144#[derive(Serialize)]
32a655c1
SL
145struct Package {
146 version: String,
ea8adc8c 147 git_commit_hash: Option<String>,
cc61c64b 148 target: BTreeMap<String, Target>,
32a655c1
SL
149}
150
ea8adc8c
XL
151#[derive(Serialize)]
152struct Rename {
153 to: String,
154}
155
3b2f2976 156#[derive(Serialize)]
32a655c1
SL
157struct Target {
158 available: bool,
159 url: Option<String>,
160 hash: Option<String>,
7cac9316
XL
161 xz_url: Option<String>,
162 xz_hash: Option<String>,
32a655c1
SL
163 components: Option<Vec<Component>>,
164 extensions: Option<Vec<Component>>,
165}
166
7cac9316
XL
167impl Target {
168 fn unavailable() -> Target {
169 Target {
170 available: false,
171 url: None,
172 hash: None,
173 xz_url: None,
174 xz_hash: None,
175 components: None,
176 extensions: None,
177 }
178 }
179}
180
3b2f2976 181#[derive(Serialize)]
32a655c1
SL
182struct Component {
183 pkg: String,
184 target: String,
185}
186
187macro_rules! t {
188 ($e:expr) => (match $e {
189 Ok(e) => e,
190 Err(e) => panic!("{} failed with {}", stringify!($e), e),
191 })
192}
193
194struct Builder {
8bb4bdeb
XL
195 rust_release: String,
196 cargo_release: String,
3b2f2976 197 rls_release: String,
8faf50e0 198 clippy_release: String,
abe05a73 199 rustfmt_release: String,
8faf50e0 200 llvm_tools_release: String,
b7449926 201 lldb_release: String,
0731742a 202 miri_release: String,
abe05a73 203
32a655c1
SL
204 input: PathBuf,
205 output: PathBuf,
206 gpg_passphrase: String,
cc61c64b 207 digests: BTreeMap<String, String>,
32a655c1
SL
208 s3_address: String,
209 date: String,
abe05a73
XL
210
211 rust_version: Option<String>,
212 cargo_version: Option<String>,
213 rls_version: Option<String>,
8faf50e0 214 clippy_version: Option<String>,
abe05a73 215 rustfmt_version: Option<String>,
8faf50e0 216 llvm_tools_version: Option<String>,
b7449926 217 lldb_version: Option<String>,
0731742a 218 miri_version: Option<String>,
abe05a73 219
ea8adc8c
XL
220 rust_git_commit_hash: Option<String>,
221 cargo_git_commit_hash: Option<String>,
222 rls_git_commit_hash: Option<String>,
8faf50e0 223 clippy_git_commit_hash: Option<String>,
abe05a73 224 rustfmt_git_commit_hash: Option<String>,
8faf50e0 225 llvm_tools_git_commit_hash: Option<String>,
b7449926 226 lldb_git_commit_hash: Option<String>,
0731742a 227 miri_git_commit_hash: Option<String>,
b7449926
XL
228
229 should_sign: bool,
32a655c1
SL
230}
231
232fn main() {
b7449926
XL
233 // Avoid signing packages while manually testing
234 // Do NOT set this envvar in CI
235 let should_sign = env::var("BUILD_MANIFEST_DISABLE_SIGNING").is_err();
236
237 // Safety check to ensure signing is always enabled on CI
238 // The CI environment variable is set by both Travis and AppVeyor
239 if !should_sign && env::var("CI").is_ok() {
240 println!("The 'BUILD_MANIFEST_DISABLE_SIGNING' env var can't be enabled on CI.");
241 println!("If you're not running this on CI, unset the 'CI' env var.");
242 panic!();
243 }
244
32a655c1
SL
245 let mut args = env::args().skip(1);
246 let input = PathBuf::from(args.next().unwrap());
247 let output = PathBuf::from(args.next().unwrap());
248 let date = args.next().unwrap();
8bb4bdeb 249 let rust_release = args.next().unwrap();
0731742a 250 let s3_address = args.next().unwrap();
8bb4bdeb 251 let cargo_release = args.next().unwrap();
3b2f2976 252 let rls_release = args.next().unwrap();
8faf50e0 253 let clippy_release = args.next().unwrap();
0731742a 254 let miri_release = args.next().unwrap();
abe05a73 255 let rustfmt_release = args.next().unwrap();
8faf50e0 256 let llvm_tools_release = args.next().unwrap();
b7449926 257 let lldb_release = args.next().unwrap();
b7449926
XL
258
259 // Do not ask for a passphrase while manually testing
32a655c1 260 let mut passphrase = String::new();
b7449926
XL
261 if should_sign {
262 t!(io::stdin().read_to_string(&mut passphrase));
263 }
32a655c1
SL
264
265 Builder {
3b2f2976
XL
266 rust_release,
267 cargo_release,
268 rls_release,
8faf50e0 269 clippy_release,
abe05a73 270 rustfmt_release,
8faf50e0 271 llvm_tools_release,
b7449926 272 lldb_release,
0731742a 273 miri_release,
abe05a73 274
3b2f2976
XL
275 input,
276 output,
32a655c1 277 gpg_passphrase: passphrase,
cc61c64b 278 digests: BTreeMap::new(),
3b2f2976
XL
279 s3_address,
280 date,
abe05a73
XL
281
282 rust_version: None,
283 cargo_version: None,
284 rls_version: None,
8faf50e0 285 clippy_version: None,
abe05a73 286 rustfmt_version: None,
8faf50e0 287 llvm_tools_version: None,
b7449926 288 lldb_version: None,
0731742a 289 miri_version: None,
abe05a73 290
ea8adc8c
XL
291 rust_git_commit_hash: None,
292 cargo_git_commit_hash: None,
293 rls_git_commit_hash: None,
8faf50e0 294 clippy_git_commit_hash: None,
abe05a73 295 rustfmt_git_commit_hash: None,
8faf50e0 296 llvm_tools_git_commit_hash: None,
b7449926 297 lldb_git_commit_hash: None,
0731742a 298 miri_git_commit_hash: None,
b7449926
XL
299
300 should_sign,
32a655c1
SL
301 }.build();
302}
303
304impl Builder {
305 fn build(&mut self) {
306 self.rust_version = self.version("rust", "x86_64-unknown-linux-gnu");
307 self.cargo_version = self.version("cargo", "x86_64-unknown-linux-gnu");
3b2f2976 308 self.rls_version = self.version("rls", "x86_64-unknown-linux-gnu");
8faf50e0 309 self.clippy_version = self.version("clippy", "x86_64-unknown-linux-gnu");
abe05a73 310 self.rustfmt_version = self.version("rustfmt", "x86_64-unknown-linux-gnu");
8faf50e0 311 self.llvm_tools_version = self.version("llvm-tools", "x86_64-unknown-linux-gnu");
b7449926
XL
312 // lldb is only built for macOS.
313 self.lldb_version = self.version("lldb", "x86_64-apple-darwin");
0731742a 314 self.miri_version = self.version("miri", "x86_64-unknown-linux-gnu");
abe05a73 315
ea8adc8c
XL
316 self.rust_git_commit_hash = self.git_commit_hash("rust", "x86_64-unknown-linux-gnu");
317 self.cargo_git_commit_hash = self.git_commit_hash("cargo", "x86_64-unknown-linux-gnu");
318 self.rls_git_commit_hash = self.git_commit_hash("rls", "x86_64-unknown-linux-gnu");
8faf50e0 319 self.clippy_git_commit_hash = self.git_commit_hash("clippy", "x86_64-unknown-linux-gnu");
abe05a73 320 self.rustfmt_git_commit_hash = self.git_commit_hash("rustfmt", "x86_64-unknown-linux-gnu");
8faf50e0
XL
321 self.llvm_tools_git_commit_hash = self.git_commit_hash("llvm-tools",
322 "x86_64-unknown-linux-gnu");
b7449926 323 self.lldb_git_commit_hash = self.git_commit_hash("lldb", "x86_64-unknown-linux-gnu");
0731742a 324 self.miri_git_commit_hash = self.git_commit_hash("miri", "x86_64-unknown-linux-gnu");
32a655c1
SL
325
326 self.digest_and_sign();
3b2f2976 327 let manifest = self.build_manifest();
ea8adc8c 328 self.write_channel_files(&self.rust_release, &manifest);
8bb4bdeb
XL
329
330 if self.rust_release != "beta" && self.rust_release != "nightly" {
ea8adc8c 331 self.write_channel_files("stable", &manifest);
32a655c1
SL
332 }
333 }
334
335 fn digest_and_sign(&mut self) {
336 for file in t!(self.input.read_dir()).map(|e| t!(e).path()) {
337 let filename = file.file_name().unwrap().to_str().unwrap();
338 let digest = self.hash(&file);
339 self.sign(&file);
340 assert!(self.digests.insert(filename.to_string(), digest).is_none());
341 }
342 }
343
344 fn build_manifest(&mut self) -> Manifest {
345 let mut manifest = Manifest {
346 manifest_version: "2".to_string(),
347 date: self.date.to_string(),
cc61c64b 348 pkg: BTreeMap::new(),
ea8adc8c 349 renames: BTreeMap::new(),
0731742a 350 profiles: BTreeMap::new(),
32a655c1
SL
351 };
352
353 self.package("rustc", &mut manifest.pkg, HOSTS);
354 self.package("cargo", &mut manifest.pkg, HOSTS);
355 self.package("rust-mingw", &mut manifest.pkg, MINGW);
356 self.package("rust-std", &mut manifest.pkg, TARGETS);
b7449926 357 self.package("rust-docs", &mut manifest.pkg, DOCS_TARGETS);
32a655c1 358 self.package("rust-src", &mut manifest.pkg, &["*"]);
ea8adc8c 359 self.package("rls-preview", &mut manifest.pkg, HOSTS);
8faf50e0 360 self.package("clippy-preview", &mut manifest.pkg, HOSTS);
abe05a73 361 self.package("rustfmt-preview", &mut manifest.pkg, HOSTS);
cc61c64b 362 self.package("rust-analysis", &mut manifest.pkg, TARGETS);
8faf50e0 363 self.package("llvm-tools-preview", &mut manifest.pkg, TARGETS);
b7449926 364 self.package("lldb-preview", &mut manifest.pkg, TARGETS);
8bb4bdeb 365
0731742a
XL
366 self.profile("minimal",
367 &mut manifest.profiles,
368 &["rustc", "cargo", "rust-std", "rust-mingw"]);
369 self.profile("default",
370 &mut manifest.profiles,
371 &["rustc", "cargo", "rust-std", "rust-mingw",
372 "rust-docs", "rustfmt-preview", "clippy-preview"]);
373 self.profile("complete",
374 &mut manifest.profiles,
375 &["rustc", "cargo", "rust-std", "rust-mingw",
376 "rust-docs", "rustfmt-preview", "clippy-preview",
377 "rls-preview", "rust-src", "llvm-tools-preview",
378 "lldb-preview", "rust-analysis"]);
379
b7449926 380 manifest.renames.insert("rls".to_owned(), Rename { to: "rls-preview".to_owned() });
13cf67c4
XL
381 manifest.renames.insert("rustfmt".to_owned(), Rename { to: "rustfmt-preview".to_owned() });
382 manifest.renames.insert("clippy".to_owned(), Rename { to: "clippy-preview".to_owned() });
ea8adc8c 383
32a655c1 384 let mut pkg = Package {
abe05a73
XL
385 version: self.cached_version("rust")
386 .as_ref()
387 .expect("Couldn't find Rust version")
388 .clone(),
ea8adc8c 389 git_commit_hash: self.cached_git_commit_hash("rust").clone(),
cc61c64b 390 target: BTreeMap::new(),
32a655c1
SL
391 };
392 for host in HOSTS {
393 let filename = self.filename("rust", host);
394 let digest = match self.digests.remove(&filename) {
395 Some(digest) => digest,
396 None => {
7cac9316 397 pkg.target.insert(host.to_string(), Target::unavailable());
32a655c1
SL
398 continue
399 }
400 };
7cac9316
XL
401 let xz_filename = filename.replace(".tar.gz", ".tar.xz");
402 let xz_digest = self.digests.remove(&xz_filename);
32a655c1
SL
403 let mut components = Vec::new();
404 let mut extensions = Vec::new();
405
8bb4bdeb
XL
406 // rustc/rust-std/cargo/docs are all required, and so is rust-mingw
407 // if it's available for the target.
32a655c1
SL
408 components.extend(vec![
409 Component { pkg: "rustc".to_string(), target: host.to_string() },
410 Component { pkg: "rust-std".to_string(), target: host.to_string() },
411 Component { pkg: "cargo".to_string(), target: host.to_string() },
8bb4bdeb 412 Component { pkg: "rust-docs".to_string(), target: host.to_string() },
32a655c1
SL
413 ]);
414 if host.contains("pc-windows-gnu") {
415 components.push(Component {
416 pkg: "rust-mingw".to_string(),
417 target: host.to_string(),
418 });
419 }
420
b7449926
XL
421 // Tools are always present in the manifest, but might be marked as unavailable if they
422 // weren't built
423 extensions.extend(vec![
424 Component { pkg: "clippy-preview".to_string(), target: host.to_string() },
425 Component { pkg: "rls-preview".to_string(), target: host.to_string() },
426 Component { pkg: "rustfmt-preview".to_string(), target: host.to_string() },
427 Component { pkg: "llvm-tools-preview".to_string(), target: host.to_string() },
428 Component { pkg: "lldb-preview".to_string(), target: host.to_string() },
429 Component { pkg: "rust-analysis".to_string(), target: host.to_string() },
430 ]);
431
32a655c1
SL
432 for target in TARGETS {
433 if target != host {
434 extensions.push(Component {
435 pkg: "rust-std".to_string(),
436 target: target.to_string(),
437 });
438 }
439 }
440 extensions.push(Component {
441 pkg: "rust-src".to_string(),
442 target: "*".to_string(),
443 });
444
564c78a2
XL
445 // If the components/extensions don't actually exist for this
446 // particular host/target combination then nix it entirely from our
447 // lists.
448 {
449 let has_component = |c: &Component| {
450 if c.target == "*" {
451 return true
452 }
453 let pkg = match manifest.pkg.get(&c.pkg) {
454 Some(p) => p,
455 None => return false,
456 };
b7449926 457 pkg.target.get(&c.target).is_some()
564c78a2
XL
458 };
459 extensions.retain(&has_component);
460 components.retain(&has_component);
461 }
462
32a655c1
SL
463 pkg.target.insert(host.to_string(), Target {
464 available: true,
7cac9316 465 url: Some(self.url(&filename)),
8bb4bdeb 466 hash: Some(digest),
7cac9316
XL
467 xz_url: xz_digest.as_ref().map(|_| self.url(&xz_filename)),
468 xz_hash: xz_digest,
32a655c1
SL
469 components: Some(components),
470 extensions: Some(extensions),
471 });
472 }
473 manifest.pkg.insert("rust".to_string(), pkg);
474
9fa01778 475 manifest
32a655c1
SL
476 }
477
0731742a
XL
478 fn profile(&mut self,
479 profile_name: &str,
480 dst: &mut BTreeMap<String, Vec<String>>,
481 pkgs: &[&str]) {
482 dst.insert(profile_name.to_owned(), pkgs.iter().map(|s| (*s).to_owned()).collect());
483 }
484
32a655c1
SL
485 fn package(&mut self,
486 pkgname: &str,
cc61c64b 487 dst: &mut BTreeMap<String, Package>,
32a655c1 488 targets: &[&str]) {
b7449926
XL
489 let (version, is_present) = match *self.cached_version(pkgname) {
490 Some(ref version) => (version.clone(), true),
491 None => (String::new(), false),
abe05a73
XL
492 };
493
32a655c1 494 let targets = targets.iter().map(|name| {
b7449926
XL
495 if is_present {
496 let filename = self.filename(pkgname, name);
497 let digest = match self.digests.remove(&filename) {
498 Some(digest) => digest,
499 None => return (name.to_string(), Target::unavailable()),
500 };
501 let xz_filename = filename.replace(".tar.gz", ".tar.xz");
502 let xz_digest = self.digests.remove(&xz_filename);
503
504 (name.to_string(), Target {
505 available: true,
506 url: Some(self.url(&filename)),
507 hash: Some(digest),
508 xz_url: xz_digest.as_ref().map(|_| self.url(&xz_filename)),
509 xz_hash: xz_digest,
510 components: None,
511 extensions: None,
512 })
513 } else {
514 // If the component is not present for this build add it anyway but mark it as
515 // unavailable -- this way rustup won't allow upgrades without --force
516 (name.to_string(), Target {
517 available: false,
518 url: None,
519 hash: None,
520 xz_url: None,
521 xz_hash: None,
522 components: None,
523 extensions: None,
524 })
525 }
32a655c1
SL
526 }).collect();
527
528 dst.insert(pkgname.to_string(), Package {
abe05a73 529 version,
ea8adc8c 530 git_commit_hash: self.cached_git_commit_hash(pkgname).clone(),
32a655c1
SL
531 target: targets,
532 });
533 }
534
7cac9316 535 fn url(&self, filename: &str) -> String {
32a655c1
SL
536 format!("{}/{}/{}",
537 self.s3_address,
538 self.date,
7cac9316 539 filename)
32a655c1
SL
540 }
541
542 fn filename(&self, component: &str, target: &str) -> String {
543 if component == "rust-src" {
8bb4bdeb 544 format!("rust-src-{}.tar.gz", self.rust_release)
32a655c1 545 } else if component == "cargo" {
8bb4bdeb 546 format!("cargo-{}-{}.tar.gz", self.cargo_release, target)
3b2f2976
XL
547 } else if component == "rls" || component == "rls-preview" {
548 format!("rls-{}-{}.tar.gz", self.rls_release, target)
8faf50e0
XL
549 } else if component == "clippy" || component == "clippy-preview" {
550 format!("clippy-{}-{}.tar.gz", self.clippy_release, target)
abe05a73
XL
551 } else if component == "rustfmt" || component == "rustfmt-preview" {
552 format!("rustfmt-{}-{}.tar.gz", self.rustfmt_release, target)
8faf50e0
XL
553 } else if component == "llvm-tools" || component == "llvm-tools-preview" {
554 format!("llvm-tools-{}-{}.tar.gz", self.llvm_tools_release, target)
b7449926
XL
555 } else if component == "lldb" || component == "lldb-preview" {
556 format!("lldb-{}-{}.tar.gz", self.lldb_release, target)
0731742a
XL
557 } else if component == "miri" || component == "miri-preview" {
558 format!("miri-{}-{}.tar.gz", self.miri_release, target)
32a655c1 559 } else {
8bb4bdeb 560 format!("{}-{}-{}.tar.gz", component, self.rust_release, target)
32a655c1
SL
561 }
562 }
563
abe05a73 564 fn cached_version(&self, component: &str) -> &Option<String> {
32a655c1
SL
565 if component == "cargo" {
566 &self.cargo_version
3b2f2976
XL
567 } else if component == "rls" || component == "rls-preview" {
568 &self.rls_version
8faf50e0
XL
569 } else if component == "clippy" || component == "clippy-preview" {
570 &self.clippy_version
abe05a73
XL
571 } else if component == "rustfmt" || component == "rustfmt-preview" {
572 &self.rustfmt_version
8faf50e0
XL
573 } else if component == "llvm-tools" || component == "llvm-tools-preview" {
574 &self.llvm_tools_version
b7449926
XL
575 } else if component == "lldb" || component == "lldb-preview" {
576 &self.lldb_version
0731742a
XL
577 } else if component == "miri" || component == "miri-preview" {
578 &self.miri_version
32a655c1
SL
579 } else {
580 &self.rust_version
581 }
582 }
583
ea8adc8c
XL
584 fn cached_git_commit_hash(&self, component: &str) -> &Option<String> {
585 if component == "cargo" {
586 &self.cargo_git_commit_hash
587 } else if component == "rls" || component == "rls-preview" {
588 &self.rls_git_commit_hash
8faf50e0
XL
589 } else if component == "clippy" || component == "clippy-preview" {
590 &self.clippy_git_commit_hash
abe05a73
XL
591 } else if component == "rustfmt" || component == "rustfmt-preview" {
592 &self.rustfmt_git_commit_hash
8faf50e0
XL
593 } else if component == "llvm-tools" || component == "llvm-tools-preview" {
594 &self.llvm_tools_git_commit_hash
b7449926
XL
595 } else if component == "lldb" || component == "lldb-preview" {
596 &self.lldb_git_commit_hash
0731742a
XL
597 } else if component == "miri" || component == "miri-preview" {
598 &self.miri_git_commit_hash
ea8adc8c
XL
599 } else {
600 &self.rust_git_commit_hash
601 }
602 }
603
abe05a73 604 fn version(&self, component: &str, target: &str) -> Option<String> {
32a655c1
SL
605 let mut cmd = Command::new("tar");
606 let filename = self.filename(component, target);
607 cmd.arg("xf")
608 .arg(self.input.join(&filename))
609 .arg(format!("{}/version", filename.replace(".tar.gz", "")))
610 .arg("-O");
ea8adc8c 611 let output = t!(cmd.output());
abe05a73
XL
612 if output.status.success() {
613 Some(String::from_utf8_lossy(&output.stdout).trim().to_string())
614 } else {
615 // Perhaps we didn't build this package.
616 None
ea8adc8c 617 }
ea8adc8c
XL
618 }
619
620 fn git_commit_hash(&self, component: &str, target: &str) -> Option<String> {
621 let mut cmd = Command::new("tar");
622 let filename = self.filename(component, target);
623 cmd.arg("xf")
624 .arg(self.input.join(&filename))
625 .arg(format!("{}/git-commit-hash", filename.replace(".tar.gz", "")))
626 .arg("-O");
627 let output = t!(cmd.output());
628 if output.status.success() {
629 Some(String::from_utf8_lossy(&output.stdout).trim().to_string())
630 } else {
ea8adc8c 631 None
32a655c1 632 }
32a655c1
SL
633 }
634
635 fn hash(&self, path: &Path) -> String {
636 let sha = t!(Command::new("shasum")
637 .arg("-a").arg("256")
638 .arg(path.file_name().unwrap())
639 .current_dir(path.parent().unwrap())
640 .output());
641 assert!(sha.status.success());
642
643 let filename = path.file_name().unwrap().to_str().unwrap();
644 let sha256 = self.output.join(format!("{}.sha256", filename));
0731742a 645 t!(fs::write(&sha256, &sha.stdout));
32a655c1
SL
646
647 let stdout = String::from_utf8_lossy(&sha.stdout);
648 stdout.split_whitespace().next().unwrap().to_string()
649 }
650
651 fn sign(&self, path: &Path) {
b7449926
XL
652 if !self.should_sign {
653 return;
654 }
655
32a655c1
SL
656 let filename = path.file_name().unwrap().to_str().unwrap();
657 let asc = self.output.join(format!("{}.asc", filename));
658 println!("signing: {:?}", path);
659 let mut cmd = Command::new("gpg");
69743fb6
XL
660 cmd.arg("--pinentry-mode=loopback")
661 .arg("--no-tty")
32a655c1 662 .arg("--yes")
69743fb6 663 .arg("--batch")
32a655c1 664 .arg("--passphrase-fd").arg("0")
ea8adc8c 665 .arg("--personal-digest-preferences").arg("SHA512")
32a655c1
SL
666 .arg("--armor")
667 .arg("--output").arg(&asc)
668 .arg("--detach-sign").arg(path)
669 .stdin(Stdio::piped());
670 let mut child = t!(cmd.spawn());
671 t!(child.stdin.take().unwrap().write_all(self.gpg_passphrase.as_bytes()));
672 assert!(t!(child.wait()).success());
673 }
674
ea8adc8c
XL
675 fn write_channel_files(&self, channel_name: &str, manifest: &Manifest) {
676 self.write(&toml::to_string(&manifest).unwrap(), channel_name, ".toml");
677 self.write(&manifest.date, channel_name, "-date.txt");
678 self.write(manifest.pkg["rust"].git_commit_hash.as_ref().unwrap(),
679 channel_name, "-git-commit-hash.txt");
32a655c1 680 }
32a655c1 681
ea8adc8c
XL
682 fn write(&self, contents: &str, channel_name: &str, suffix: &str) {
683 let dst = self.output.join(format!("channel-rust-{}{}", channel_name, suffix));
0731742a 684 t!(fs::write(&dst, contents));
8bb4bdeb
XL
685 self.hash(&dst);
686 self.sign(&dst);
32a655c1
SL
687 }
688}