@@ -8,7 +8,6 @@ use diesel_async::{AsyncPgConnection, RunQueryDsl};
88use futures_util:: { future, TryStreamExt } ;
99use http:: request:: Parts ;
1010use indexmap:: { IndexMap , IndexSet } ;
11- use std:: cmp:: Reverse ;
1211use std:: str:: FromStr ;
1312
1413use crate :: app:: AppState ;
@@ -51,6 +50,7 @@ pub async fn list_versions(state: AppState, path: CratePath, req: Parts) -> AppR
5150 . map ( |mode| ShowIncludeMode :: from_str ( mode) )
5251 . transpose ( ) ?
5352 . unwrap_or_default ( ) ;
53+ let include_release_tracks = include. release_tracks ;
5454
5555 // Sort by semver by default
5656 let versions_and_publishers = match params. get ( "sort" ) . map ( |s| s. to_lowercase ( ) ) . as_deref ( ) {
@@ -75,6 +75,12 @@ pub async fn list_versions(state: AppState, path: CratePath, req: Parts) -> AppR
7575
7676 Ok ( match pagination {
7777 Some ( _) => json ! ( { "versions" : versions, "meta" : versions_and_publishers. meta } ) ,
78+ None if include_release_tracks => {
79+ json ! ( {
80+ "versions" : versions,
81+ "meta" : ReleaseTracksMeta { release_tracks: versions_and_publishers. meta. release_tracks }
82+ } )
83+ }
7884 None => json ! ( { "versions" : versions } ) ,
7985 } )
8086}
@@ -99,7 +105,6 @@ async fn list_by_date(
99105 . select ( <( Version , Option < User > ) >:: as_select ( ) )
100106 . into_boxed ( ) ;
101107
102- let mut release_tracks = None ;
103108 if let Some ( options) = options {
104109 assert ! (
105110 !matches!( & options. page, Page :: Numeric ( _) ) ,
@@ -114,9 +119,20 @@ async fn list_by_date(
114119 )
115120 }
116121 query = query. limit ( options. per_page ) ;
122+ }
123+
124+ query = query. order ( ( versions:: created_at. desc ( ) , versions:: id. desc ( ) ) ) ;
117125
118- if include. release_tracks {
119- let mut sorted_versions = IndexSet :: new ( ) ;
126+ let data: Vec < ( Version , Option < User > ) > = query. load ( conn) . await ?;
127+ let mut next_page = None ;
128+ if let Some ( options) = options {
129+ next_page = next_seek_params ( & data, options, |last| Seek :: Date . to_payload ( last) ) ?
130+ . map ( |p| req. query_with_params ( p) ) ;
131+ } ;
132+
133+ let release_tracks = if include. release_tracks {
134+ let mut sorted_versions = IndexSet :: new ( ) ;
135+ if options. is_some ( ) {
120136 versions:: table
121137 . filter ( versions:: crate_id. eq ( crate_id) )
122138 . filter ( not ( versions:: yanked) )
@@ -130,21 +146,23 @@ async fn list_by_date(
130146 future:: ready ( Ok ( ( ) ) )
131147 } )
132148 . await ?;
133-
134- sorted_versions. sort_unstable_by ( |a, b| b. cmp ( a) ) ;
135- release_tracks = Some ( ReleaseTracks :: from_sorted_semver_iter (
136- sorted_versions. iter ( ) ,
137- ) ) ;
149+ } else {
150+ sorted_versions = data
151+ . iter ( )
152+ . flat_map ( |( version, _) | {
153+ ( !version. yanked )
154+ . then_some ( version)
155+ . and_then ( |v| semver:: Version :: parse ( & v. num ) . ok ( ) )
156+ } )
157+ . collect ( ) ;
138158 }
139- }
140-
141- query = query. order ( ( versions:: created_at. desc ( ) , versions:: id. desc ( ) ) ) ;
142159
143- let data: Vec < ( Version , Option < User > ) > = query. load ( conn) . await ?;
144- let mut next_page = None ;
145- if let Some ( options) = options {
146- next_page = next_seek_params ( & data, options, |last| Seek :: Date . to_payload ( last) ) ?
147- . map ( |p| req. query_with_params ( p) ) ;
160+ sorted_versions. sort_unstable_by ( |a, b| b. cmp ( a) ) ;
161+ Some ( ReleaseTracks :: from_sorted_semver_iter (
162+ sorted_versions. iter ( ) ,
163+ ) )
164+ } else {
165+ None
148166 } ;
149167
150168 // Since the total count is retrieved through an additional query, to maintain consistency
@@ -269,15 +287,29 @@ async fn list_by_semver(
269287 ( vec ! [ ] , 0 , release_tracks)
270288 }
271289 } else {
272- let mut data: Vec < ( Version , Option < User > ) > = versions:: table
290+ let mut data = IndexMap :: new ( ) ;
291+ versions:: table
273292 . filter ( versions:: crate_id. eq ( crate_id) )
274293 . left_outer_join ( users:: table)
275294 . select ( <( Version , Option < User > ) >:: as_select ( ) )
276- . load ( conn)
295+ . load_stream :: < ( Version , Option < User > ) > ( conn)
296+ . await ?
297+ . try_for_each ( |row| {
298+ if let Ok ( semver) = semver:: Version :: parse ( & row. 0 . num ) {
299+ data. insert ( semver, row) ;
300+ } ;
301+ future:: ready ( Ok ( ( ) ) )
302+ } )
277303 . await ?;
278- data. sort_by_cached_key ( | ( version , _) | Reverse ( semver :: Version :: parse ( & version . num ) . ok ( ) ) ) ;
304+ data. sort_unstable_by ( |a , _, b , _| b . cmp ( a ) ) ;
279305 let total = data. len ( ) ;
280- ( data, total, None )
306+ let release_tracks = include. release_tracks . then ( || {
307+ ReleaseTracks :: from_sorted_semver_iter (
308+ data. iter ( )
309+ . flat_map ( |( semver, ( version, _) ) | ( !version. yanked ) . then_some ( semver) ) ,
310+ )
311+ } ) ;
312+ ( data. into_values ( ) . collect ( ) , total, release_tracks)
281313 } ;
282314
283315 let mut next_page = None ;
@@ -365,6 +397,12 @@ struct ResponseMeta {
365397 release_tracks : Option < ReleaseTracks > ,
366398}
367399
400+ #[ derive( Serialize ) ]
401+ struct ReleaseTracksMeta {
402+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
403+ release_tracks : Option < ReleaseTracks > ,
404+ }
405+
368406#[ derive( Debug , Eq , PartialEq , Serialize ) ]
369407struct ReleaseTracks ( IndexMap < ReleaseTrackName , ReleaseTrackDetails > ) ;
370408
0 commit comments