diff options
| author | Hermes Agent <hermes@localhost> | 2026-08-12 02:33:28 +0000 |
|---|---|---|
| committer | Hermes Agent <hermes@localhost> | 2026-08-12 02:33:28 +0000 |
| commit | cad87b77c0003c851abb6264d3e373e9516edaae (patch) | |
| tree | 4dc529f514a1625fa6180fc91cf482e93419a205 | |
| parent | dee25c497c017c2b88d618ec1ce034f86af5c452 (diff) | |
Compile typed package requests from build plans
| -rw-r--r-- | src/plan.rs | 22 | ||||
| -rw-r--r-- | tests/compare.rs | 20 | ||||
| -rw-r--r-- | tests/package_installer.rs | 18 |
3 files changed, 60 insertions, 0 deletions
diff --git a/src/plan.rs b/src/plan.rs index 3d28d96..f3e58fa 100644 --- a/src/plan.rs +++ b/src/plan.rs @@ -1,5 +1,8 @@ +use std::path::Path; + use anyhow::Result; +use crate::package_installer::{AptConfig, PackageRequest}; use crate::{ImageSpec, Stage}; #[derive(Debug, Clone, PartialEq, Eq)] @@ -24,4 +27,23 @@ impl BuildPlan { pub fn dependencies(&self, stage: Stage) -> &'static [Stage] { stage.dependencies() } + + /// Compile package-installation inputs from the validated immutable spec. + /// This keeps ALT's external resolver behind the typed adapter boundary. + pub fn package_request( + &self, + workdir: impl AsRef<Path>, + apt_config: impl AsRef<Path>, + ) -> Result<PackageRequest> { + PackageRequest::new( + workdir, + AptConfig::new(apt_config)?, + self.spec.packages.base.iter().cloned(), + self.spec + .packages + .selectors + .iter() + .map(|selector| selector.as_str().to_owned()), + ) + } } diff --git a/tests/compare.rs b/tests/compare.rs index 6dd7317..eb6d388 100644 --- a/tests/compare.rs +++ b/tests/compare.rs @@ -217,6 +217,26 @@ fn normalizes_legacy_dot_prefixed_archive_paths_before_comparison() { } #[test] +fn normalizes_dot_prefixed_paths_from_a_legacy_tree_archive() { + let fixture = tempdir().expect("temporary directory"); + let rootfs = fixture.path().join("rootfs"); + fs::create_dir_all(rootfs.join("etc")).expect("create rootfs directory"); + fs::write(rootfs.join("etc/controller.conf"), "controller\n").expect("write rootfs file"); + let artifact = fixture.path().join("legacy.tar"); + let mut archive = tar::Builder::new(fs::File::create(&artifact).expect("create legacy archive")); + archive.append_dir_all(".", &rootfs).expect("write legacy tree archive"); + archive.finish().expect("finish legacy archive"); + + let manifest = ArtifactManifest::collect_archive(&artifact).expect("collect legacy archive facts"); + + assert!(manifest.files.iter().all(|record| !record.path.starts_with("./"))); + assert!(manifest + .archive_members + .iter() + .all(|record| !record.path.starts_with("./"))); +} + +#[test] fn excludes_legacy_internal_host_and_fakedata_archive_members() { let fixture = tempdir().expect("temporary directory"); let rootfs = fixture.path().join("rootfs"); diff --git a/tests/package_installer.rs b/tests/package_installer.rs index 622d378..b322aa9 100644 --- a/tests/package_installer.rs +++ b/tests/package_installer.rs @@ -1,6 +1,7 @@ use std::path::PathBuf; use alt_controller_image::hasher::{CommandRunner, HasherInstaller, Invocation}; +use alt_controller_image::{BuildPlan, ImageSpec}; use alt_controller_image::package_installer::{AptConfig, PackageInstaller, PackageRequest}; #[derive(Default)] @@ -70,3 +71,20 @@ fn package_request_rejects_empty_packages_and_unsafe_apt_config_paths() { ) .is_err()); } + +#[test] +fn build_plan_compiles_its_typed_package_request() { + let spec = ImageSpec::load(std::path::Path::new("profiles/alt-controller.toml")) + .expect("load controller spec"); + let plan = BuildPlan::compile(spec).expect("compile controller plan"); + + let request = plan + .package_request("work/alt-controller", "profiles/apt.conf") + .expect("compile package request"); + + assert_eq!(request.workdir(), std::path::Path::new("work/alt-controller")); + assert_eq!(request.apt_config().as_path(), std::path::Path::new("profiles/apt.conf")); + assert_eq!(request.packages()[0], "apt"); + assert!(request.packages().contains(&"libiec61850".to_owned())); + assert_eq!(request.selectors(), ["^kernel-(image|modules-())-(rt)$"]); +} |