Skip to content
Merged
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
4 changes: 2 additions & 2 deletions crates/rattler_conda_types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ pub use repo_data::{
compute_package_url,
patches::{PackageRecordPatch, PatchInstructions, RepoDataPatch},
sharded::{Shard, ShardedRepodata, ShardedSubdirInfo},
ChannelInfo, ConvertSubdirError, PackageRecord, RecordFromPath, RepoData, SubdirRunExportsJson,
UrlOrPath, ValidatePackageRecordsError, WhlPackageRecord,
ChannelInfo, ConvertSubdirError, ExperimentalV3Packages, PackageRecord, RecordFromPath,
RepoData, SubdirRunExportsJson, UrlOrPath, ValidatePackageRecordsError, WhlPackageRecord,
};
pub use repo_data_record::{RepoDataRecord, SolverResult};
pub use run_export::RunExportKind;
Expand Down
9 changes: 9 additions & 0 deletions crates/rattler_conda_types/src/package/archive_identifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,15 @@ pub struct DistArchiveIdentifier {
}

impl DistArchiveIdentifier {
/// Constructs a new [`DistArchiveIdentifier`] from an
/// [`ArchiveIdentifier`] and an archive type.
pub fn new(identifier: ArchiveIdentifier, archive_type: impl Into<DistArchiveType>) -> Self {
Self {
identifier,
archive_type: archive_type.into(),
}
}

/// Returns a new version but with a different archive type.
pub fn with_archive_type(&self, archive_type: DistArchiveType) -> Self {
Self {
Expand Down
159 changes: 132 additions & 27 deletions crates/rattler_conda_types/src/repo_data/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ use url::Url;

use crate::{
build_spec::BuildNumber,
package::{DistArchiveIdentifier, IndexJson, RunExportsJson},
package::{
ArchiveIdentifier, CondaArchiveType, DistArchiveIdentifier, IndexJson, RunExportsJson,
WheelArchiveType,
},
utils::{
serde::{
sort_index_map_alphabetically, sort_map_alphabetically, DeserializeFromStrUnchecked,
Expand Down Expand Up @@ -57,14 +60,15 @@ pub struct RepoData {
)]
pub conda_packages: IndexMap<DistArchiveIdentifier, PackageRecord, ahash::RandomState>,

/// The wheel packages contained in the repodata.json file
/// Packages stored under the `v3` top-level key.
/// Uses extension-less `ArchiveIdentifier` keys with sub-maps for each
/// archive type.
#[serde(
default,
rename = "packages.whl",
serialize_with = "sort_index_map_alphabetically"
rename = "v3",
skip_serializing_if = "ExperimentalV3Packages::is_empty"
)]
pub experimental_whl_packages:
IndexMap<DistArchiveIdentifier, WhlPackageRecord, ahash::RandomState>,
pub experimental_v3: ExperimentalV3Packages,

/// removed packages (files are still accessible, but they are not
/// installable like regular packages)
Expand All @@ -91,6 +95,45 @@ pub struct ChannelInfo {
pub base_url: Option<String>,
}

/// Packages stored under the `v3` top-level key.
///
/// Records in this set of packages can have conditional dependencies, extras
/// and can be whls.
#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone, Default)]
pub struct ExperimentalV3Packages {
/// The tar.bz2 package records
#[serde(
default,
rename = "tar.bz2",
serialize_with = "sort_map_alphabetically",
skip_serializing_if = "ahash::HashMap::is_empty"
)]
pub tar_bz2: ahash::HashMap<ArchiveIdentifier, PackageRecord>,

/// The conda package records
#[serde(
default,
serialize_with = "sort_map_alphabetically",
skip_serializing_if = "ahash::HashMap::is_empty"
)]
pub conda: ahash::HashMap<ArchiveIdentifier, PackageRecord>,

/// The whl package records
#[serde(
default,
serialize_with = "sort_map_alphabetically",
skip_serializing_if = "ahash::HashMap::is_empty"
)]
pub whl: ahash::HashMap<ArchiveIdentifier, WhlPackageRecord>,
}

impl ExperimentalV3Packages {
/// Returns true if all sub-maps are empty.
pub fn is_empty(&self) -> bool {
self.tar_bz2.is_empty() && self.conda.is_empty() && self.whl.is_empty()
}
}

