Skip to content

Commit 6a57629

Browse files
committed
Give a better error message when the CI download fails
1 parent 290d792 commit 6a57629

File tree

2 files changed

+66
-12
lines changed

2 files changed

+66
-12
lines changed

src/bootstrap/src/core/download.rs

+57-12
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@ use std::{
66
path::{Path, PathBuf},
77
process::{Command, Stdio},
88
sync::OnceLock,
9+
time::SystemTime,
910
};
1011

1112
use build_helper::ci::CiEnv;
1213
use xz2::bufread::XzDecoder;
1314

1415
use crate::core::config::RustfmtMetadata;
15-
use crate::utils::helpers::{check_run, exe, program_out_of_date};
16+
use crate::utils::helpers::{check_run, exe, program_out_of_date, try_output};
1617
use crate::{core::build_steps::llvm::detect_llvm_sha, utils::helpers::hex_encode};
1718
use crate::{t, Config};
1819

@@ -194,7 +195,7 @@ impl Config {
194195
let _ = try_run(self, patchelf.arg(fname));
195196
}
196197

197-
fn download_file(&self, url: &str, dest_path: &Path, help_on_error: &str) {
198+
fn download_file(&self, url: &str, dest_path: &Path, help_on_error: &str, commit: &str) {
198199
self.verbose(|| println!("download {url}"));
199200
// Use a temporary file in case we crash while downloading, to avoid a corrupt download in cache/.
200201
let tempfile = self.tempdir().join(dest_path.file_name().unwrap());
@@ -203,7 +204,7 @@ impl Config {
203204
// protocols without worrying about merge conflicts if we change the HTTP implementation.
204205
match url.split_once("://").map(|(proto, _)| proto) {
205206
Some("http") | Some("https") => {
206-
self.download_http_with_retries(&tempfile, url, help_on_error)
207+
self.download_http_with_retries(&tempfile, url, help_on_error, commit)
207208
}
208209
Some(other) => panic!("unsupported protocol {other} in {url}"),
209210
None => panic!("no protocol in {url}"),
@@ -214,7 +215,13 @@ impl Config {
214215
);
215216
}
216217

217-
fn download_http_with_retries(&self, tempfile: &Path, url: &str, help_on_error: &str) {
218+
fn download_http_with_retries(
219+
&self,
220+
tempfile: &Path,
221+
url: &str,
222+
help_on_error: &str,
223+
commit: &str,
224+
) {
218225
println!("downloading {url}");
219226
// Try curl. If that fails and we are on windows, fallback to PowerShell.
220227
let mut curl = Command::new("curl");
@@ -250,19 +257,52 @@ impl Config {
250257
"(New-Object System.Net.WebClient).DownloadFile('{}', '{}')",
251258
url, tempfile.to_str().expect("invalid UTF-8 not supported with powershell downloads"),
252259
),
253-
])).is_err() {
260+
])).is_ok() {
254261
return;
255262
}
256263
eprintln!("\nspurious failure, trying again");
257264
}
258265
}
259266
if !help_on_error.is_empty() {
260267
eprintln!("{help_on_error}");
268+
Self::check_outdated(commit);
261269
}
262270
crate::exit!(1);
263271
}
264272
}
265273

