Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
278 changes: 147 additions & 131 deletions Cargo.lock

Large diffs are not rendered by default.

18 changes: 18 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,24 @@ zstd = { version = "0.13.3", default-features = false }
reqwest-middleware = { git = "https://github.com/astral-sh/reqwest-middleware", rev = "7650ed76215a962a96d94a79be71c27bffde7ab2" }
reqwest-retry = { git = "https://github.com/astral-sh/reqwest-middleware", rev = "7650ed76215a962a96d94a79be71c27bffde7ab2" }
version-ranges = { git = "https://github.com/astral-sh/pubgrub", rev = "d8efd77673c9a90792da9da31b6c0da7ea8a324b" }
#
# pixi-rattler-patches - START
file_url = { git = "https://github.com/baszalmstra/rattler", branch = "rattler-lock/v7" }
rattler = { git = "https://github.com/baszalmstra/rattler", branch = "rattler-lock/v7" }
rattler_cache = { git = "https://github.com/baszalmstra/rattler", branch = "rattler-lock/v7" }
rattler_conda_types = { git = "https://github.com/baszalmstra/rattler", branch = "rattler-lock/v7" }
rattler_digest = { git = "https://github.com/baszalmstra/rattler", branch = "rattler-lock/v7" }
rattler_lock = { git = "https://github.com/baszalmstra/rattler", branch = "rattler-lock/v7" }
rattler_menuinst = { git = "https://github.com/baszalmstra/rattler", branch = "rattler-lock/v7" }
rattler_networking = { git = "https://github.com/baszalmstra/rattler", branch = "rattler-lock/v7" }
rattler_package_streaming = { git = "https://github.com/baszalmstra/rattler", branch = "rattler-lock/v7" }
rattler_repodata_gateway = { git = "https://github.com/baszalmstra/rattler", branch = "rattler-lock/v7" }
rattler_shell = { git = "https://github.com/baszalmstra/rattler", branch = "rattler-lock/v7" }
rattler_solve = { git = "https://github.com/baszalmstra/rattler", branch = "rattler-lock/v7" }
rattler_virtual_packages = { git = "https://github.com/baszalmstra/rattler", branch = "rattler-lock/v7" }
simple_spawn_blocking = { git = "https://github.com/baszalmstra/rattler", branch = "rattler-lock/v7" }
# pixi-rattler-patches - END
#

