Skip to content

Commit 9c18379

Browse files
committed
wip: return pixi specs
1 parent 490601a commit 9c18379

File tree

2 files changed

+113
-23
lines changed
  • crates/pixi_command_dispatcher

2 files changed

+113
-23
lines changed

crates/pixi_command_dispatcher/src/output_dependencies/mod.rs

Lines changed: 86 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
1-
use std::collections::BTreeMap;
1+
use std::{collections::BTreeMap, str::FromStr};
22

33
use miette::Diagnostic;
44
use pixi_build_discovery::EnabledProtocols;
55
use pixi_build_types::procedures::conda_outputs::{CondaOutput, CondaOutputDependencies};
66
use pixi_record::PinnedSourceSpec;
7-
use rattler_conda_types::{ChannelConfig, ChannelUrl, PackageName};
7+
use pixi_spec::{BinarySpec, PixiSpec};
8+
use pixi_spec_containers::DependencyMap;
9+
use rattler_conda_types::{ChannelConfig, ChannelUrl, InvalidPackageNameError, PackageName};
810
use thiserror::Error;
911
use tracing::instrument;
1012

1113
use crate::{
1214
BuildBackendMetadataError, BuildBackendMetadataSpec, BuildEnvironment, CommandDispatcher,
1315
CommandDispatcherError, CommandDispatcherErrorResultExt,
14-
build::source_metadata_cache::MetadataKind,
16+
build::{conversion, source_metadata_cache::MetadataKind},
1517
};
1618

1719
/// A specification for retrieving the dependencies of a specific output from a
@@ -48,15 +50,24 @@ pub struct GetOutputDependenciesSpec {
4850
pub struct OutputDependencies {
4951
/// The build dependencies of the package. These refer to the packages that
5052
/// should be installed in the "build" environment.
51-
pub build_dependencies: Option<CondaOutputDependencies>,
53+
pub build_dependencies: Option<DependencyMap<PackageName, PixiSpec>>,
54+
55+
/// Additional constraints for the build environment.
56+
pub build_constraints: Option<DependencyMap<PackageName, BinarySpec>>,
5257

5358
/// The "host" dependencies of the package. These refer to the packages that
5459
/// should be installed to be able to refer to them from the build process
5560
/// but not run them.
56-
pub host_dependencies: Option<CondaOutputDependencies>,
61+
pub host_dependencies: Option<DependencyMap<PackageName, PixiSpec>>,
62+
63+
/// Additional constraints for the host environment.
64+
pub host_constraints: Option<DependencyMap<PackageName, BinarySpec>>,
5765

5866
/// The dependencies for the run environment of the package.
59-
pub run_dependencies: CondaOutputDependencies,
67+
pub run_dependencies: DependencyMap<PackageName, PixiSpec>,
68+
69+
/// Additional constraints for the run environment.
70+
pub run_constraints: DependencyMap<PackageName, BinarySpec>,
6071
}
6172

6273
impl GetOutputDependenciesSpec {
@@ -110,17 +121,76 @@ impl GetOutputDependenciesSpec {
110121
})?;
111122

112123
// Extract and return the dependencies.
113-
Ok(extract_dependencies(output))
124+
extract_dependencies(output).map_err(CommandDispatcherError::Failed)
114125
}
115126
}
116127