/// Trait to allow for generic deserialization of records from a path.
pub trait RecordFromPath {
/// Deserialize a record from a path.
Expand Down Expand Up @@ -364,41 +407,61 @@ impl RepoData {
pub fn into_repo_data_records(self, channel: &Channel) -> Vec<RepoDataRecord> {
let mut records = Vec::with_capacity(self.packages.len() + self.conda_packages.len());
let base_url = self.base_url().map(ToOwned::to_owned);
let channel_str = channel.base_url.as_str().to_string();

let subdir_url = |subdir: &str| {
channel
.base_url
.url()
.join(subdir)
.expect("cannot join channel base_url and subdir")
};

// Conda packages: packages, packages.conda, v3.tar.bz2, v3.conda
let v3_tar_bz2 = self.experimental_v3.tar_bz2.into_iter().map(|(id, rec)| {
(
DistArchiveIdentifier::new(id, CondaArchiveType::TarBz2),
rec,
)
});
let v3_conda = self
.experimental_v3
.conda
.into_iter()
.map(|(id, rec)| (DistArchiveIdentifier::new(id, CondaArchiveType::Conda), rec));

// Determine the base_url of the channel
for (identifier, package_record) in self.packages.into_iter().chain(self.conda_packages) {
for (identifier, package_record) in self
.packages
.into_iter()
.chain(self.conda_packages)
.chain(v3_tar_bz2)
.chain(v3_conda)
{
records.push(RepoDataRecord {
url: compute_package_url(
&channel
.base_url
.url()
.join(&package_record.subdir)
.expect("cannot join channel base_url and subdir"),
&subdir_url(&package_record.subdir),
base_url.as_deref(),
&identifier.to_file_name(),
),
channel: Some(channel.base_url.as_str().to_string()),
channel: Some(channel_str.clone()),
package_record,
identifier,
});
}

// Determine the base_url of the channel
// Whl packages: v3.whl
for (
identifier,
id,
WhlPackageRecord {
url,
package_record,
},
) in self.experimental_whl_packages
) in self.experimental_v3.whl
{
let dist_id = DistArchiveIdentifier::new(id, WheelArchiveType::Whl);
let url = match url {
UrlOrPath::Path(path) => compute_package_url(
&channel
.base_url
.url()
.join(&package_record.subdir)
.expect("cannot join channel base_url and subdir"),
&subdir_url(&package_record.subdir),
base_url.as_deref(),
&path,
),
Expand All @@ -407,9 +470,9 @@ impl RepoData {

records.push(RepoDataRecord {
url,
channel: Some(channel.base_url.as_str().to_string()),
channel: Some(channel_str.clone()),
package_record,
identifier,
identifier: dist_id,
});
}

Expand Down Expand Up @@ -572,6 +635,42 @@ pub struct SubdirRunExportsJson {
serialize_with = "sort_map_alphabetically"
)]
conda_packages: ahash::HashMap<DistArchiveIdentifier, PackageRunExports>,

/// Run exports for v3 packages.
#[serde(
default,
rename = "v3",
skip_serializing_if = "ExperimentalV3RunExports::is_empty"
)]
experimental_v3: ExperimentalV3RunExports,
}

/// Run exports for packages stored under the `v3` top-level key.
#[derive(Debug, Default, Deserialize, Serialize, Eq, PartialEq, Clone)]
struct ExperimentalV3RunExports {
/// Run exports for v3 tar.bz2 packages
#[serde(
default,
rename = "tar.bz2",
serialize_with = "sort_map_alphabetically",
skip_serializing_if = "ahash::HashMap::is_empty"
)]
tar_bz2: ahash::HashMap<ArchiveIdentifier, PackageRunExports>,

/// Run exports for v3 conda packages
#[serde(
default,
serialize_with = "sort_map_alphabetically",
skip_serializing_if = "ahash::HashMap::is_empty"
)]
conda: ahash::HashMap<ArchiveIdentifier, PackageRunExports>,
}

impl ExperimentalV3RunExports {
/// Returns true if all sub-maps are empty.
pub fn is_empty(&self) -> bool {
self.tar_bz2.is_empty() && self.conda.is_empty()
}
}

impl SubdirRunExportsJson {
Expand All @@ -581,6 +680,12 @@ impl SubdirRunExportsJson {
self.packages
.get(file_name)
.or_else(|| self.conda_packages.get(file_name))
.or_else(|| {
self.experimental_v3
.tar_bz2
.get(&file_name.identifier)
.or_else(|| self.experimental_v3.conda.get(&file_name.identifier))
})
.map(|pre| &pre.run_exports)
}

Expand Down Expand Up @@ -725,7 +830,7 @@ mod test {
use crate::{
package::DistArchiveIdentifier,
repo_data::{compute_package_url, determine_subdir},
Channel, ChannelConfig, PackageRecord, RepoData,
Channel, ChannelConfig, ExperimentalV3Packages, PackageRecord, RepoData,
};

// isl-0.12.2-1.tar.bz2
Expand All @@ -747,7 +852,7 @@ mod test {
info: None,
packages: IndexMap::default(),
conda_packages: IndexMap::default(),
experimental_whl_packages: IndexMap::default(),
experimental_v3: ExperimentalV3Packages::default(),
removed: [
"xyz-1-py.conda",
"foo-1-py.conda",
Expand Down Expand Up @@ -1004,7 +1109,7 @@ mod test {
info: None,
packages,
conda_packages,
experimental_whl_packages: IndexMap::default(),
experimental_v3: ExperimentalV3Packages::default(),
removed: ahash::HashSet::default(),
};

Expand Down
Loading
Loading