cargo.build: write the SDK copy in the cache only when a build needs it

An unwritable cache makes only a build fail, with the folder in
data.output. The host still starts.
This commit is contained in:
2026-10-23 08:09:37 +01:00
parent 93f092e02b
commit 1386acc924
2 changed files with 58 additions and 17 deletions
+22 -17
View File
@@ -61,6 +61,7 @@ pub struct Cargo {
runner: PathBuf,
target: PathBuf,
sdk: PathBuf,
sdk_files: Arc<std::collections::BTreeMap<PathBuf, Vec<u8>>>,
}
impl Cargo {
/// Installs changed SDK files and selects the current sausage executable as runner.
@@ -126,25 +127,9 @@ impl Cargo {
let cached = std::path::absolute(cache)?
.join("sdk")
.join(format!("{:x}", hash.finalize()));
if !cached.is_dir() {
let parent = cached.parent().unwrap();
std::fs::create_dir_all(parent)
.with_context(|| format!("create {}", parent.display()))?;
let staging = tempfile::Builder::new()
.prefix("install-")
.tempdir_in(parent)?;
for (path, bytes) in &files {
write_changed(&staging.path().join(path), bytes)?;
}
// Another builder can publish the same complete, content-addressed SDK first.
if let Err(error) = std::fs::rename(staging.path(), &cached)
&& !cached.is_dir()
{
return Err(error).with_context(|| format!("install {}", cached.display()));
}
}
Ok(Self {
sdk: cached,
sdk_files: Arc::new(files),
target: std::path::absolute(cache)?.join("cargo-target"),
world,
runner,
@@ -177,7 +162,27 @@ impl Cargo {
let source = source.to_path_buf();
let copy = work.clone();
let sdk = self.sdk.clone();
let sdk_files = self.sdk_files.clone();
let build_guard = tokio::task::spawn_blocking(move || -> Result<_> {
// Host startup installs only the readable world copy. Builds populate the cache.
if !sdk.is_dir() {
let parent = sdk.parent().unwrap();
std::fs::create_dir_all(parent)
.with_context(|| format!("create {}", parent.display()))?;
let staging = tempfile::Builder::new()
.prefix("install-")
.tempdir_in(parent)
.with_context(|| format!("stage SDK in {}", parent.display()))?;
for (path, bytes) in sdk_files.iter() {
write_changed(&staging.path().join(path), bytes)?;
}
// Another builder can publish the same complete SDK first.
if let Err(error) = std::fs::rename(staging.path(), &sdk)
&& !sdk.is_dir()
{
return Err(error).with_context(|| format!("install {}", sdk.display()));
}
}
if cleanup.exists() {
std::fs::remove_dir_all(&cleanup)
.with_context(|| format!("remove {}", cleanup.display()))?;