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:
+42
-3
@@ -70,9 +70,11 @@ impl PackageSpec {
|
||||
.unwrap_or_else(|| PathBuf::from("."));
|
||||
spec.apply_spec_appends(&appends)?;
|
||||
|
||||
// Require at least one source (remote or manual)
|
||||
if spec.source.is_empty() && spec.manual_sources.is_empty() {
|
||||
anyhow::bail!("Package must have at least one source or manual_sources entry");
|
||||
// Require at least one source (remote or manual) unless this is a metapackage.
|
||||
if spec.source.is_empty() && spec.manual_sources.is_empty() && !spec.is_metapackage() {
|
||||
anyhow::bail!(
|
||||
"Package must have at least one source or manual_sources entry (except build.type = \"meta\")"
|
||||
);
|
||||
}
|
||||
spec.validate_manual_sources()?;
|
||||
|
||||
@@ -167,6 +169,11 @@ impl PackageSpec {
|
||||
&self.source
|
||||
}
|
||||
|
||||
/// Returns true when this spec is a metadata-only package that exists to pull dependencies.
|
||||
pub fn is_metapackage(&self) -> bool {
|
||||
matches!(self.build.build_type, BuildType::Meta)
|
||||
}
|
||||
|
||||
/// Return all package outputs this spec will produce (primary + any extras)
|
||||
pub fn outputs(&self) -> Vec<PackageInfo> {
|
||||
let mut v = Vec::new();
|
||||
@@ -1202,6 +1209,37 @@ type = "custom"
|
||||
assert!(PackageSpec::from_file(&path).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_allows_metapackage_without_sources() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let path = tmp.path().join("pkg.toml");
|
||||
|
||||
std::fs::write(
|
||||
&path,
|
||||
r#"
|
||||
[package]
|
||||
name = "foo-meta"
|
||||
version = "1.0"
|
||||
description = "metapackage"
|
||||
homepage = "https://example.com"
|
||||
license = "MIT"
|
||||
|
||||
[build]
|
||||
type = "meta"
|
||||
|
||||
[dependencies]
|
||||
runtime = ["foo", "bar"]
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let spec = PackageSpec::from_file(&path).unwrap();
|
||||
assert!(spec.source.is_empty());
|
||||
assert!(spec.manual_sources.is_empty());
|
||||
assert!(spec.is_metapackage());
|
||||
assert_eq!(spec.dependencies.runtime, vec!["foo", "bar"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_manual_source_with_url() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
@@ -2297,6 +2335,7 @@ pub enum BuildType {
|
||||
Rust,
|
||||
Makefile,
|
||||
Bin,
|
||||
Meta,
|
||||
}
|
||||
|
||||
/// Build flags and toolchain configuration
|
||||
|
||||
Reference in New Issue
Block a user