diff --git a/crates/rattler_conda_types/src/repo_data/mod.rs b/crates/rattler_conda_types/src/repo_data/mod.rs index 2e6d783057..1dca7a1eae 100644 --- a/crates/rattler_conda_types/src/repo_data/mod.rs +++ b/crates/rattler_conda_types/src/repo_data/mod.rs @@ -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, }; @@ -37,13 +40,17 @@ pub struct RepoData { pub info: Option, /// The tar.bz2 packages contained in the repodata.json file - #[serde(default)] + #[serde(default, serialize_with = "sort_index_map_alphabetically")] pub packages: IndexMap, /// 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, /// removed packages (files are still accessible, but they are not @@ -421,10 +428,14 @@ struct PackageRunExports { pub struct SubdirRunExportsJson { info: Option, - #[serde(default)] + #[serde(default, serialize_with = "sort_map_alphabetically")] packages: ahash::HashMap, - #[serde(default, rename = "packages.conda")] + #[serde( + default, + rename = "packages.conda", + serialize_with = "sort_map_alphabetically" + )] conda_packages: ahash::HashMap, } @@ -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" + ); + } + } } diff --git a/crates/rattler_conda_types/src/repo_data/snapshots/rattler_conda_types__repo_data__test__deserialize_no_noarch_empty_str.snap b/crates/rattler_conda_types/src/repo_data/snapshots/rattler_conda_types__repo_data__test__deserialize_no_noarch_empty_str.snap index 3f206e0953..0fe684c918 100644 --- a/crates/rattler_conda_types/src/repo_data/snapshots/rattler_conda_types__repo_data__test__deserialize_no_noarch_empty_str.snap +++ b/crates/rattler_conda_types/src/repo_data/snapshots/rattler_conda_types__repo_data__test__deserialize_no_noarch_empty_str.snap @@ -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 @@ -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 diff --git a/crates/rattler_conda_types/src/repo_data/snapshots/rattler_conda_types__repo_data__test__deserialize_no_packages_conda.snap b/crates/rattler_conda_types/src/repo_data/snapshots/rattler_conda_types__repo_data__test__deserialize_no_packages_conda.snap index ef54f72983..7ad5d15346 100644 --- a/crates/rattler_conda_types/src/repo_data/snapshots/rattler_conda_types__repo_data__test__deserialize_no_packages_conda.snap +++ b/crates/rattler_conda_types/src/repo_data/snapshots/rattler_conda_types__repo_data__test__deserialize_no_packages_conda.snap @@ -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 @@ -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 diff --git a/crates/rattler_conda_types/src/repo_data/snapshots/rattler_conda_types__repo_data__test__serialize_packages-2.snap b/crates/rattler_conda_types/src/repo_data/snapshots/rattler_conda_types__repo_data__test__serialize_packages-2.snap index 276d6bd108..40b48e5a34 100644 --- a/crates/rattler_conda_types/src/repo_data/snapshots/rattler_conda_types__repo_data__test__serialize_packages-2.snap +++ b/crates/rattler_conda_types/src/repo_data/snapshots/rattler_conda_types__repo_data__test__serialize_packages-2.snap @@ -8,96 +8,6 @@ expression: json "base_url": "../linux-64" }, "packages": { - "cuda-version-12.5-hd4f0392_3.conda": { - "build": "hd4f0392_3", - "build_number": 3, - "constrains": [ - "__cuda >=12.1" - ], - "depends": [], - "license": "LicenseRef-NVIDIA-End-User-License-Agreement", - "license_family": "LicenseRef-NVIDIA-End-User-License-Agreement", - "md5": "6ae1a563a4aa61e55e8ae8260f0d021b", - "name": "cuda-version", - "sha256": "e45a5d14909296abd0784a073da9ee5c420fa58671fbc999f8a9ec898cf3486b", - "size": 21151, - "subdir": "noarch", - "timestamp": 1716314536803, - "version": "12.5" - }, - "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": 1715610974000, - "version": "3.0.2" - }, - "foo-3.0.2-py36h1af98f8_2.conda": { - "build": "py36h1af98f8_2", - "build_number": 2, - "depends": [], - "license": "MIT", - "license_family": "MIT", - "md5": "fb731d9290f0bcbf3a054665f33ec94f", - "name": "foo", - "sha256": "67a63bec3fd3205170eaad532d487595b8aaceb9814d13c6858d7bac3ef24cd4", - "size": 414494, - "subdir": "linux-64", - "timestamp": 1715610974000, - "version": "3.0.2" - }, - "foo-3.0.2-py36h1af98f8_3.conda": { - "build": "py36h1af98f8_3", - "build_number": 3, - "constrains": [ - "bors <2.0" - ], - "depends": [], - "license": "MIT", - "license_family": "MIT", - "md5": "fb731d9290f0bcbf3a054665f33ec94f", - "name": "foo", - "sha256": "67a63bec3fd3205170eaad532d487595b8aaceb9814d13c6858d7bac3ef24cd4", - "size": 414494, - "subdir": "linux-64", - "timestamp": 1715610974000, - "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": 1715610974000, - "version": "4.0.2" - }, "bar-1.0-unix_py36h1af98f8_2.tar.bz2": { "build": "unix_py36h1af98f8_2", "build_number": 1, @@ -214,6 +124,96 @@ expression: json "timestamp": 1715610974000, "version": "2.1" }, + "cuda-version-12.5-hd4f0392_3.conda": { + "build": "hd4f0392_3", + "build_number": 3, + "constrains": [ + "__cuda >=12.1" + ], + "depends": [], + "license": "LicenseRef-NVIDIA-End-User-License-Agreement", + "license_family": "LicenseRef-NVIDIA-End-User-License-Agreement", + "md5": "6ae1a563a4aa61e55e8ae8260f0d021b", + "name": "cuda-version", + "sha256": "e45a5d14909296abd0784a073da9ee5c420fa58671fbc999f8a9ec898cf3486b", + "size": 21151, + "subdir": "noarch", + "timestamp": 1716314536803, + "version": "12.5" + }, + "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": 1715610974000, + "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-3.0.2-py36h1af98f8_2.conda": { + "build": "py36h1af98f8_2", + "build_number": 2, + "depends": [], + "license": "MIT", + "license_family": "MIT", + "md5": "fb731d9290f0bcbf3a054665f33ec94f", + "name": "foo", + "sha256": "67a63bec3fd3205170eaad532d487595b8aaceb9814d13c6858d7bac3ef24cd4", + "size": 414494, + "subdir": "linux-64", + "timestamp": 1715610974000, + "version": "3.0.2" + }, + "foo-3.0.2-py36h1af98f8_3.conda": { + "build": "py36h1af98f8_3", + "build_number": 3, + "constrains": [ + "bors <2.0" + ], + "depends": [], + "license": "MIT", + "license_family": "MIT", + "md5": "fb731d9290f0bcbf3a054665f33ec94f", + "name": "foo", + "sha256": "67a63bec3fd3205170eaad532d487595b8aaceb9814d13c6858d7bac3ef24cd4", + "size": 414494, + "subdir": "linux-64", + "timestamp": 1715610974000, + "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": 1715610974000, + "version": "4.0.2" + }, "foobar-2.0-bla_1.tar.bz2": { "build": "bla_1", "build_number": 1, @@ -263,51 +263,52 @@ expression: json "timestamp": 1715610974000, "version": "2.1" }, - "xfoo-1-xxx.tar.bz2": { + "track-features-1-xxx.tar.bz2": { "build": "xxx", "build_number": 0, "depends": [], "license": "MIT", "license_family": "MIT", "md5": "bc13aa58e2092bcb0b97c561373d3905", - "name": "xfoo", + "name": "track-features", "sha256": "97ec377d2ad83dfef1194b7aa31b0c9076194e10d995a6e696c9d07dd782b14a", "size": 414494, "subdir": "linux-64", "timestamp": 1715610974000, + "track_features": "foo", "version": "1" }, - "xfoo-2-xxx.tar.bz2": { + "track-features-2-xxx.tar.bz2": { "build": "xxx", "build_number": 0, "depends": [], "license": "MIT", "license_family": "MIT", "md5": "bc13aa58e2092bcb0b97c561373d3905", - "name": "xfoo", + "name": "track-features", "sha256": "97ec377d2ad83dfef1194b7aa31b0c9076194e10d995a6e696c9d07dd782b14a", "size": 414494, "subdir": "linux-64", "timestamp": 1715610974000, + "track_features": "foo bar", "version": "2" }, - "xbar-1-xxx.tar.bz2": { + "track-features-3-xxx.tar.bz2": { "build": "xxx", "build_number": 0, - "depends": [ - "xfoo >=2" - ], + "depends": [], "license": "MIT", "license_family": "MIT", "md5": "bc13aa58e2092bcb0b97c561373d3905", - "name": "xbar", + "name": "track-features", "sha256": "97ec377d2ad83dfef1194b7aa31b0c9076194e10d995a6e696c9d07dd782b14a", "size": 414494, "subdir": "linux-64", "timestamp": 1715610974000, - "version": "1" + "track_features": "foo bar", + "version": "3" }, - "track-features-1-xxx.tar.bz2": { + "track-features-4-xxx.tar.bz2": { "build": "xxx", "build_number": 0, "depends": [], @@ -319,73 +320,70 @@ expression: json "size": 414494, "subdir": "linux-64", "timestamp": 1715610974000, - "track_features": "foo", - "version": "1" + "track_features": "foo bar", + "version": "4" }, - "track-features-2-xxx.tar.bz2": { + "xbar-1-xxx.tar.bz2": { "build": "xxx", "build_number": 0, - "depends": [], + "depends": [ + "xfoo >=2" + ], "license": "MIT", "license_family": "MIT", "md5": "bc13aa58e2092bcb0b97c561373d3905", - "name": "track-features", + "name": "xbar", "sha256": "97ec377d2ad83dfef1194b7aa31b0c9076194e10d995a6e696c9d07dd782b14a", "size": 414494, "subdir": "linux-64", "timestamp": 1715610974000, - "track_features": "foo bar", - "version": "2" + "version": "1" }, - "track-features-3-xxx.tar.bz2": { + "xfoo-1-xxx.tar.bz2": { "build": "xxx", "build_number": 0, "depends": [], "license": "MIT", "license_family": "MIT", "md5": "bc13aa58e2092bcb0b97c561373d3905", - "name": "track-features", + "name": "xfoo", "sha256": "97ec377d2ad83dfef1194b7aa31b0c9076194e10d995a6e696c9d07dd782b14a", "size": 414494, "subdir": "linux-64", "timestamp": 1715610974000, - "track_features": "foo bar", - "version": "3" + "version": "1" }, - "track-features-4-xxx.tar.bz2": { + "xfoo-2-xxx.tar.bz2": { "build": "xxx", "build_number": 0, "depends": [], "license": "MIT", "license_family": "MIT", "md5": "bc13aa58e2092bcb0b97c561373d3905", - "name": "track-features", + "name": "xfoo", "sha256": "97ec377d2ad83dfef1194b7aa31b0c9076194e10d995a6e696c9d07dd782b14a", "size": 414494, "subdir": "linux-64", "timestamp": 1715610974000, - "track_features": "foo bar", - "version": "4" + "version": "2" } }, "packages.conda": { - "foobar-2.0-bla_1.conda": { + "bors-1.1-bla_1.conda": { "build": "bla_1", "build_number": 1, - "depends": [ - "bors <2.0" - ], + "depends": [], "license": "MIT", "license_family": "MIT", "md5": "bc13aa58e2092bcb0b97c561373d3905", - "name": "foobar", + "name": "bors", "sha256": "97ec377d2ad83dfef1194b7aa31b0c9076194e10d995a6e696c9d07dd782b14a", "size": 414494, "subdir": "linux-64", "timestamp": 1605110689658, - "version": "2.0" + "version": "1.1" }, - "bors-1.1-bla_1.conda": { + "bors-2.1-bla_1.conda": { "build": "bla_1", "build_number": 1, "depends": [], @@ -396,22 +394,36 @@ expression: json "sha256": "97ec377d2ad83dfef1194b7aa31b0c9076194e10d995a6e696c9d07dd782b14a", "size": 414494, "subdir": "linux-64", - "timestamp": 1605110689658, - "version": "1.1" + "timestamp": 1715610974000, + "version": "2.1" }, - "bors-2.1-bla_1.conda": { + "conda-only-0.1.0-foobar_0.conda": { + "build": "foobar", + "build_number": 0, + "depends": [], + "md5": "bc13aa58e2092bcb0b97c561373d3905", + "name": "conda-only", + "sha256": "97ec377d2ad83dfef1194b7aa31b0c9076194e10d995a6e696c9d07dd782b14a", + "size": 414494, + "subdir": "linux-64", + "timestamp": 1715610974000, + "version": "0.1.0" + }, + "foobar-2.0-bla_1.conda": { "build": "bla_1", "build_number": 1, - "depends": [], + "depends": [ + "bors <2.0" + ], "license": "MIT", "license_family": "MIT", "md5": "bc13aa58e2092bcb0b97c561373d3905", - "name": "bors", + "name": "foobar", "sha256": "97ec377d2ad83dfef1194b7aa31b0c9076194e10d995a6e696c9d07dd782b14a", "size": 414494, "subdir": "linux-64", - "timestamp": 1715610974000, - "version": "2.1" + "timestamp": 1605110689658, + "version": "2.0" }, "issue_717-2.1-bla_1.conda": { "build": "issue_717", @@ -429,18 +441,6 @@ expression: json "subdir": "linux-64", "timestamp": 1715610974000, "version": "2.1" - }, - "conda-only-0.1.0-foobar_0.conda": { - "build": "foobar", - "build_number": 0, - "depends": [], - "md5": "bc13aa58e2092bcb0b97c561373d3905", - "name": "conda-only", - "sha256": "97ec377d2ad83dfef1194b7aa31b0c9076194e10d995a6e696c9d07dd782b14a", - "size": 414494, - "subdir": "linux-64", - "timestamp": 1715610974000, - "version": "0.1.0" } }, "repodata_version": 2 diff --git a/crates/rattler_conda_types/src/repo_data/snapshots/rattler_conda_types__repo_data__test__serialize_packages.snap b/crates/rattler_conda_types/src/repo_data/snapshots/rattler_conda_types__repo_data__test__serialize_packages.snap index 5d9de7471d..6080eaf871 100644 --- a/crates/rattler_conda_types/src/repo_data/snapshots/rattler_conda_types__repo_data__test__serialize_packages.snap +++ b/crates/rattler_conda_types/src/repo_data/snapshots/rattler_conda_types__repo_data__test__serialize_packages.snap @@ -6,88 +6,6 @@ info: subdir: linux-64 base_url: "../linux-64" packages: - cuda-version-12.5-hd4f0392_3.conda: - build: hd4f0392_3 - build_number: 3 - constrains: - - __cuda >=12.1 - depends: [] - license: LicenseRef-NVIDIA-End-User-License-Agreement - license_family: LicenseRef-NVIDIA-End-User-License-Agreement - md5: 6ae1a563a4aa61e55e8ae8260f0d021b - name: cuda-version - sha256: e45a5d14909296abd0784a073da9ee5c420fa58671fbc999f8a9ec898cf3486b - size: 21151 - subdir: noarch - timestamp: 1716314536803 - version: "12.5" - 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: 1715610974000 - version: 3.0.2 - foo-3.0.2-py36h1af98f8_2.conda: - build: py36h1af98f8_2 - build_number: 2 - depends: [] - license: MIT - license_family: MIT - md5: fb731d9290f0bcbf3a054665f33ec94f - name: foo - sha256: 67a63bec3fd3205170eaad532d487595b8aaceb9814d13c6858d7bac3ef24cd4 - size: 414494 - subdir: linux-64 - timestamp: 1715610974000 - version: 3.0.2 - foo-3.0.2-py36h1af98f8_3.conda: - build: py36h1af98f8_3 - build_number: 3 - constrains: - - bors <2.0 - depends: [] - license: MIT - license_family: MIT - md5: fb731d9290f0bcbf3a054665f33ec94f - name: foo - sha256: 67a63bec3fd3205170eaad532d487595b8aaceb9814d13c6858d7bac3ef24cd4 - size: 414494 - subdir: linux-64 - timestamp: 1715610974000 - 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: 1715610974000 - version: 4.0.2 bar-1.0-unix_py36h1af98f8_2.tar.bz2: build: unix_py36h1af98f8_2 build_number: 1 @@ -194,6 +112,88 @@ packages: subdir: linux-64 timestamp: 1715610974000 version: "2.1" + cuda-version-12.5-hd4f0392_3.conda: + build: hd4f0392_3 + build_number: 3 + constrains: + - __cuda >=12.1 + depends: [] + license: LicenseRef-NVIDIA-End-User-License-Agreement + license_family: LicenseRef-NVIDIA-End-User-License-Agreement + md5: 6ae1a563a4aa61e55e8ae8260f0d021b + name: cuda-version + sha256: e45a5d14909296abd0784a073da9ee5c420fa58671fbc999f8a9ec898cf3486b + size: 21151 + subdir: noarch + timestamp: 1716314536803 + version: "12.5" + 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: 1715610974000 + 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-3.0.2-py36h1af98f8_2.conda: + build: py36h1af98f8_2 + build_number: 2 + depends: [] + license: MIT + license_family: MIT + md5: fb731d9290f0bcbf3a054665f33ec94f + name: foo + sha256: 67a63bec3fd3205170eaad532d487595b8aaceb9814d13c6858d7bac3ef24cd4 + size: 414494 + subdir: linux-64 + timestamp: 1715610974000 + version: 3.0.2 + foo-3.0.2-py36h1af98f8_3.conda: + build: py36h1af98f8_3 + build_number: 3 + constrains: + - bors <2.0 + depends: [] + license: MIT + license_family: MIT + md5: fb731d9290f0bcbf3a054665f33ec94f + name: foo + sha256: 67a63bec3fd3205170eaad532d487595b8aaceb9814d13c6858d7bac3ef24cd4 + size: 414494 + subdir: linux-64 + timestamp: 1715610974000 + 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: 1715610974000 + version: 4.0.2 foobar-2.0-bla_1.tar.bz2: build: bla_1 build_number: 1 @@ -237,47 +237,49 @@ packages: subdir: linux-64 timestamp: 1715610974000 version: "2.1" - xfoo-1-xxx.tar.bz2: + track-features-1-xxx.tar.bz2: build: xxx build_number: 0 depends: [] license: MIT license_family: MIT md5: bc13aa58e2092bcb0b97c561373d3905 - name: xfoo + name: track-features sha256: 97ec377d2ad83dfef1194b7aa31b0c9076194e10d995a6e696c9d07dd782b14a size: 414494 subdir: linux-64 timestamp: 1715610974000 + track_features: foo version: "1" - xfoo-2-xxx.tar.bz2: + track-features-2-xxx.tar.bz2: build: xxx build_number: 0 depends: [] license: MIT license_family: MIT md5: bc13aa58e2092bcb0b97c561373d3905 - name: xfoo + name: track-features sha256: 97ec377d2ad83dfef1194b7aa31b0c9076194e10d995a6e696c9d07dd782b14a size: 414494 subdir: linux-64 timestamp: 1715610974000 + track_features: foo bar version: "2" - xbar-1-xxx.tar.bz2: + track-features-3-xxx.tar.bz2: build: xxx build_number: 0 - depends: - - xfoo >=2 + depends: [] license: MIT license_family: MIT md5: bc13aa58e2092bcb0b97c561373d3905 - name: xbar + name: track-features sha256: 97ec377d2ad83dfef1194b7aa31b0c9076194e10d995a6e696c9d07dd782b14a size: 414494 subdir: linux-64 timestamp: 1715610974000 - version: "1" - track-features-1-xxx.tar.bz2: + track_features: foo bar + version: "3" + track-features-4-xxx.tar.bz2: build: xxx build_number: 0 depends: [] @@ -289,66 +291,63 @@ packages: size: 414494 subdir: linux-64 timestamp: 1715610974000 - track_features: foo - version: "1" - track-features-2-xxx.tar.bz2: + track_features: foo bar + version: "4" + xbar-1-xxx.tar.bz2: build: xxx build_number: 0 - depends: [] + depends: + - xfoo >=2 license: MIT license_family: MIT md5: bc13aa58e2092bcb0b97c561373d3905 - name: track-features + name: xbar sha256: 97ec377d2ad83dfef1194b7aa31b0c9076194e10d995a6e696c9d07dd782b14a size: 414494 subdir: linux-64 timestamp: 1715610974000 - track_features: foo bar - version: "2" - track-features-3-xxx.tar.bz2: + version: "1" + xfoo-1-xxx.tar.bz2: build: xxx build_number: 0 depends: [] license: MIT license_family: MIT md5: bc13aa58e2092bcb0b97c561373d3905 - name: track-features + name: xfoo sha256: 97ec377d2ad83dfef1194b7aa31b0c9076194e10d995a6e696c9d07dd782b14a size: 414494 subdir: linux-64 timestamp: 1715610974000 - track_features: foo bar - version: "3" - track-features-4-xxx.tar.bz2: + version: "1" + xfoo-2-xxx.tar.bz2: build: xxx build_number: 0 depends: [] license: MIT license_family: MIT md5: bc13aa58e2092bcb0b97c561373d3905 - name: track-features + name: xfoo sha256: 97ec377d2ad83dfef1194b7aa31b0c9076194e10d995a6e696c9d07dd782b14a size: 414494 subdir: linux-64 timestamp: 1715610974000 - track_features: foo bar - version: "4" + version: "2" packages.conda: - foobar-2.0-bla_1.conda: + bors-1.1-bla_1.conda: build: bla_1 build_number: 1 - depends: - - bors <2.0 + depends: [] license: MIT license_family: MIT md5: bc13aa58e2092bcb0b97c561373d3905 - name: foobar + name: bors sha256: 97ec377d2ad83dfef1194b7aa31b0c9076194e10d995a6e696c9d07dd782b14a size: 414494 subdir: linux-64 timestamp: 1605110689658 - version: "2.0" - bors-1.1-bla_1.conda: + version: "1.1" + bors-2.1-bla_1.conda: build: bla_1 build_number: 1 depends: [] @@ -359,21 +358,33 @@ packages.conda: sha256: 97ec377d2ad83dfef1194b7aa31b0c9076194e10d995a6e696c9d07dd782b14a size: 414494 subdir: linux-64 - timestamp: 1605110689658 - version: "1.1" - bors-2.1-bla_1.conda: + timestamp: 1715610974000 + version: "2.1" + conda-only-0.1.0-foobar_0.conda: + build: foobar + build_number: 0 + depends: [] + md5: bc13aa58e2092bcb0b97c561373d3905 + name: conda-only + sha256: 97ec377d2ad83dfef1194b7aa31b0c9076194e10d995a6e696c9d07dd782b14a + size: 414494 + subdir: linux-64 + timestamp: 1715610974000 + version: 0.1.0 + foobar-2.0-bla_1.conda: build: bla_1 build_number: 1 - depends: [] + depends: + - bors <2.0 license: MIT license_family: MIT md5: bc13aa58e2092bcb0b97c561373d3905 - name: bors + name: foobar sha256: 97ec377d2ad83dfef1194b7aa31b0c9076194e10d995a6e696c9d07dd782b14a size: 414494 subdir: linux-64 - timestamp: 1715610974000 - version: "2.1" + timestamp: 1605110689658 + version: "2.0" issue_717-2.1-bla_1.conda: build: issue_717 build_number: 0 @@ -389,15 +400,4 @@ packages.conda: subdir: linux-64 timestamp: 1715610974000 version: "2.1" - conda-only-0.1.0-foobar_0.conda: - build: foobar - build_number: 0 - depends: [] - md5: bc13aa58e2092bcb0b97c561373d3905 - name: conda-only - sha256: 97ec377d2ad83dfef1194b7aa31b0c9076194e10d995a6e696c9d07dd782b14a - size: 414494 - subdir: linux-64 - timestamp: 1715610974000 - version: 0.1.0 repodata_version: 2 diff --git a/crates/rattler_conda_types/src/utils/serde.rs b/crates/rattler_conda_types/src/utils/serde.rs index df7c9c0c7b..09ad2e3c99 100644 --- a/crates/rattler_conda_types/src/utils/serde.rs +++ b/crates/rattler_conda_types/src/utils/serde.rs @@ -1,7 +1,10 @@ //! Serde utilities for conda types. + +use indexmap::IndexMap; use serde::{de::Error as _, ser::Error, Deserialize, Deserializer, Serialize, Serializer}; use serde_with::{DeserializeAs, SerializeAs}; use std::borrow::Cow; +use std::collections::{BTreeMap, HashMap}; use std::{ marker::PhantomData, path::{Path, PathBuf}, @@ -231,6 +234,28 @@ impl Serialize for TimestampMs { /// string. pub struct DeserializeFromStrUnchecked; +/// A helper function used to sort map alphabetically when serializing. +pub(crate) fn sort_map_alphabetically( + value: &HashMap, + serializer: S, +) -> Result { + value + .iter() + .collect::>() + .serialize(serializer) +} + +/// A helper function used to sort map alphabetically when serializing. +pub(crate) fn sort_index_map_alphabetically( + value: &IndexMap, + serializer: S, +) -> Result { + value + .iter() + .collect::>() + .serialize(serializer) +} + /// A helper to serialize and deserialize `track_features` in repodata. Track /// features are expected to be a space separated list. However, in the past we /// have serialized and deserialized them as a list of strings so for