about summary refs log tree commit diff
path: root/src/bootstrap
diff options
context:
space:
mode:
authorbinarycat <binarycat@envs.net>2024-08-15 16:22:01 -0400
committerbinarycat <binarycat@envs.net>2024-08-16 19:30:20 -0400
commit12e638978814d84e4e09b172f784d5f16759d8e1 (patch)
tree3d92785981eb117fdcc236ba3075fd7fdd1ce161 /src/bootstrap
parent899eb03926be23f2e5d2ffcaa1d6f9ac40af7f13 (diff)
downloadrust-12e638978814d84e4e09b172f784d5f16759d8e1.tar.gz
rust-12e638978814d84e4e09b172f784d5f16759d8e1.zip
bootstrap: improve error recovery flags to curl
alternative to #128459

fixes #110178
Diffstat (limited to 'src/bootstrap')
-rw-r--r--src/bootstrap/bootstrap.py8
-rw-r--r--src/bootstrap/src/core/download.rs31
2 files changed, 38 insertions, 1 deletions
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 4e8e0fd2532..5ea4b4882a9 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -79,6 +79,8 @@ def get(base, url, path, checksums, verbose=False):
                 eprint("removing", temp_path)
             os.unlink(temp_path)
 
+def curl_version():
+    return float(re.match(bytes("^curl ([0-9]+\\.[0-9]+)", "utf8"), require(["curl", "-V"]))[1])
 
 def download(path, url, probably_big, verbose):
     for _ in range(4):
@@ -107,11 +109,15 @@ def _download(path, url, probably_big, verbose, exception):
         # If curl is not present on Win32, we should not sys.exit
         #   but raise `CalledProcessError` or `OSError` instead
         require(["curl", "--version"], exception=platform_is_win32())
-        run(["curl", option,
+        extra_flags = []
+        if curl_version() > 7.70:
+            extra_flags = [ "--retry-all-errors" ]
+        run(["curl", option] + extra_flags + [
             "-L", # Follow redirect.
             "-y", "30", "-Y", "10",    # timeout if speed is < 10 bytes/sec for > 30 seconds
             "--connect-timeout", "30",  # timeout if cannot connect within 30 seconds
             "-o", path,
+            "--continue-at", "-",
             "--retry", "3", "-SRf", url],
             verbose=verbose,
             exception=True, # Will raise RuntimeError on failure
diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs
index 4d1aea3cd95..ed7637e8ee0 100644
--- a/src/bootstrap/src/core/download.rs
+++ b/src/bootstrap/src/core/download.rs
@@ -21,6 +21,31 @@ fn try_run(config: &Config, cmd: &mut Command) -> Result<(), ()> {
     config.try_run(cmd)
 }
 
+fn extract_curl_version(out: &[u8]) -> f32 {
+    let out = &out[5..];
+    let Some(i) = out.iter().position(|&x| x == b' ') else { return 0.0 };
+    let out = &out[..i];
+    let Some(k) = out.iter().rev().position(|&x| x == b'.') else { return 0.0 };
+    let out = &out[..out.len()-k-1];
+    std::str::from_utf8(out).unwrap().parse().unwrap_or(0.0)
+}
+
+#[test]
+fn test_extract_curl_version() {
+    assert_eq!(extract_curl_version(b"\
+        curl 8.4.0 (x86_64-pc-linux-gnu) libcurl/8.4.0 \
+        OpenSSL/3.0.13 zlib/1.3 brotli/1.1.0 zstd/1.5.5 libidn2/2.3.4 \
+        libssh2/1.11.0 nghttp2/1.57.0"), 8.4);
+}
+
+fn curl_version() -> f32 {
+    let mut curl = Command::new("curl");
+    curl.arg("-V");
+    let Ok(out) = curl.output() else { return 0.0 };
+    let out = out.stdout;
+    extract_curl_version(&out)
+}
+
 /// Generic helpers that are useful anywhere in bootstrap.
 impl Config {
     pub fn is_verbose(&self) -> bool {
@@ -219,6 +244,8 @@ impl Config {
             "30", // timeout if cannot connect within 30 seconds
             "-o",
             tempfile.to_str().unwrap(),
+            "--continue-at",
+            "-",
             "--retry",
             "3",
             "-SRf",
@@ -229,6 +256,10 @@ impl Config {
         } else {
             curl.arg("--progress-bar");
         }
+        // --retry-all-errors was added in 7.71.0, don't use it if curl is old.
+        if dbg!(curl_version()) > 7.70 {
+            curl.arg("--retry-all-errors");
+        }
         curl.arg(url);
         if !self.check_run(&mut curl) {
             if self.build.contains("windows-msvc") {