feat: add metapackage build support and fail-fast custom scripts

- add BuildType::Meta handling in builder and interactive spec output
- allow metapackage specs without sources and expose is_metapackage()
- avoid build deps in install planning for metapackages
- run custom non-function build.sh scripts with `sh -e` to stop on first failure
- add regression test for custom script fail-fast behavior
- apply small cleanup refactors (let-chains/iterator simplifications)
This commit is contained in:
2026-02-25 16:49:36 -06:00
parent 9953d4b2ee
commit d9a30f5d56
13 changed files with 168 additions and 94 deletions
+31 -1
View File
@@ -113,7 +113,9 @@ pub fn build(
build_function_mode_command(spec, destdir, &abs_build_script)?
} else {
let mut cmd = fakeroot::wrap_install_command("sh", destdir);
cmd.arg(&abs_build_script);
// Run custom scripts with `-e` so command failures stop the build immediately
// instead of being masked by later shell commands.
cmd.arg("-e").arg(&abs_build_script);
cmd
};
cmd.current_dir(&build_dir);
@@ -422,4 +424,32 @@ depot_install() {
assert!(err.to_string().contains("Custom build script failed"));
Ok(())
}
#[test]
fn test_build_non_function_mode_stops_on_first_command_failure() -> Result<()> {
let tmp_src = tempdir()?;
let tmp_dest = tempdir()?;
let build_sh = tmp_src.path().join("build.sh");
std::fs::write(
&build_sh,
r#"#!/bin/sh
false
exit 0
"#,
)?;
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
let mut perms = std::fs::metadata(&build_sh)?.permissions();
perms.set_mode(0o755);
std::fs::set_permissions(&build_sh, perms)?;
}
let spec = mk_spec("custom-fail-fast", "1.0");
let err = build(&spec, tmp_src.path(), tmp_dest.path(), None, true)
.expect_err("non-function custom scripts should fail when a command fails");
assert!(err.to_string().contains("Custom build script failed"));
Ok(())
}
}
+6
View File
@@ -226,6 +226,12 @@ pub fn build(
BuildType::Python => python::build(spec, src_dir, destdir, cross, export_compiler_flags),
BuildType::Rust => rust::build(spec, src_dir, destdir, cross, export_compiler_flags),
BuildType::Bin => bin::build(spec, src_dir, destdir, cross, export_compiler_flags),
BuildType::Meta => {
// Metapackages are metadata-only; create an empty staging root and let
// packaging/installation metadata carry dependencies.
std::fs::create_dir_all(destdir)?;
Ok(())
}
BuildType::Makefile => {
makefile::build(spec, src_dir, destdir, cross, export_compiler_flags)
}