274+
fn check_outdated(commit: &str) {
275+
let build_date: String = try_output(
276+
Command::new("git")
277+
.arg("show")
278+
.arg("-s")
279+
.arg("--format=%ct") // Commit date in unix timestamp
280+
.arg(commit),
281+
);
282+
match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
283+
Ok(n) => {
284+
let replaced = build_date.trim();
285+
let diff = n.as_secs() - replaced.parse::<u64>().unwrap();
286+
if diff >= 165 * 24 * 60 * 60 {
287+
let build_date: String = try_output(
288+
Command::new("git")
289+
.arg("show")
290+
.arg("-s")
291+
.arg("--format=%cr") // Commit date in `x days ago` format
292+
.arg(commit),
293+
);
294+
eprintln!(
295+
"NOTE: tried to download builds for {} (from {}), CI builds are only retained for 168 days",
296+
commit, build_date
297+
);
298+
eprintln!("HELP: Consider updating your copy of the rust sources");
299+
return;
300+
}
301+
}
302+
Err(_) => panic!("SystemTime before UNIX EPOCH!"),
303+
}
304+
}
305+
266306
fn unpack(&self, tarball: &Path, dst: &Path, pattern: &str) {
267307
eprintln!("extracting {} to {}", tarball.display(), dst.display());
268308
if !dst.exists() {
@@ -495,7 +535,7 @@ impl Config {
495535
let extra_components = ["cargo"];
496536

497537
let download_beta_component = |config: &Config, filename, prefix: &_, date: &_| {
498-
config.download_component(DownloadSource::Dist, filename, prefix, date, "stage0")
538+
config.download_component(DownloadSource::Dist, filename, prefix, date, "stage0");
499539
};
500540

501541
self.download_toolchain(
@@ -573,7 +613,7 @@ impl Config {
573613
mode: DownloadSource,
574614
filename: String,
575615
prefix: &str,
576-
key: &str,
616+
commit: &str,
577617
destination: &str,
578618
) {
579619
if self.dry_run() {
@@ -583,7 +623,7 @@ impl Config {
583623
let cache_dst =
584624
self.bootstrap_cache_path.as_ref().cloned().unwrap_or_else(|| self.out.join("cache"));
585625

586-
let cache_dir = cache_dst.join(key);
626+
let cache_dir = cache_dst.join(commit);
587627
if !cache_dir.exists() {
588628
t!(fs::create_dir_all(&cache_dir));
589629
}
@@ -599,15 +639,15 @@ impl Config {
599639
};
600640
let url = format!(
601641
"{}/{filename}",
602-
key.strip_suffix(&format!("-{}", self.llvm_assertions)).unwrap()
642+
commit.strip_suffix(&format!("-{}", self.llvm_assertions)).unwrap()
603643
);
604644
(dist_server, url, false)
605645
}
606646
DownloadSource::Dist => {
607647
let dist_server = env::var("RUSTUP_DIST_SERVER")
608648
.unwrap_or(self.stage0_metadata.config.dist_server.to_string());
609649
// NOTE: make `dist` part of the URL because that's how it's stored in src/stage0.json
610-
(dist_server, format!("dist/{key}/{filename}"), true)
650+
(dist_server, format!("dist/{commit}/{filename}"), true)
611651
}
612652
};
613653

@@ -655,7 +695,7 @@ HELP: if trying to compile an old commit of rustc, disable `download-rustc` in c
655695
download-rustc = false
656696
";
657697
}
658-
self.download_file(&format!("{base_url}/{url}"), &tarball, help_on_error);
698+
self.download_file(&format!("{base_url}/{url}"), &tarball, help_on_error, &commit);
659699
if let Some(sha256) = checksum {
660700
if !self.verify(&tarball, sha256) {
661701
panic!("failed to verify {}", tarball.display());
@@ -737,7 +777,12 @@ download-rustc = false
737777
[llvm]
738778
download-ci-llvm = false
739779
";
740-
self.download_file(&format!("{base}/{llvm_sha}/{filename}"), &tarball, help_on_error);
780+
self.download_file(
781+
&format!("{base}/{llvm_sha}/{filename}"),
782+
&tarball,
783+
help_on_error,
784+
&llvm_sha,
785+
);
741786
}
742787
let llvm_root = self.ci_llvm_root();
743788
self.unpack(&tarball, &llvm_root, "rust-dev");

src/bootstrap/src/utils/helpers.rs

+9
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,15 @@ pub fn output(cmd: &mut Command) -> String {
271271
String::from_utf8(output.stdout).unwrap()
272272
}
273273

274+
#[track_caller]
275+
pub fn try_output(cmd: &mut Command) -> String {
276+
let output = match cmd.stderr(Stdio::inherit()).output() {
277+
Ok(status) => status,
278+
Err(e) => fail(&format!("failed to execute command: {cmd:?}\nERROR: {e}")),
279+
};
280+
String::from_utf8(output.stdout).unwrap()
281+
}
282+
274283
/// Returns the last-modified time for `path`, or zero if it doesn't exist.
275284
pub fn mtime(path: &Path) -> SystemTime {
276285
fs::metadata(path).and_then(|f| f.modified()).unwrap_or(UNIX_EPOCH)

0 commit comments

Comments
 (0)