[profile.ci]
codegen-units = 16
Expand Down
2 changes: 1 addition & 1 deletion crates/pixi/tests/integration_rust/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ impl LockFileExt for LockFile {
.into_iter()
.flatten()
.filter_map(LockedPackageRef::as_conda)
.any(|package| package.record().name.as_normalized() == name)
.any(|package| package.name().as_normalized() == name)
}
fn contains_pypi_package(&self, environment: &str, platform: Platform, name: &str) -> bool {
let Some(env) = self.environment(environment) else {
Expand Down
10 changes: 4 additions & 6 deletions crates/pixi/tests/integration_rust/solve_group_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ async fn test_purl_are_added_for_pypi() {
.packages(Platform::current())
.unwrap()
.for_each(|dep| {
if dep.as_conda().unwrap().record().name == PackageName::from_str("boltons").unwrap() {
assert!(dep.as_conda().unwrap().record().purls.is_none());
if dep.as_conda().unwrap().name() == &PackageName::from_str("boltons").unwrap() {
assert!(dep.as_conda().unwrap().purls().is_none());
}
});

Expand All @@ -138,13 +138,11 @@ async fn test_purl_are_added_for_pypi() {
.packages(Platform::current())
.unwrap()
.for_each(|dep| {
if dep.as_conda().unwrap().record().name == PackageName::from_str("boltons").unwrap() {
if dep.as_conda().unwrap().name() == &PackageName::from_str("boltons").unwrap() {
assert_eq!(
dep.as_conda()
.unwrap()
.record()
.purls
.as_ref()
.purls()
.unwrap()
.first()
.unwrap()
Expand Down
2 changes: 2 additions & 0 deletions crates/pixi_build_types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod channel_configuration;
mod conda_package_metadata;
pub mod procedures;
mod project_model;
mod variant;

use std::{fmt::Display, sync::LazyLock};

Expand All @@ -20,6 +21,7 @@ use rattler_conda_types::{
version_spec::{LogicalOperator, RangeOperator},
};
use serde::{Deserialize, Serialize};
pub use variant::VariantValue;

// Version 0: Initial version (removed)
// Version 1: Added conda/outputs and conda/build_v1
Expand Down
4 changes: 3 additions & 1 deletion crates/pixi_build_types/src/procedures/conda_build_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ use rattler_conda_types::{
use serde::{Deserialize, Serialize};
use serde_with::{DefaultOnError, DisplayFromStr, serde_as};

use crate::variant::VariantValue;

pub const METHOD_NAME: &str = "conda/build_v1";

/// Parameters for the `conda/build_v1` request.
Expand Down Expand Up @@ -174,7 +176,7 @@ pub struct CondaBuildV1Output {
pub subdir: Platform,

/// The variant configuration for the package.
pub variant: BTreeMap<String, String>,
pub variant: BTreeMap<String, VariantValue>,
}

/// Contains the result of the `conda/build_v1` request.
Expand Down
2 changes: 1 addition & 1 deletion crates/pixi_build_types/src/procedures/conda_outputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ pub struct CondaOutputMetadata {
pub python_site_packages_path: Option<String>,

/// The variants that were used for this output.
pub variant: BTreeMap<String, String>,
pub variant: BTreeMap<String, crate::VariantValue>,
}

/// Describes dependencies, constraints and source dependencies for a particular
Expand Down
52 changes: 52 additions & 0 deletions crates/pixi_build_types/src/variant.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use std::cmp::Ordering;
use std::fmt::Display;

use serde::{Deserialize, Serialize};

/// Represents a conda-build variant value.
///
/// Variants are used in conda-build to specify different build configurations.
/// They can be strings (e.g., "3.11" for python version), integers (e.g., 1 for feature flags),
/// or booleans (e.g., true/false for optional features).
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(untagged)]
pub enum VariantValue {
/// String variant value (most common, e.g., python version "3.11")
String(String),
/// Integer variant value (e.g., for numeric feature flags)
Int(i64),
/// Boolean variant value (e.g., for on/off features)
Bool(bool),
}

impl PartialOrd for VariantValue {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}

impl Ord for VariantValue {
fn cmp(&self, other: &Self) -> Ordering {
#[allow(clippy::match_same_arms)]
match (self, other) {
(VariantValue::String(a), VariantValue::String(b)) => a.cmp(b),
(VariantValue::Int(a), VariantValue::Int(b)) => a.cmp(b),
(VariantValue::Bool(a), VariantValue::Bool(b)) => a.cmp(b),
// Define ordering between different types for deterministic sorting
(VariantValue::String(_), _) => Ordering::Less,
(_, VariantValue::String(_)) => Ordering::Greater,
(VariantValue::Int(_), VariantValue::Bool(_)) => Ordering::Less,
(VariantValue::Bool(_), VariantValue::Int(_)) => Ordering::Greater,
}
}
}

impl Display for VariantValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
VariantValue::String(s) => write!(f, "{s}"),
VariantValue::Int(i) => write!(f, "{i}"),
VariantValue::Bool(b) => write!(f, "{b}"),
}
}
}
11 changes: 6 additions & 5 deletions crates/pixi_cli/src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ pub async fn execute(args: Args) -> miette::Result<()> {

// Determine the variant configuration for the build.
let VariantConfig {
variants,
variants: variant_config,
variant_files,
} = workspace.variants(args.target_platform)?;

Expand Down Expand Up @@ -149,7 +149,7 @@ pub async fn execute(args: Args) -> miette::Result<()> {
channels: channels.clone(),
channel_config: channel_config.clone(),
build_environment: build_environment.clone(),
variants: Some(variants.clone()),
variants: Some(variant_config.clone()),
variant_files: Some(variant_files.clone()),
enabled_protocols: Default::default(),
pin_override: None,
Expand Down Expand Up @@ -177,18 +177,19 @@ pub async fn execute(args: Args) -> miette::Result<()> {
.context("failed to create temporary output directory for build artifacts")?;

// Build the individual packages
for package in packages {
for (package_name, package_variant) in packages {
let built_package = command_dispatcher
.source_build(SourceBuildSpec {
package,
package_name,
package_variant,
// Build into a temporary directory first
output_directory: Some(temp_output_dir.path().to_path_buf()),
manifest_source: manifest_source.clone(),
build_source: None,
channels: channels.clone(),
channel_config: channel_config.clone(),
build_environment: build_environment.clone(),
variants: Some(variants.clone()),
variant_config: Some(variant_config.clone()),
variant_files: Some(variant_files.clone()),
enabled_protocols: Default::default(),
work_directory: None,
Expand Down
14 changes: 8 additions & 6 deletions crates/pixi_cli/src/global/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,14 @@ pub async fn execute(args: Args) -> miette::Result<()> {
.to_string();
let package = Package {
name: name.clone(),
version: record
.repodata_record
.package_record
.version
.version()
.to_string(),
version: Some(
record
.repodata_record
.package_record
.version
.version()
.to_string(),
),
dependencies: record
.repodata_record
.package_record
Expand Down
38 changes: 20 additions & 18 deletions crates/pixi_cli/src/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ impl FancyDisplay for KindPackage {
#[derive(Serialize)]
struct PackageToOutput {
name: String,
version: String,
version: Option<String>,
build: Option<String>,
size_bytes: Option<u64>,
kind: KindPackage,
Expand Down Expand Up @@ -163,16 +163,16 @@ impl PackageExt {
/// Returns the name of the package.
pub fn name(&self) -> Cow<'_, str> {
match self {
Self::Conda(value) => value.record().name.as_normalized().into(),
Self::Conda(value) => value.name().as_normalized().into(),
Self::PyPI(value, _) => value.name.as_dist_info_name(),
}
}

/// Returns the version string of the package
pub fn version(&self) -> Cow<'_, str> {
pub fn version(&self) -> Option<Cow<'_, str>> {
match self {
Self::Conda(value) => value.record().version.as_str(),
Self::PyPI(value, _) => value.version.to_string().into(),
Self::Conda(value) => Some(value.version()?.as_str()),
Self::PyPI(value, _) => Some(value.version.to_string().into()),
}
}
}
Expand Down Expand Up @@ -216,10 +216,12 @@ pub async fn execute(args: Args) -> miette::Result<()> {
.into_diagnostic()?;

// Get the python record from the lock file
let mut conda_records = locked_deps_ext.iter().filter_map(|d| d.as_conda());
let conda_records = locked_deps_ext.iter().filter_map(|d| d.as_conda());

// Construct the registry index if we have a python record
let python_record = conda_records.find(|r| is_python_record(r));
let python_record = conda_records
.filter_map(CondaPackageData::as_binary)
.find(|r| is_python_record(&r.package_record));
let tags;
let uv_context;
let index_locations;
Expand All @@ -237,7 +239,7 @@ pub async fn execute(args: Args) -> miette::Result<()> {
tags = get_pypi_tags(
platform,
&environment.system_requirements(),
python_record.record(),
&python_record.package_record,
)?;
Some(RegistryWheelIndex::new(
&uv_context.cache,
Expand Down Expand Up @@ -376,7 +378,7 @@ fn print_packages_as_table(packages: &Vec<PackageToOutput>) -> io::Result<()> {
writeln!(
writer,
"\t{}\t{}\t{}\t{}\t{}{}",
&package.version,
package.version.as_deref().unwrap_or(""),
package.build.as_deref().unwrap_or(""),
size_human,
&package.kind.fancy_display(),
Expand Down Expand Up @@ -420,22 +422,22 @@ fn create_package_to_output<'a, 'b>(
registry_index: Option<&'a mut RegistryWheelIndex<'b>>,
) -> miette::Result<PackageToOutput> {
let name = package.name().to_string();
let version = package.version().into_owned();
let version = package.version().map(|v| v.into_owned());
let kind = KindPackage::from(package);

let build = match package {
PackageExt::Conda(pkg) => Some(pkg.record().build.clone()),
PackageExt::Conda(pkg) => pkg.build().map(ToOwned::to_owned),
PackageExt::PyPI(_, _) => None,
};

let (size_bytes, source) = match package {
PackageExt::Conda(pkg) => (
pkg.record().size,
match pkg {
CondaPackageData::Source(source) => Some(source.location.to_string()),
CondaPackageData::Binary(binary) => binary.channel.as_ref().map(|c| c.to_string()),
},
),
PackageExt::Conda(pkg) => match pkg {
CondaPackageData::Source(source) => (None, Some(source.location.to_string())),
CondaPackageData::Binary(binary) => (
binary.package_record.size,
binary.channel.as_ref().map(|c| c.to_string()),
),
},
PackageExt::PyPI(p, name) => {
// Check the hash to avoid non index packages to be handled by the registry
// index as wheels
Expand Down
10 changes: 6 additions & 4 deletions crates/pixi_cli/src/shared/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub enum PackageSource {
#[derive(Debug, Clone)]
pub struct Package {
pub name: String,
pub version: String,
pub version: Option<String>,
pub dependencies: Vec<String>,
pub needed_by: Vec<String>,
pub source: PackageSource,
Expand Down Expand Up @@ -214,7 +214,7 @@ fn print_dependency_node(
&format!("{prefix}{symbol} "),
&Package {
name: dep_name.to_owned(),
version: String::from(""),
version: None,
dependencies: Vec::new(),
needed_by: Vec::new(),
source: PackageSource::Conda,
Expand Down Expand Up @@ -256,8 +256,10 @@ pub fn print_package(
console::style(&package.name)
},
match package.source {
PackageSource::Conda => console::style(&package.version).fg(Color::Yellow),
PackageSource::Pypi => console::style(&package.version).fg(Color::Blue),
PackageSource::Conda =>
console::style(package.version.as_deref().unwrap_or_default()).fg(Color::Yellow),
PackageSource::Pypi =>
console::style(package.version.as_deref().unwrap_or_default()).fg(Color::Blue),
},
if visited { "(*)" } else { "" }
)
Expand Down
9 changes: 4 additions & 5 deletions crates/pixi_cli/src/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,10 @@ pub(crate) fn extract_package_info(
package: rattler_lock::LockedPackageRef<'_>,
) -> Option<PackageInfo> {
if let Some(conda_package) = package.as_conda() {
let name = conda_package.record().name.as_normalized().to_string();
let name = conda_package.name().as_normalized().to_string();

let dependencies: Vec<String> = conda_package
.record()
.depends
.depends()
.iter()
.map(|d| {
d.split_once(' ')
Expand Down Expand Up @@ -179,9 +178,9 @@ pub fn generate_dependency_map(locked_deps: &[LockedPackageRef<'_>]) -> HashMap<
name: package_info.name,
version: match package {
LockedPackageRef::Conda(conda_data) => {
conda_data.record().version.to_string()
conda_data.version().map(|v| v.to_string())
}
LockedPackageRef::Pypi(pypi_data, _) => pypi_data.version.to_string(),
LockedPackageRef::Pypi(pypi_data, _) => Some(pypi_data.version.to_string()),
},
dependencies: package_info
.dependencies
Expand Down
1 change: 0 additions & 1 deletion crates/pixi_command_dispatcher/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ pin-project-lite = { workspace = true }
rand = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
serde_with = { workspace = true }
slotmap = { workspace = true }
strsim = { workspace = true }
thiserror = { workspace = true }
Expand Down
Loading
Loading