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
126 changes: 121 additions & 5 deletions crates/rattler_conda_types/src/repo_data/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ use url::Url;
use crate::{
build_spec::BuildNumber,
package::{IndexJson, RunExportsJson},
utils::{serde::DeserializeFromStrUnchecked, UrlWithTrailingSlash},
utils::{
serde::sort_index_map_alphabetically, serde::sort_map_alphabetically,
serde::DeserializeFromStrUnchecked, UrlWithTrailingSlash,
},
Arch, Channel, MatchSpec, Matches, NoArchType, PackageName, PackageUrl, ParseMatchSpecError,
ParseStrictness, Platform, RepoDataRecord, VersionWithSource,
};
Expand All @@ -37,13 +40,17 @@ pub struct RepoData {
pub info: Option<ChannelInfo>,

/// The tar.bz2 packages contained in the repodata.json file
#[serde(default)]
#[serde(default, serialize_with = "sort_index_map_alphabetically")]
pub packages: IndexMap<String, PackageRecord, ahash::RandomState>,

/// The conda packages contained in the repodata.json file (under a
/// different key for backwards compatibility with previous conda
/// versions)
#[serde(default, rename = "packages.conda")]
#[serde(
default,
rename = "packages.conda",
serialize_with = "sort_index_map_alphabetically"
)]
pub conda_packages: IndexMap<String, PackageRecord, ahash::RandomState>,

/// removed packages (files are still accessible, but they are not
Expand Down Expand Up @@ -421,10 +428,14 @@ struct PackageRunExports {
pub struct SubdirRunExportsJson {
info: Option<ChannelInfo>,

#[serde(default)]
#[serde(default, serialize_with = "sort_map_alphabetically")]
packages: ahash::HashMap<String, PackageRunExports>,

#[serde(default, rename = "packages.conda")]
#[serde(
default,
rename = "packages.conda",
serialize_with = "sort_map_alphabetically"
)]
conda_packages: ahash::HashMap<String, PackageRunExports>,
}

Expand Down Expand Up @@ -758,4 +769,109 @@ mod test {
"package 'foo=3.0.2=py36h1af98f8_3' has constraint 'bors <2.0', which is not satisfied by 'bors=2.1=bla_1' in the environment"
));
}

