Skip to content

Commit 56728c8

Browse files
committed
Start to implement handling embedded packages
A handful of tests now pass but `todo!`s remain. One test was modified to be less picky about how the build is populated when the solve includes an embedded package. The new solver populates the embedded package parent info instead of leaving it as "Unknown". Signed-off-by: J Robert Ray <[email protected]>
1 parent dc83ae0 commit 56728c8

File tree

2 files changed

+103
-14
lines changed

2 files changed

+103
-14
lines changed

crates/spk-solve/src/cdcl_solver/spk_provider.rs

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// https://github.com/spkenv/spk
44

55
use std::cell::{Cell, RefCell};
6-
use std::collections::{HashMap, HashSet};
6+
use std::collections::{BTreeSet, HashMap, HashSet};
77
use std::sync::Arc;
88

99
use resolvo::utils::Pool;
@@ -22,9 +22,20 @@ use resolvo::{
2222
VersionSetUnionId,
2323
};
2424
use spk_schema::foundation::pkg_name;
25-
use spk_schema::ident::{LocatedBuildIdent, PinnableValue, PkgRequest, Satisfy, VarRequest};
25+
use spk_schema::ident::{
26+
LocatedBuildIdent,
27+
PinnableValue,
28+
PkgRequest,
29+
RangeIdent,
30+
RequestedBy,
31+
Satisfy,
32+
VarRequest,
33+
};
34+
use spk_schema::ident_build::{Build, EmbeddedSource, EmbeddedSourcePackage};
2635
use spk_schema::ident_component::Component;
2736
use spk_schema::name::{OptNameBuf, PkgNameBuf};
37+
use spk_schema::prelude::{HasVersion, Named};
38+
use spk_schema::version_range::{DoubleEqualsVersion, VersionFilter};
2839
use spk_schema::{Opt, Package, Request, VersionIdent};
2940
use spk_storage::RepositoryHandle;
3041

