Skip to content

Commit 40f5ac9

Browse files
committed
Resolvo: fix stubs getting added to solve without parent
The case where a stub only depended on the Run component of the parent still needs to declare a dependency to bring it in. Signed-off-by: J Robert Ray <[email protected]>
1 parent 6384f33 commit 40f5ac9

File tree

1 file changed

+119
-97
lines changed

1 file changed

+119
-97
lines changed

crates/spk-solve/src/solvers/resolvo/spk_provider.rs

Lines changed: 119 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use std::borrow::Cow;
66
use std::cell::RefCell;
77
use std::collections::{BTreeSet, HashMap, HashSet};
88
use std::ops::Not;
9-
use std::str::FromStr;
109
use std::sync::Arc;
1110

1211
use itertools::Itertools;
@@ -38,7 +37,6 @@ use spk_schema::ident_build::{Build, EmbeddedSource, EmbeddedSourcePackage};
3837
use spk_schema::ident_component::Component;
3938
use spk_schema::name::{OptNameBuf, PkgNameBuf};
4039
use spk_schema::prelude::{HasVersion, Named};
41-
use spk_schema::version::Version;
4240
use spk_schema::version_range::{DoubleEqualsVersion, Ranged, VersionFilter, parse_version_range};
4341
use spk_schema::{
4442
BuildIdent,
@@ -1448,106 +1446,130 @@ impl DependencyProvider for SpkProvider {
14481446
if let Build::Embedded(EmbeddedSource::Package(parent)) =
14491447
located_build_ident_with_component.ident.build()
14501448
{
1451-
match actual_component {
1452-
Component::Run => {
1453-
// The Run component is the default "home" of
1454-
// embedded packages, no dependency needed in this
1455-
// case.
1449+
let parent_ident: BuildIdent = match (**parent).clone().try_into() {
1450+
Ok(ident) => ident,
1451+
Err(err) => {
1452+
let msg = self.pool.intern_string(format!(
1453+
"failed to get valid parent ident for '{}': {err}",
1454+
located_build_ident_with_component.ident
1455+
));
1456+
return Dependencies::Unknown(msg);
14561457
}
1457-
component => 'invalid_parent: {
1458-
// XXX: Do we not have a convenient way to read the
1459-
// parent package from an embedded stub ident?
1460-
let Ok(pkg_name) = PkgNameBuf::from_str(&parent.ident.pkg_name) else {
1461-
break 'invalid_parent;
1462-
};
1463-
let Some(version_str) = parent.ident.version_str.as_ref() else {
1464-
break 'invalid_parent;
1465-
};
1466-
let Ok(version) = Version::from_str(version_str) else {
1467-
break 'invalid_parent;
1468-
};
1469-
let Some(build_str) = parent.ident.build_str.as_ref() else {
1470-
break 'invalid_parent;
1471-
};
1472-
let Ok(build) = Build::from_str(build_str) else {
1473-
break 'invalid_parent;
1474-
};
1475-
let ident = BuildIdent::new(
1476-
VersionIdent::new(pkg_name, version),
1477-
build.clone(),
1478-
);
1479-
let Ok(parent) = repo.read_package(&ident).await else {
1480-
break 'invalid_parent;
1481-
};
1482-
// Look through the components of the parent to see
1483-
// if one (or more?) of them embeds this component.
1484-
for parent_component in parent.components().iter() {
1485-
parent_component
1486-
.embedded
1487-
.iter()
1488-
.filter(|embedded_package| {
1489-
embedded_package.pkg.name()
1490-
== located_build_ident_with_component.ident.name()
1491-
&& embedded_package
1492-
.pkg
1493-
.target()
1494-
.as_ref()
1495-
.map(|version| {
1496-
version
1497-
== located_build_ident_with_component
1458+
};
1459+
let parent = match repo.read_package(&parent_ident).await {
1460+
Ok(spec) => spec,
1461+
Err(err) => {
1462+
let msg = self.pool.intern_string(format!(
1463+
"failed to read parent package for '{}': {err}",
1464+
located_build_ident_with_component.ident
1465+
));
1466+
return Dependencies::Unknown(msg);
1467+
}
1468+
};
1469+
// Look through the components of the parent to see
1470+
// if one (or more?) of them embeds this component.
1471+
let mut found = false;
1472+
for parent_component in parent.components().iter() {
1473+
parent_component
1474+
.embedded
1475+
.iter()
1476+
.filter(|embedded_package| {
1477+
embedded_package.pkg.name()
1478+
== located_build_ident_with_component.ident.name()
1479+
&& embedded_package
1480+
.pkg
1481+
.target()
1482+
.as_ref()
1483+
.map(|version| {
1484+
version
1485+
== located_build_ident_with_component
1486+
.ident
1487+
.version()
1488+
})
1489+
.unwrap_or(true)
1490+
&& embedded_package.components().contains(actual_component)
1491+
})
1492+
.for_each(|_embedded_package| {
1493+
found = true;
1494+
let dep_name = self.pool.intern_package_name(
1495+
ResolvoPackageName::PkgNameBufWithComponent(
1496+
PkgNameBufWithComponent {
1497+
name: parent_ident.name().to_owned(),
1498+
component: SyntheticComponent::Actual(
1499+
parent_component.name.clone(),
1500+
),
1501+
},
1502+
),
1503+
);
1504+
known_deps.requirements.push(
1505+
self.pool
1506+
.intern_version_set(
1507+
dep_name,
1508+
RequestVS::SpkRequest(Request::Pkg(PkgRequest::new(
1509+
RangeIdent {
1510+
repository_name: Some(
1511+
located_build_ident_with_component
14981512
.ident
1499-
.version()
1500-
})
1501-
.unwrap_or(true)
1502-
&& embedded_package.components().contains(component)
1503-
})
1504-
.for_each(|_embedded_package| {
1505-
let dep_name = self.pool.intern_package_name(
1506-
ResolvoPackageName::PkgNameBufWithComponent(
1507-
PkgNameBufWithComponent {
1508-
name: ident.name().to_owned(),
1509-
component: SyntheticComponent::Actual(
1510-
parent_component.name.clone(),
1513+
.repository_name()
1514+
.to_owned(),
15111515
),
1512-
},
1513-
),
1514-
);
1515-
known_deps.requirements.push(
1516-
self.pool.intern_version_set(
1517-
dep_name,
1518-
RequestVS::SpkRequest(Request::Pkg(
1519-
PkgRequest::new(
1520-
RangeIdent {
1521-
repository_name: Some(
1522-
located_build_ident_with_component
1523-
.ident
1524-
.repository_name()
1525-
.to_owned(),
1526-
),
1527-
name: ident.name().to_owned(),
1528-
components: BTreeSet::from_iter([
1529-
parent_component.name.clone(),
1530-
]),
1531-
version: VersionFilter::single(
1532-
DoubleEqualsVersion::version_range(
1533-
ident.version().clone(),
1534-
),
1535-
),
1536-
build: Some(build.clone()),
1537-
},
1538-
RequestedBy::Embedded(
1539-
located_build_ident_with_component
1540-
.ident
1541-
.target()
1542-
.clone(),
1516+
name: parent_ident.name().to_owned(),
1517+
components: BTreeSet::from_iter([
1518+
parent_component.name.clone(),
1519+
]),
1520+
version: VersionFilter::single(
1521+
DoubleEqualsVersion::version_range(
1522+
parent_ident.version().clone(),
15431523
),
15441524
),
1545-
))
1546-
).into(),
1547-
);
1548-
});
1549-
}
1550-
}
1525+
build: Some(parent_ident.build().clone()),
1526+
},
1527+
RequestedBy::Embedded(
1528+
located_build_ident_with_component
1529+
.ident
1530+
.target()
1531+
.clone(),
1532+
),
1533+
))),
1534+
)
1535+
.into(),
1536+
);
1537+
});
1538+
}
1539+
if !found {
1540+
// In the event that no owning component was found,
1541+
// this stub must still bring in at least one
1542+
// component from the parent. By convention, bring
1543+
// in the Run component of the parent.
1544+
let dep_name = self.pool.intern_package_name(
1545+
ResolvoPackageName::PkgNameBufWithComponent(PkgNameBufWithComponent {
1546+
name: parent_ident.name().to_owned(),
1547+
component: SyntheticComponent::Actual(Component::Run),
1548+
}),
1549+
);
1550+
let located_parent = LocatedBuildIdentWithComponent {
1551+
ident: parent_ident.clone().to_located(
1552+
located_build_ident_with_component
1553+
.ident
1554+
.repository_name()
1555+
.to_owned(),
1556+
),
1557+
// as_request_with_components does not make use
1558+
// of the component field, assigning Base here
1559+
// does not imply anything.
1560+
component: SyntheticComponent::Base,
1561+
requires_build_from_source: false,
1562+
};
1563+
known_deps.requirements.push(
1564+
self.pool
1565+
.intern_version_set(
1566+
dep_name,
1567+
RequestVS::SpkRequest(
1568+
located_parent.as_request_with_components([Component::Run]),
1569+
),
1570+
)
1571+
.into(),
1572+
);
15511573
}
15521574
}
15531575
for option in package.get_build_options() {

0 commit comments

Comments
 (0)