#[test]
fn test_packages_serialized_alphabetically() {
use crate::{PackageName, Version};

// Create a RepoData with packages inserted in NON-alphabetical order
let mut packages = IndexMap::default();
let mut conda_packages = IndexMap::default();

// Insert packages in deliberately non-alphabetical order: z, a, m, b
packages.insert(
"zebra-1.0-h123.tar.bz2".to_string(),
PackageRecord::new(
PackageName::new_unchecked("zebra"),
Version::major(1),
"h123".to_string(),
),
);
packages.insert(
"apple-2.0-h456.tar.bz2".to_string(),
PackageRecord::new(
PackageName::new_unchecked("apple"),
Version::major(2),
"h456".to_string(),
),
);
packages.insert(
"mango-1.5-h789.tar.bz2".to_string(),
PackageRecord::new(
PackageName::new_unchecked("mango"),
Version::major(1),
"h789".to_string(),
),
);
packages.insert(
"banana-3.0-habc.tar.bz2".to_string(),
PackageRecord::new(
PackageName::new_unchecked("banana"),
Version::major(3),
"habc".to_string(),
),
);

// Insert conda packages in non-alphabetical order too
conda_packages.insert(
"xray-1.0-h111.conda".to_string(),
PackageRecord::new(
PackageName::new_unchecked("xray"),
Version::major(1),
"h111".to_string(),
),
);
conda_packages.insert(
"alpha-2.0-h222.conda".to_string(),
PackageRecord::new(
PackageName::new_unchecked("alpha"),
Version::major(2),
"h222".to_string(),
),
);
conda_packages.insert(
"omega-3.0-h333.conda".to_string(),
PackageRecord::new(
PackageName::new_unchecked("omega"),
Version::major(3),
"h333".to_string(),
),
);

let repodata = RepoData {
version: Some(2),
info: None,
packages,
conda_packages,
removed: ahash::HashSet::default(),
};

// Serialize to JSON string
let json = serde_json::to_string(&repodata).unwrap();

// Parse the JSON to extract the package keys
let json_value: serde_json::Value = serde_json::from_str(&json).unwrap();

// Check that packages are in alphabetical order
if let Some(packages) = json_value.get("packages").and_then(|p| p.as_object()) {
let keys: Vec<&String> = packages.keys().collect();
let mut sorted_keys = keys.clone();
sorted_keys.sort();
assert_eq!(
keys, sorted_keys,
"packages should be serialized in alphabetical order"
);
}

// Check that packages.conda are in alphabetical order
if let Some(conda_packages) = json_value.get("packages.conda").and_then(|p| p.as_object()) {
let keys: Vec<&String> = conda_packages.keys().collect();
let mut sorted_keys = keys.clone();
sorted_keys.sort();
assert_eq!(
keys, sorted_keys,
"packages.conda should be serialized in alphabetical order"
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,6 @@ info:
subdir: noarch
base_url: "../linux-64"
packages:
foo-1-xxx.tar.bz2:
build: xxx
build_number: 0
depends: []
extra_depends:
with-bar:
- bar <2
name: foo
subdir: linux-64
version: "1"
bar-1-xxx.tar.bz2:
build: xxx
build_number: 0
Expand All @@ -30,5 +20,15 @@ packages:
name: bar
subdir: linux-64
version: "2"
foo-1-xxx.tar.bz2:
build: xxx
build_number: 0
depends: []
extra_depends:
with-bar:
- bar <2
name: foo
subdir: linux-64
version: "1"
packages.conda: {}
repodata_version: 2
Original file line number Diff line number Diff line change
Expand Up @@ -6,45 +6,6 @@ info:
subdir: linux-64
base_url: "../linux-64"
packages:
foo-3.0.2-py36h1af98f8_1.tar.bz2:
build: py36h1af98f8_1
build_number: 1
depends: []
license: MIT
license_family: MIT
md5: d65ab674acf3b7294ebacaec05fc5b54
name: foo
sha256: 1154fceeb5c4ee9bb97d245713ac21eb1910237c724d2b7103747215663273c2
size: 414494
subdir: linux-64
timestamp: 1605110689658
version: 3.0.2
foo-3.0.2-py36h1af98f8_1.conda:
build: py36h1af98f8_1
build_number: 1
depends: []
license: MIT
license_family: MIT
md5: fb731d9290f0bcbf3a054665f33ec94f
name: foo
sha256: 67a63bec3fd3205170eaad532d487595b8aaceb9814d13c6858d7bac3ef24cd4
size: 414494
subdir: linux-64
timestamp: 1605110689658
version: 3.0.2
foo-4.0.2-py36h1af98f8_2.tar.bz2:
build: py36h1af98f8_2
build_number: 1
depends: []
license: MIT
license_family: MIT
md5: bc13aa58e2092bcb0b97c561373d3905
name: foo
sha256: 97ec377d2ad83dfef1194b7aa31b0c9076194e10d995a6e696c9d07dd782b14a
size: 414494
subdir: linux-64
timestamp: 1605110689658
version: 4.0.2
bar-1.0-unix_py36h1af98f8_2.tar.bz2:
build: unix_py36h1af98f8_2
build_number: 1
Expand Down Expand Up @@ -151,6 +112,45 @@ packages:
subdir: linux-64
timestamp: 1605110689658
version: "2.1"
foo-3.0.2-py36h1af98f8_1.conda:
build: py36h1af98f8_1
build_number: 1
depends: []
license: MIT
license_family: MIT
md5: fb731d9290f0bcbf3a054665f33ec94f
name: foo
sha256: 67a63bec3fd3205170eaad532d487595b8aaceb9814d13c6858d7bac3ef24cd4
size: 414494
subdir: linux-64
timestamp: 1605110689658
version: 3.0.2
foo-3.0.2-py36h1af98f8_1.tar.bz2:
build: py36h1af98f8_1
build_number: 1
depends: []
license: MIT
license_family: MIT
md5: d65ab674acf3b7294ebacaec05fc5b54
name: foo
sha256: 1154fceeb5c4ee9bb97d245713ac21eb1910237c724d2b7103747215663273c2
size: 414494
subdir: linux-64
timestamp: 1605110689658
version: 3.0.2
foo-4.0.2-py36h1af98f8_2.tar.bz2:
build: py36h1af98f8_2
build_number: 1
depends: []
license: MIT
license_family: MIT
md5: bc13aa58e2092bcb0b97c561373d3905
name: foo
sha256: 97ec377d2ad83dfef1194b7aa31b0c9076194e10d995a6e696c9d07dd782b14a
size: 414494
subdir: linux-64
timestamp: 1605110689658
version: 4.0.2
foobar-2.0-bla_1.tar.bz2:
build: bla_1
build_number: 1
Expand Down
Loading