refactor command flow and add signed package/hook safety

- split CLI definitions and command execution out of main.rs into new cli.rs and commands.rs modules\n- add transaction hook support via /etc/depot.d/hooks/*.toml with pre/post phases, operation/package/path filters, wildcard negation, and optional affected-path stdin\n- execute transaction hooks around install/update/remove operations and add package-action prompts for install/build/remove flows\n- require and verify detached minisign signatures for binary package archives when allow_unsigned=false, including cache handling and tests\n- persist optional dependencies from package metadata into repo index data and include optional deps in produced metadata\n- update dependency/planner logic to ignore dependencies provided by local split outputs and stop pulling test deps into install planning\n- auto-disable tests when required test dependencies are missing instead of hard-failing build/install paths\n- improve autotools defaults by injecting standard install directory flags when supported and preserving user overrides\n- remove static .a archives during staging by default with new build.flags.no_delete_static escape hatch\n- preserve symlinks and file metadata (permissions/timestamps) in extractor fallback copy path and add regression tests\n- refresh README docs for detached package signatures, optional dependencies, and transaction hooks\n- adjust dependency set: add filetime, disable reqwest default features, and simplify git2/OpenSSL linkage
This commit is contained in:
2026-02-28 00:54:08 -06:00
parent e045ae78fd
commit ce5fefa833
19 changed files with 3863 additions and 2923 deletions
+36 -1
View File
@@ -640,6 +640,10 @@ pub fn create_interactive() -> Result<PackageSpec> {
"Test dependency",
"Package needed only for running package test suites",
)?;
let optional_deps = prompt_repeating_list(
"Optional dependency",
"Package that enables optional runtime functionality",
)?;
Ok(PackageSpec {
package: PackageInfo {
@@ -659,6 +663,7 @@ pub fn create_interactive() -> Result<PackageSpec> {
build: build_deps,
runtime: runtime_deps,
test: test_deps,
optional: optional_deps,
},
package_alternatives: Default::default(),
package_dependencies: Default::default(),
@@ -875,6 +880,12 @@ pub fn spec_to_minimal_toml(spec: &PackageSpec) -> anyhow::Result<String> {
if spec.build.flags.no_strip != defaults.no_strip {
flags_tbl.insert("no_strip".into(), Value::Boolean(spec.build.flags.no_strip));
}
if spec.build.flags.no_delete_static != defaults.no_delete_static {
flags_tbl.insert(
"no_delete_static".into(),
Value::Boolean(spec.build.flags.no_delete_static),
);
}
if spec.build.flags.no_compress_man != defaults.no_compress_man {
flags_tbl.insert(
"no_compress_man".into(),
@@ -1221,6 +1232,7 @@ pub fn spec_to_minimal_toml(spec: &PackageSpec) -> anyhow::Result<String> {
if !spec.dependencies.build.is_empty()
|| !spec.dependencies.runtime.is_empty()
|| !spec.dependencies.test.is_empty()
|| !spec.dependencies.optional.is_empty()
{
let mut dep_tbl = Table::new();
if !spec.dependencies.build.is_empty() {
@@ -1259,6 +1271,18 @@ pub fn spec_to_minimal_toml(spec: &PackageSpec) -> anyhow::Result<String> {
),
);
}
if !spec.dependencies.optional.is_empty() {
dep_tbl.insert(
"optional".into(),
Value::Array(
spec.dependencies
.optional
.iter()
.map(|s| Value::String(s.clone()))
.collect(),
),
);
}
root.insert("dependencies".into(), Value::Table(dep_tbl));
}
@@ -1412,6 +1436,7 @@ mod tests {
flags.keep = vec!["etc/locale.gen".into()];
flags.no_flags = true;
flags.no_strip = true;
flags.no_delete_static = true;
flags.no_compress_man = true;
flags.skip_tests = true;
flags.make_vars = vec!["V=1".into()];
@@ -1467,6 +1492,7 @@ mod tests {
assert!(toml.contains("\"etc/locale.gen\""));
assert!(toml.contains("no_flags = true"));
assert!(toml.contains("no_strip = true"));
assert!(toml.contains("no_delete_static = true"));
assert!(toml.contains("no_compress_man = true"));
assert!(toml.contains("skip_tests = true"));
assert!(toml.contains("make_vars = ["));
@@ -1515,7 +1541,7 @@ mod tests {
}
#[test]
fn spec_to_minimal_toml_includes_test_dependencies() {
fn spec_to_minimal_toml_includes_test_and_optional_dependencies() {
let spec = PackageSpec {
package: PackageInfo {
name: "foo".into(),
@@ -1543,6 +1569,7 @@ mod tests {
build: vec![],
runtime: vec![],
test: vec!["python".into(), "bats".into()],
optional: vec!["gtk-doc".into()],
},
package_alternatives: Default::default(),
package_dependencies: Default::default(),
@@ -1559,6 +1586,13 @@ mod tests {
assert_eq!(test_deps.len(), 2);
assert_eq!(test_deps[0].as_str(), Some("python"));
assert_eq!(test_deps[1].as_str(), Some("bats"));
let optional_deps = val
.get("dependencies")
.and_then(|d| d.get("optional"))
.and_then(|t| t.as_array())
.expect("expected dependencies.optional array");
assert_eq!(optional_deps.len(), 1);
assert_eq!(optional_deps[0].as_str(), Some("gtk-doc"));
}
#[test]
@@ -1584,6 +1618,7 @@ mod tests {
build: Vec::new(),
runtime: vec!["foo".into(), "bar".into()],
test: Vec::new(),
optional: Vec::new(),
},
package_alternatives: Default::default(),
package_dependencies: Default::default(),