@@ -456,6 +467,19 @@ impl DependencyProvider for SpkProvider {
456467
let located_build_ident =
457468
LocatedBuildIdent::new(repo.name().to_owned(), build.clone());
458469
if let SyntheticComponent::Actual(pkg_name_component) = &pkg_name.component {
470+
if let Build::Embedded(EmbeddedSource::Package(parent)) = build.build() {
471+
// Embedded packages don't have components, but
472+
// their parent has a component.
473+
if parent.components.contains(pkg_name_component) {
474+
located_builds.push(LocatedBuildIdentWithComponent {
475+
ident: located_build_ident,
476+
component: SyntheticComponent::Actual(
477+
pkg_name_component.clone(),
478+
),
479+
});
480+
}
481+
continue;
482+
}
459483
let components =
460484
repo.list_build_components(&build).await.unwrap_or_default();
461485
for component in components.into_iter().chain(
@@ -692,6 +716,67 @@ impl DependencyProvider for SpkProvider {
692716
.extend(self.pkg_requirements(&component_spec.requirements));
693717
}
694718
}
719+
// Also add dependencies on any packages embedded in this
720+
// component.
721+
// XXX: This ignores the detail of embeds inside components for
722+
// now.
723+
for embedded in package.embedded().iter() {
724+
let dep_name = self.pool.intern_package_name(PkgNameBufWithComponent {
725+
name: embedded.name().to_owned(),
726+
component: located_build_ident_with_component.component.clone(),
727+
});
728+
known_deps.requirements.push(
729+
self.pool
730+
.intern_version_set(
731+
dep_name,
732+
RequestVS::SpkRequest(Request::Pkg(PkgRequest::new(
733+
RangeIdent {
734+
repository_name: Some(
735+
located_build_ident_with_component
736+
.ident
737+
.repository_name()
738+
.to_owned(),
739+
),
740+
name: embedded.name().to_owned(),
741+
components: Default::default(),
742+
version: VersionFilter::single(
743+
DoubleEqualsVersion::version_range(
744+
embedded.version().clone(),
745+
),
746+
),
747+
// This needs to match the build of
748+
// the stub for get_candidates to like
749+
// it.
750+
build: Some(Build::Embedded(EmbeddedSource::Package(
751+
Box::new(EmbeddedSourcePackage {
752+
ident: package.ident().into(),
753+
// XXX: Hard coded to Run for
754+
// now.
755+
components: BTreeSet::from_iter([Component::Run]),
756+
}),
757+
))),
758+
},
759+
RequestedBy::Embedded(
760+
located_build_ident_with_component.ident.target().clone(),
761+
),
762+
))),
763+
)
764+
.into(),
765+
);
766+
// Any install requirements of components inside embedded
767+
// packages with the same name as this component also
768+
// become dependencies.
769+
for embedded_component_requirement in embedded
770+
.components()
771+
.iter()
772+
.filter(|embedded_component| {
773+
embedded_component.name == located_build_ident_with_component.component
774+
})
775+
.flat_map(|embedded_component| embedded_component.requirements.iter())
776+
{
777+
todo!("{embedded_component_requirement:?}");
778+
}
779+
}
695780
for option in package.get_build_options() {
696781
let Opt::Var(var_opt) = option else {
697782
continue;

crates/spk-solve/src/solver_test.rs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,16 @@ macro_rules! assert_resolved {
6767
assert_eq!(pkg.spec.ident().build(), &$build, $message);
6868
}};
6969

70+
($solution:ident, $pkg:literal, build =~ $build:pat) => {
71+
assert_resolved!($solution, $pkg, build =~ $build, "wrong package build was resolved")
72+
};
73+
($solution:ident, $pkg:literal, build =~ $build:pat, $message:literal) => {{
74+
let pkg = $solution
75+
.get($pkg)
76+
.expect("expected package to be in solution");
77+
assert!(matches!(pkg.spec.ident().build(), $build), $message);
78+
}};
79+
7080
($solution:ident, $pkg:literal, components = [$($component:literal),+ $(,)?]) => {{
7181
let mut resolved = std::collections::HashSet::<String>::new();
7282
let pkg = $solution
@@ -510,8 +520,6 @@ async fn test_solver_dependency_already_satisfied(#[case] mut solver: SolverImpl
510520

511521
#[rstest]
512522
#[case::og(og_solver())]
513-
// Remove #[should_panic] once cdcl handles this case
514-
#[should_panic]
515523
#[case::cdcl(cdcl_solver())]
516524
#[tokio::test]
517525
async fn test_solver_dependency_already_satisfied_conflicting_components(
@@ -1279,8 +1287,6 @@ async fn test_solver_build_from_source_deprecated_and_impossible_initial_checks(
12791287

12801288
#[rstest]
12811289
#[case::og(og_solver())]
1282-
// Remove #[should_panic] once cdcl handles this case
1283-
#[should_panic]
12841290
#[case::cdcl(cdcl_solver())]
12851291
#[tokio::test]
12861292
async fn test_solver_embedded_package_adds_request(#[case] mut solver: SolverImpl) {
@@ -1301,18 +1307,21 @@ async fn test_solver_embedded_package_adds_request(#[case] mut solver: SolverImp
13011307
solver.add_repository(Arc::new(repo));
13021308
solver.add_request(request!("maya"));
13031309

1304-
let solution = run_and_print_resolve_for_tests(&mut solver).await.unwrap();
1310+
let solution = run_and_print_resolve_for_tests(&mut solver)
1311+
.await
1312+
.tap_err(|e| eprintln!("{e}"))
1313+
.unwrap();
13051314

13061315
assert_resolved!(
13071316
solution,
13081317
"qt",
1309-
build = Build::Embedded(EmbeddedSource::Unknown)
1318+
build =~ Build::Embedded(_)
13101319
);
13111320
assert_resolved!(solution, "qt", "5.12.6");
13121321
assert_resolved!(
13131322
solution,
13141323
"qt",
1315-
build = Build::Embedded(EmbeddedSource::Unknown)
1324+
build =~ Build::Embedded(_)
13161325
);
13171326
}
13181327

@@ -1358,8 +1367,6 @@ async fn test_solver_embedded_package_solvable(#[case] mut solver: SolverImpl) {
13581367

13591368
#[rstest]
13601369
#[case::og(og_solver())]
1361-
// Remove #[should_panic] once cdcl handles this case
1362-
#[should_panic]
13631370
#[case::cdcl(cdcl_solver())]
13641371
#[tokio::test]
13651372
async fn test_solver_embedded_package_unsolvable(#[case] mut solver: SolverImpl) {
@@ -1739,7 +1746,6 @@ async fn test_solver_some_versions_conflicting_requests(#[case] mut solver: Solv
17391746

17401747
#[rstest]
17411748
#[case::og(og_solver())]
1742-
#[should_panic]
17431749
#[case::cdcl(cdcl_solver())]
17441750
#[tokio::test]
17451751
async fn test_solver_embedded_request_invalidates(#[case] mut solver: SolverImpl) {
@@ -2629,8 +2635,6 @@ async fn test_solver_component_embedded_multiple_versions(
26292635

26302636
#[rstest]
26312637
#[case::og(og_solver())]
2632-
// Remove #[should_panic] once cdcl handles this case
2633-
#[should_panic]
26342638
#[case::cdcl(cdcl_solver())]
26352639
#[tokio::test]
26362640
async fn test_solver_component_embedded_incompatible_requests(#[case] mut solver: SolverImpl) {

0 commit comments

Comments
 (0)