Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sort paths json deterministically when serializing #147

Merged
merged 5 commits into from
Apr 2, 2023
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
2 changes: 2 additions & 0 deletions crates/rattler_conda_types/src/package/link.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::path::Path;

use rattler_macros::sorted;
use serde::{Deserialize, Serialize};

use super::{EntryPoint, PackageFile};
Expand All @@ -23,6 +24,7 @@ pub enum NoArchLinks {
/// A representation of the `link.json` file found in noarch package archives.
///
/// The `link.json` file contains information about entrypoints that need to be installed for the package.
#[sorted]
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct LinkJson {
/// Links for specific noarch packages
Expand Down
64 changes: 53 additions & 11 deletions crates/rattler_conda_types/src/package/paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use super::PackageFile;
use crate::package::has_prefix::HasPrefixEntry;
use crate::package::{Files, HasPrefix, NoLink, NoSoftlink};
use rattler_digest::serde::SerializableHash;
use serde::{Deserialize, Serialize};
use rattler_macros::sorted;
use serde::{Deserialize, Serialize, Serializer};
use serde_with::serde_as;
use std::collections::{HashMap, HashSet};
use std::io::ErrorKind;
Expand All @@ -11,13 +12,25 @@ use std::path::{Path, PathBuf};
/// A representation of the `paths.json` file found in package archives.
///
/// The `paths.json` file contains information about every file included with the package.
#[sorted]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct PathsJson {
/// All entries included in the package.
#[serde(serialize_with = "serialize_sorted_paths")]
pub paths: Vec<PathsEntry>,

/// The version of the file
pub paths_version: u64,
}

/// All entries included in the package.
pub paths: Vec<PathsEntry>,
fn serialize_sorted_paths<S>(paths: &[PathsEntry], serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
// Sort the paths by the relative_path attribute
let mut sorted_paths = paths.to_vec();
sorted_paths.sort_by(|a, b| a.relative_path.cmp(&b.relative_path));
sorted_paths.serialize(serializer)
}

impl PackageFile for PathsJson {
Expand Down Expand Up @@ -174,10 +187,20 @@ pub struct PrefixPlaceholder {
#[serde_as]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct PathsEntry {
// The alphabetical order of the fields is important for the serialization of the struct.
// ['_path', 'no_link', 'path_type', 'prefix_placeholder', 'sha256', 'size_in_bytes']
// rename can't be sorted by the macro yet.
/// The relative path from the root of the package
#[serde(rename = "_path")]
pub relative_path: PathBuf,

/// Whether or not this file should be linked or not when installing the package.
#[serde(
default = "no_link_default",
skip_serializing_if = "is_no_link_default"
)]
pub no_link: bool,

/// Determines how to include the file when installing the package
pub path_type: PathType,

Expand All @@ -186,13 +209,6 @@ pub struct PathsEntry {
#[serde(default, flatten, skip_serializing_if = "Option::is_none")]
pub prefix_placeholder: Option<PrefixPlaceholder>,

/// Whether or not this file should be linked or not when installing the package.
#[serde(
default = "no_link_default",
skip_serializing_if = "is_no_link_default"
)]
pub no_link: bool,

