@@ -8,7 +8,7 @@ use diesel::prelude::*;
88/// This struct is used to load all versions of a crate from the database,
99/// without loading all the additional data unnecessary for default version
1010/// resolution.
11- #[ derive( Clone , Debug , Queryable , Selectable ) ]
11+ #[ derive( Clone , Debug , PartialEq , Eq , Queryable , Selectable ) ]
1212#[ diesel( table_name = versions) ]
1313#[ diesel( check_for_backend( diesel:: pg:: Pg ) ) ]
1414struct Version {
@@ -23,6 +23,22 @@ impl Version {
2323 fn is_prerelease ( & self ) -> bool {
2424 !self . num . pre . is_empty ( )
2525 }
26+
27+ fn ord_tuple ( & self ) -> ( bool , bool , & semver:: Version , i32 ) {
28+ ( !self . yanked , !self . is_prerelease ( ) , & self . num , self . id )
29+ }
30+ }
31+
32+ impl PartialOrd for Version {
33+ fn partial_cmp ( & self , other : & Self ) -> Option < std:: cmp:: Ordering > {
34+ Some ( self . cmp ( other) )
35+ }
36+ }
37+
38+ impl Ord for Version {
39+ fn cmp ( & self , other : & Self ) -> std:: cmp:: Ordering {
40+ self . ord_tuple ( ) . cmp ( & other. ord_tuple ( ) )
41+ }
2642}
2743
2844/// Updates the `default_versions` table entry for the specified crate.
@@ -102,20 +118,16 @@ fn calculate_default_version(crate_id: i32, conn: &mut impl Conn) -> QueryResult
102118}
103119
104120fn find_default_version ( versions : & [ Version ] ) -> Option < & Version > {
105- highest ( versions, |v| !v. is_prerelease ( ) && !v. yanked )
106- . or_else ( || highest ( versions, |v| !v. yanked ) )
107- . or_else ( || highest ( versions, |_| true ) )
108- }
109-
110- fn highest ( versions : & [ Version ] , filter : impl FnMut ( & & Version ) -> bool ) -> Option < & Version > {
111- versions. iter ( ) . filter ( filter) . max_by_key ( |v| & v. num )
121+ versions. iter ( ) . max ( )
112122}
113123
114124#[ cfg( test) ]
115125mod tests {
116126 use super :: * ;
117127 use crate :: schema:: crates;
118128 use crate :: test_util:: test_db_connection;
129+ use insta:: assert_snapshot;
130+ use std:: fmt:: Write ;
119131
120132 fn v ( num : & str , yanked : bool ) -> Version {
121133 let num = semver:: Version :: parse ( num) . unwrap ( ) ;
@@ -179,6 +191,51 @@ mod tests {
179191 check ( & versions, "1.0.0-beta.3" ) ;
180192 }
181193
194+ #[ test]
195+ fn test_ord ( ) {
196+ let mut versions = vec ! [
197+ v( "1.0.0" , false ) ,
198+ v( "1.0.0-beta.1" , false ) ,
199+ v( "1.0.0-beta.2" , false ) ,
200+ v( "1.0.0-beta.3" , false ) ,
201+ v( "1.0.1" , true ) ,
202+ v( "1.0.2" , false ) ,
203+ v( "1.1.0" , false ) ,
204+ v( "1.1.1-beta.1" , true ) ,
205+ v( "1.1.1" , true ) ,
206+ v( "1.0.3" , false ) ,
207+ v( "2.0.0-beta.1" , false ) ,
208+ ] ;
209+
210+ versions. sort ( ) ;
211+
212+ assert_snapshot ! ( format_versions( & versions) , @r#"
213+ 1.1.1-beta.1 (yanked)
214+ 1.0.1 (yanked)
215+ 1.1.1 (yanked)
216+ 1.0.0-beta.1
217+ 1.0.0-beta.2
218+ 1.0.0-beta.3
219+ 2.0.0-beta.1
220+ 1.0.0
221+ 1.0.2
222+ 1.0.3
223+ 1.1.0
224+ "# ) ;
225+ }
226+
227+ fn format_versions ( versions : & [ Version ] ) -> String {
228+ let mut buf = String :: with_capacity ( versions. len ( ) * 20 ) ;
229+ for v in versions {
230+ write ! ( buf, "{}" , v. num) . unwrap ( ) ;
231+ if v. yanked {
232+ buf. push_str ( " (yanked)" ) ;
233+ }
234+ buf. push ( '\n' ) ;
235+ }
236+ buf
237+ }
238+
182239 fn create_crate ( name : & str , conn : & mut impl Conn ) -> i32 {
183240 diesel:: insert_into ( crates:: table)
184241 . values ( crates:: name. eq ( name) )
0 commit comments