fix(progress): close the sink on failed transfers

A download that died mid-stream (read error, digest mismatch)
returned before progress.finish(), leaving the sink with an open
operation — a lingering progress bar in the CLI and a broken
begin/finish pairing for any other sink.
This commit is contained in:
vhaudiquet committed 2026-10-29 23:56:38 +01:00
1 parent e4f712b782
commit a49cba488b
2 files changed
+12 -4

No files matched your search

+5 -1
View File
@@ -257,7 +257,6 @@ fn download_file(
progress.advance(n as u64);
}
progress.finish();
hasher.verify(expected)?;
if expected.is_some() {
log::debug!("Verified content digest: {}", dest.display());
@@ -270,6 +269,11 @@ fn download_file(
Ok(())
})();
// The operation ended — success or not. A sink is told finish()
// exactly once per begin(), so a failed transfer leaves no bar
// hanging and no implicit open operation behind it.
progress.finish();
if result.is_err() {
// Best-effort cleanup; ignore errors (file may not exist if creation failed).
let _ = std::fs::remove_file(&temp_dest);
+7 -3
View File
@@ -487,18 +487,22 @@ fn download_blob_with_auth(
}
file.flush().context("Failed to flush the layer file")?;
progress.finish();
// The blob was addressed by this digest in the manifest; a mismatch means
// truncated or tampered content. The blob lives in a temp directory that
// is discarded on error, so a bad layer never reaches the cache.
hasher.verify(Some(expected_digest)).with_context(|| {
let verified = hasher.verify(Some(expected_digest)).with_context(|| {
format!(
"layer blob {} failed verification against manifest digest",
url
)
})?;
});
// The operation ended — success or not. A sink is told finish()
// exactly once per begin(), so a failed layer leaves no bar
// hanging and no implicit open operation behind it.
progress.finish();
verified?;
Ok(())
}