/// A hex representation of the SHA256 hash of the contents of the file.
/// This entry is only present in version 1 of the paths.json file.
#[serde_as(as = "Option<SerializableHash::<rattler_digest::Sha256>>")]
Expand Down Expand Up @@ -241,7 +257,7 @@ fn is_no_link_default(value: &bool) -> bool {
mod test {
use crate::package::PackageFile;

use super::PathsJson;
use super::{PathsEntry, PathsJson};

#[test]
pub fn roundtrip_paths_json() {
Expand Down Expand Up @@ -289,4 +305,30 @@ mod test {
PathsJson::from_deprecated_package_directory(&package_dir).unwrap()
);
}

#[test]
pub fn test_paths_sorted() {
// create some fake data
let mut paths = vec![];
for i in 0..15 {
paths.push(PathsEntry {
relative_path: format!("path_{}", i).into(),
path_type: super::PathType::HardLink,
prefix_placeholder: None,
no_link: false,
sha256: None,
size_in_bytes: Some(0),
});
}

// shuffle the data
use rand::seq::SliceRandom;
let mut rng = rand::thread_rng();
paths.shuffle(&mut rng);

insta::assert_yaml_snapshot!(PathsJson {
paths,
paths_version: 1
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
source: crates/rattler_conda_types/src/package/paths.rs
expression: "PathsJson { paths, paths_version: 1 }"
---
paths:
- _path: path_0
path_type: hardlink
size_in_bytes: 0
- _path: path_1
path_type: hardlink
size_in_bytes: 0
- _path: path_10
path_type: hardlink
size_in_bytes: 0
- _path: path_11
path_type: hardlink
size_in_bytes: 0
- _path: path_12
path_type: hardlink
size_in_bytes: 0
- _path: path_13
path_type: hardlink
size_in_bytes: 0
- _path: path_14
path_type: hardlink
size_in_bytes: 0
- _path: path_2
path_type: hardlink
size_in_bytes: 0
- _path: path_3
path_type: hardlink
size_in_bytes: 0
- _path: path_4
path_type: hardlink
size_in_bytes: 0
- _path: path_5
path_type: hardlink
size_in_bytes: 0
- _path: path_6
path_type: hardlink
size_in_bytes: 0
- _path: path_7
path_type: hardlink
size_in_bytes: 0
- _path: path_8
path_type: hardlink
size_in_bytes: 0
- _path: path_9
path_type: hardlink
size_in_bytes: 0
paths_version: 1

Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
---
source: crates/rattler_conda_types/src/package/paths.rs
assertion_line: 249
expression: "PathsJson::from_deprecated_package_directory(package_dir.path()).unwrap()"
---
paths_version: 1
paths:
- _path: Library/bin/zlib.dll
path_type: hardlink
Expand All @@ -25,4 +23,5 @@ paths:
path_type: hardlink
file_mode: text
prefix_placeholder: "C:/conda/envs/_build"
paths_version: 1

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
source: crates/rattler_conda_types/src/package/paths.rs
expression: "PathsJson::from_deprecated_package_directory(&package_dir).unwrap()"
---
paths_version: 1
paths:
- _path: include/zconf.h
path_type: hardlink
Expand All @@ -20,4 +19,5 @@ paths:
path_type: hardlink
file_mode: text
prefix_placeholder: /opt/anaconda1anaconda2anaconda3
paths_version: 1

Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,7 @@
source: crates/rattler_conda_types/src/package/paths.rs
expression: paths_json
---
paths_version: 1
paths:
- _path: Lib/site-packages/mamba-1.0.0.dist-info/INSTALLER
path_type: hardlink
sha256: d0edee15f91b406f3f99726e44eb990be6e34fd0345b52b910c568e0eef6a2a8
size_in_bytes: 5
- _path: Lib/site-packages/mamba-1.0.0.dist-info/LICENSE
path_type: hardlink
sha256: 41fd98a468e39d319911bd94f4e65d6ad6a7ea66559dd5aa4112f138ff9b629a
size_in_bytes: 1483
- _path: Lib/site-packages/mamba-1.0.0.dist-info/METADATA
path_type: hardlink
sha256: 48d8890aebe423cf5f524a7bb8ac5f76021499653bc5962c66fcb6e39983770c
size_in_bytes: 500
- _path: Lib/site-packages/mamba-1.0.0.dist-info/RECORD
path_type: hardlink
sha256: 6e3d06d645f2dd605fe3409e923b7d6973d25768d911002b97c39a92b65eed55
size_in_bytes: 2600
- _path: Lib/site-packages/mamba-1.0.0.dist-info/REQUESTED
path_type: hardlink
sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
size_in_bytes: 0
- _path: Lib/site-packages/mamba-1.0.0.dist-info/WHEEL
path_type: hardlink
sha256: d34cac92eb22c54a14b79a1bfc2894a7a2ec9cde65ab34c9a68a8e160fc55487
size_in_bytes: 92
- _path: Lib/site-packages/mamba-1.0.0.dist-info/direct_url.json
path_type: hardlink
sha256: 04797d13c447a487a309781fb5084be28d320228c3ed797850d6d65c71b78ece
size_in_bytes: 78
- _path: Lib/site-packages/mamba-1.0.0.dist-info/entry_points.txt
path_type: hardlink
sha256: ee2ddcf64c6755fc11151d0dab39ecf77916cd3b3fa62bd3a229b9fe8c67bf4b
size_in_bytes: 43
- _path: Lib/site-packages/mamba-1.0.0.dist-info/top_level.txt
path_type: hardlink
sha256: 2a9dc054338292439470e7388cd0eb1cec12d9e1021de15909798a2df9918437
size_in_bytes: 6
- _path: Lib/site-packages/mamba/__init__.py
path_type: hardlink
sha256: fa769046d0468ad6e2997ea166d20fe0d2af9a840791692a1ebea6099c96a13e
Expand Down Expand Up @@ -128,6 +91,42 @@ paths:
path_type: hardlink
sha256: 54f2b6d6ae65bc50ff78ab338ee01139f7a1ce9b352aee75304a511d96f28d90
size_in_bytes: 14233
- _path: Lib/site-packages/mamba-1.0.0.dist-info/INSTALLER
path_type: hardlink
sha256: d0edee15f91b406f3f99726e44eb990be6e34fd0345b52b910c568e0eef6a2a8
size_in_bytes: 5
- _path: Lib/site-packages/mamba-1.0.0.dist-info/LICENSE
path_type: hardlink
sha256: 41fd98a468e39d319911bd94f4e65d6ad6a7ea66559dd5aa4112f138ff9b629a
size_in_bytes: 1483
- _path: Lib/site-packages/mamba-1.0.0.dist-info/METADATA
path_type: hardlink
sha256: 48d8890aebe423cf5f524a7bb8ac5f76021499653bc5962c66fcb6e39983770c
size_in_bytes: 500
- _path: Lib/site-packages/mamba-1.0.0.dist-info/RECORD
path_type: hardlink
sha256: 6e3d06d645f2dd605fe3409e923b7d6973d25768d911002b97c39a92b65eed55
size_in_bytes: 2600
- _path: Lib/site-packages/mamba-1.0.0.dist-info/REQUESTED
path_type: hardlink
sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
size_in_bytes: 0
- _path: Lib/site-packages/mamba-1.0.0.dist-info/WHEEL
path_type: hardlink
sha256: d34cac92eb22c54a14b79a1bfc2894a7a2ec9cde65ab34c9a68a8e160fc55487
size_in_bytes: 92
- _path: Lib/site-packages/mamba-1.0.0.dist-info/direct_url.json
path_type: hardlink
sha256: 04797d13c447a487a309781fb5084be28d320228c3ed797850d6d65c71b78ece
size_in_bytes: 78
- _path: Lib/site-packages/mamba-1.0.0.dist-info/entry_points.txt
path_type: hardlink
sha256: ee2ddcf64c6755fc11151d0dab39ecf77916cd3b3fa62bd3a229b9fe8c67bf4b
size_in_bytes: 43
- _path: Lib/site-packages/mamba-1.0.0.dist-info/top_level.txt
path_type: hardlink
sha256: 2a9dc054338292439470e7388cd0eb1cec12d9e1021de15909798a2df9918437
size_in_bytes: 6
- _path: Library/bin/mamba.bat
path_type: hardlink
sha256: c627e57f922b03d7a48453225ba2ab3639c99ee146df27b8f093330137b1bfa7
Expand All @@ -152,4 +151,5 @@ paths:
path_type: hardlink
sha256: 41f0a1b9b398bc090fb5c005bba9c2586132cae14cf948b03c1062d130473a20
size_in_bytes: 628
paths_version: 1