@@ -4,10 +4,8 @@ use crate::{Channel, EnvironmentPackageData, LockFile, PypiPackageData};
4
4
use itertools:: Itertools ;
5
5
use rattler_conda_types:: Platform ;
6
6
use serde:: { Serialize , Serializer } ;
7
- use std:: {
8
- cmp:: Ordering ,
9
- collections:: { BTreeMap , HashSet } ,
10
- } ;
7
+ use std:: collections:: { BTreeSet , HashSet } ;
8
+ use std:: { cmp:: Ordering , collections:: BTreeMap } ;
11
9
use url:: Url ;
12
10
13
11
#[ derive( Serialize ) ]
@@ -31,16 +29,16 @@ enum SerializablePackageData<'a> {
31
29
Pypi ( & ' a PypiPackageData ) ,
32
30
}
33
31
34
- #[ derive( Serialize ) ]
32
+ #[ derive( Serialize , Eq , PartialEq ) ]
35
33
#[ serde( untagged, rename_all = "snake_case" ) ]
36
34
enum SerializablePackageSelector < ' a > {
37
35
Conda {
38
36
conda : & ' a Url ,
39
37
} ,
40
38
Pypi {
41
39
pypi : & ' a Url ,
42
- #[ serde( skip_serializing_if = "HashSet ::is_empty" ) ]
43
- extras : & ' a HashSet < String > ,
40
+ #[ serde( skip_serializing_if = "BTreeSet ::is_empty" ) ]
41
+ extras : & ' a BTreeSet < String > ,
44
42
} ,
45
43
}
46
44
@@ -53,6 +51,60 @@ impl<'a> SerializablePackageSelector<'a> {
53
51
}
54
52
}
55
53
54
+ impl < ' a > PartialOrd for SerializablePackageSelector < ' a > {
55
+ fn partial_cmp ( & self , other : & Self ) -> Option < Ordering > {
56
+ Some ( self . cmp ( other) )
57
+ }
58
+ }
59
+
60
+ impl < ' a > Ord for SerializablePackageSelector < ' a > {
61
+ fn cmp ( & self , other : & Self ) -> Ordering {
62
+ match ( self , other) {
63
+ (
64
+ SerializablePackageSelector :: Conda { .. } ,
65
+ SerializablePackageSelector :: Pypi { .. } ,
66
+ ) => {
67
+ // Sort conda packages before pypi packages
68
+ Ordering :: Less
69
+ }
70
+ (
71
+ SerializablePackageSelector :: Pypi { .. } ,
72
+ SerializablePackageSelector :: Conda { .. } ,
73
+ ) => {
74
+ // Sort Pypi packages after conda packages
75
+ Ordering :: Greater
76
+ }
77
+ (
78
+ SerializablePackageSelector :: Conda { conda : a } ,
79
+ SerializablePackageSelector :: Conda { conda : b } ,
80
+ )
81
+ | (
82
+ SerializablePackageSelector :: Pypi { pypi : a, .. } ,
83
+ SerializablePackageSelector :: Pypi { pypi : b, .. } ,
84
+ ) => {
85
+ // First sort packages just by their filename. Since most of the time the urls end
86
+ // in the packages filename this causes the urls to be sorted by package name.
87
+ if let ( Some ( a) , Some ( b) ) = (
88
+ a. path_segments ( )
89
+ . and_then ( Iterator :: last)
90
+ . map ( str:: to_lowercase) ,
91
+ b. path_segments ( )
92
+ . and_then ( Iterator :: last)
93
+ . map ( str:: to_lowercase) ,
94
+ ) {
95
+ match a. cmp ( & b) {
96
+ Ordering :: Equal => { }
97
+ ordering => return ordering,
98
+ }
99
+ }
100
+
101
+ // Otherwise just sort by their full URL
102
+ a. cmp ( b)
103
+ }
104
+ }
105
+ }
106
+ }
107
+
56
108
impl < ' a > SerializablePackageData < ' a > {
57
109
fn name ( & self ) -> & str {
58
110
match self {
@@ -149,10 +201,7 @@ impl Serialize for LockFile {
149
201
}
150
202
}
151
203
} )
152
- . sorted_by_key ( |p| match p {
153
- SerializablePackageSelector :: Conda { conda } => * conda,
154
- SerializablePackageSelector :: Pypi { pypi, .. } => * pypi,
155
- } )
204
+ . sorted ( )
156
205
. collect ( ) ,
157
206
)
158
207
} )
0 commit comments