117-
/// Extracts the dependencies from a CondaOutput.
118-
fn extract_dependencies(output: &CondaOutput) -> OutputDependencies {
119-
OutputDependencies {
120-
build_dependencies: output.build_dependencies.clone(),
121-
host_dependencies: output.host_dependencies.clone(),
122-
run_dependencies: output.run_dependencies.clone(),
128+
/// Extracts the dependencies from a CondaOutput and converts them to PixiSpecs.
129+
fn extract_dependencies(
130+
output: &CondaOutput,
131+
) -> Result<OutputDependencies, GetOutputDependenciesError> {
132+
let (build_deps, build_constraints) = output
133+
.build_dependencies
134+
.as_ref()
135+
.map(convert_conda_dependencies)
136+
.transpose()?
137+
.map(|(deps, constraints)| (Some(deps), Some(constraints)))
138+
.unwrap_or((None, None));
139+
140+
let (host_deps, host_constraints) = output
141+
.host_dependencies
142+
.as_ref()
143+
.map(convert_conda_dependencies)
144+
.transpose()?
145+
.map(|(deps, constraints)| (Some(deps), Some(constraints)))
146+
.unwrap_or((None, None));
147+
148+
let (run_deps, run_constraints) = convert_conda_dependencies(&output.run_dependencies)?;
149+
150+
Ok(OutputDependencies {
151+
build_dependencies: build_deps,
152+
build_constraints,
153+
host_dependencies: host_deps,
154+
host_constraints,
155+
run_dependencies: run_deps,
156+
run_constraints,
157+
})
158+
}
159+
160+
/// Converts CondaOutputDependencies to DependencyMaps of PixiSpecs and BinarySpecs.
161+
fn convert_conda_dependencies(
162+
deps: &CondaOutputDependencies,
163+
) -> Result<
164+
(
165+
DependencyMap<PackageName, PixiSpec>,
166+
DependencyMap<PackageName, BinarySpec>,
167+
),
168+
GetOutputDependenciesError,
169+
> {
170+
let mut dependencies = DependencyMap::default();
171+
let mut constraints = DependencyMap::default();
172+
173+
// Convert depends
174+
for depend in &deps.depends {
175+
let name = PackageName::from_str(&depend.name).map_err(|err| {
176+
GetOutputDependenciesError::InvalidPackageName(depend.name.clone(), err)
177+
})?;
178+
179+
let spec = conversion::from_package_spec_v1(depend.spec.clone());
180+
dependencies.insert(name, spec);
123181
}
182+
183+
// Convert constraints
184+
for constraint in &deps.constraints {
185+
let name = PackageName::from_str(&constraint.name).map_err(|err| {
186+
GetOutputDependenciesError::InvalidPackageName(constraint.name.clone(), err)
187+
})?;
188+
189+
let spec = conversion::from_binary_spec_v1(constraint.spec.clone());
190+
constraints.insert(name, spec);
191+
}
192+
193+
Ok((dependencies, constraints))
124194
}
125195

126196
#[derive(Debug, Error, Diagnostic)]
@@ -143,4 +213,7 @@ pub enum GetOutputDependenciesError {
143213
output_name: PackageName,
144214
available_outputs: Vec<PackageName>,
145215
},
216+
217+
#[error("backend returned a dependency on an invalid package name: {0}")]
218+
InvalidPackageName(String, #[source] InvalidPackageNameError),
146219
}

crates/pixi_command_dispatcher/tests/integration/main.rs

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -666,13 +666,12 @@ pub async fn test_get_output_dependencies() {
666666

667667
let build_deps = result.build_dependencies.unwrap();
668668
let host_deps = result.host_dependencies.unwrap();
669-
let run_deps = result.run_dependencies;
669+
let run_deps = &result.run_dependencies;
670670

671671
// Verify build dependencies (cmake, make)
672672
let build_dep_names: Vec<_> = build_deps
673-
.depends
674-
.iter()
675-
.map(|dep| dep.name.as_str())
673+
.names()
674+
.map(|name| name.as_normalized())
676675
.sorted()
677676
.collect();
678677
assert_eq!(
@@ -683,9 +682,8 @@ pub async fn test_get_output_dependencies() {
683682

684683
// Verify host dependencies (zlib, openssl)
685684
let host_dep_names: Vec<_> = host_deps
686-
.depends
687-
.iter()
688-
.map(|dep| dep.name.as_str())
685+
.names()
686+
.map(|name| name.as_normalized())
689687
.sorted()
690688
.collect();
691689
assert_eq!(
@@ -696,16 +694,35 @@ pub async fn test_get_output_dependencies() {
696694

697695
// Verify run dependencies (python, numpy)
698696
let run_dep_names: Vec<_> = run_deps
699-
.depends
700-
.iter()
701-
.map(|dep| dep.name.as_str())
697+
.names()
698+
.map(|name| name.as_normalized())
702699
.sorted()
703700
.collect();
704701
assert_eq!(
705702
run_dep_names,
706703
vec!["numpy", "python"],
707704
"Run dependencies should include python and numpy"
708705
);
706+
707+
// Verify constraints are empty (our test package doesn't have any)
708+
assert!(
709+
result
710+
.build_constraints
711+
.as_ref()
712+
.map_or(true, |c| c.is_empty()),
713+
"Build constraints should be empty"
714+
);
715+
assert!(
716+
result
717+
.host_constraints
718+
.as_ref()
719+
.map_or(true, |c| c.is_empty()),
720+
"Host constraints should be empty"
721+
);
722+
assert!(
723+
result.run_constraints.is_empty(),
724+
"Run constraints should be empty"
725+
);
709726
}
710727

711728
/// Tests that `get_output_dependencies` returns an appropriate error when the

0 commit comments

Comments
 (0)