diff --git a/crates/spk-schema/src/v0/indexed_package.rs b/crates/spk-schema/src/v0/indexed_package.rs index b77f61e20..570da411f 100644 --- a/crates/spk-schema/src/v0/indexed_package.rs +++ b/crates/spk-schema/src/v0/indexed_package.rs @@ -30,6 +30,7 @@ use crate::foundation::name::PkgName; use crate::foundation::spec_ops::prelude::*; use crate::foundation::version::{Compat, Compatibility, Version}; use crate::ident::{Satisfy, VarRequest}; +use crate::option::VarOpt; use crate::package::OptionValues; use crate::spec::SpecTest; use crate::v0::EmbeddedPackageSpec; @@ -156,6 +157,47 @@ impl IndexedPackage { ::follow(&self.buf[..], self.offset) } } + + // Helper function for gathering and filtering downstream + // requirements trait implementation. + fn downstream_requirements(&self, filter: F) -> Cow<'_, RequirementsList> + where + F: FnMut(&VarOpt) -> bool, + { + // This is a version of downstream_requirements() from + // v0/package_spec.rs modified for this kind of flatbuffer + // backed package. + let build_options = self.build_options(); + let embedded = self.embedded(); + + let requests = build_options + .iter() + .filter_map(|opt| match opt { + Opt::Var(v) => Some(v.with_default_namespace(self.name())), + Opt::Pkg(_) => None, + }) + .chain(embedded.iter().flat_map(|embed| { + embed.build().options.iter().filter_map(|opt| match opt { + Opt::Var(v) => Some(v.with_default_namespace(embed.name())), + Opt::Pkg(_) => None, + }) + })) + .filter(filter) + .map(|o| { + VarRequest { + // we are assuming that the var here will have a value because + // this is a built binary package + value: o.get_value(None).unwrap_or_default().into(), + var: o.var, + // Index doesn't store the an option's description + description: None, + } + }) + .map(RequestWithOptions::Var); + RequirementsList::::try_from_iter(requests) + .map(Cow::Owned) + .expect("build opts (from a RepoIndex) do not contain duplicates") + } } impl BuildOptions for IndexedPackage { @@ -489,15 +531,9 @@ impl DownstreamRequirements for IndexedPackage { &self, _components: impl IntoIterator, ) -> Cow<'_, RequirementsList> { - // This is for build var requirements and inheritance used in - // building. This kinds of package has no build data stored. - let err = Error::SpkIndexedPackageDoesNotImplement( - "DownstreamRequirements".to_string(), - "downstream_build_requirements".to_string(), - ); - // TODO: should this change the return value, update all the - // caller's handling, and return an error for this implementation? - unreachable!("{err}"); + // This is used when doing a binary build to get additional + // information about the build environment. + self.downstream_requirements(|o| o.inheritance() != Inheritance::Weak) } fn downstream_runtime_requirements<'a>( @@ -506,40 +542,7 @@ impl DownstreamRequirements for IndexedPackage { ) -> Cow<'_, RequirementsList> { // This is used when deprecating an embedded stub/package // and this is exercised during the automated repository tests. - - // This is a version of downstream_runtime_requirements() and - // downstream_requirements() from v0/package_spec.rs modified - // for this kind of flatbuffer backed package. - let build_options = self.build_options(); - let embedded = self.embedded(); - - let requests = build_options - .iter() - .filter_map(|opt| match opt { - Opt::Var(v) => Some(v.with_default_namespace(self.name())), - Opt::Pkg(_) => None, - }) - .chain(embedded.iter().flat_map(|embed| { - embed.build().options.iter().filter_map(|opt| match opt { - Opt::Var(v) => Some(v.with_default_namespace(embed.name())), - Opt::Pkg(_) => None, - }) - })) - .filter(|o| o.inheritance() == Inheritance::Strong || o.required) - .map(|o| { - VarRequest { - // we are assuming that the var here will have a value because - // this is a built binary package - value: o.get_value(None).unwrap_or_default().into(), - var: o.var, - // Index doesn't store the an option's description - description: None, - } - }) - .map(RequestWithOptions::Var); - RequirementsList::::try_from_iter(requests) - .map(Cow::Owned) - .expect("build opts (from a RepoIndex) do not contain duplicates") + self.downstream_requirements(|o| o.inheritance() == Inheritance::Strong || o.required) } } diff --git a/crates/spk-storage/src/storage/flatbuffer_index_test.rs b/crates/spk-storage/src/storage/flatbuffer_index_test.rs index a72869aa0..93ff63955 100644 --- a/crates/spk-storage/src/storage/flatbuffer_index_test.rs +++ b/crates/spk-storage/src/storage/flatbuffer_index_test.rs @@ -22,6 +22,7 @@ use spk_schema::{ ComponentSpec, Components, Deprecate, + DownstreamRequirements, OptionMap, OptionValues, Package, @@ -262,7 +263,17 @@ fn assert_packages_are_equivalent(build_from_repo: Arc, build_from_index: // fn get_all_tests(&self) -> Vec - not implemented by SolverPackageSpec - // DownstreamRequirements - not implemented by SolverPackageSpec + // DownstreamRequirements + assert_eq!( + build_from_repo.downstream_build_requirements([]), + build_from_index.downstream_build_requirements([]), + "downstream_build_requirements() don't match [{pkg}]", + ); + assert_eq!( + build_from_repo.downstream_runtime_requirements([]), + build_from_index.downstream_runtime_requirements([]), + "downstream_runtime_requirements() don't match [{pkg}]", + ); // OptionValues assert_eq!(