@@ -9,7 +9,7 @@ use crate::{
9
9
encode_url_path,
10
10
error:: { AxumNope , AxumResult } ,
11
11
extractors:: { DbConnection , Path } ,
12
- ReqVersion ,
12
+ MatchedRelease , ReqVersion ,
13
13
} ,
14
14
AsyncStorage ,
15
15
} ;
@@ -98,11 +98,27 @@ pub struct Release {
98
98
99
99
impl CrateDetails {
100
100
#[ tracing:: instrument( skip( conn) ) ]
101
- pub async fn new (
101
+ pub ( crate ) async fn from_matched_release (
102
+ conn : & mut sqlx:: PgConnection ,
103
+ release : & MatchedRelease ,
104
+ ) -> Result < Self > {
105
+ Ok ( Self :: new (
106
+ conn,
107
+ & release. name ,
108
+ release. version ( ) ,
109
+ Some ( release. req_version . clone ( ) ) ,
110
+ release. all_releases . clone ( ) ,
111
+ )
112
+ . await ?
113
+ . unwrap ( ) )
114
+ }
115
+
116
+ async fn new (
102
117
conn : & mut sqlx:: PgConnection ,
103
118
name : & str ,
104
119
version : & Version ,
105
120
req_version : Option < ReqVersion > ,
121
+ prefetched_releases : Vec < Release > ,
106
122
) -> Result < Option < CrateDetails > , anyhow:: Error > {
107
123
let krate = match sqlx:: query!(
108
124
r#"SELECT
@@ -163,9 +179,6 @@ impl CrateDetails {
163
179
None => return Ok ( None ) ,
164
180
} ;
165
181
166
- // get releases, sorted by semver
167
- let releases = releases_for_crate ( conn, krate. crate_id ) . await ?;
168
-
169
182
let repository_metadata = krate. repo_host . map ( |_| RepositoryMetadata {
170
183
issues : krate. repo_issues . unwrap ( ) ,
171
184
stars : krate. repo_stars . unwrap ( ) ,
@@ -205,7 +218,7 @@ impl CrateDetails {
205
218
keywords : krate. keywords ,
206
219
have_examples : krate. have_examples ,
207
220
target_name : krate. target_name ,
208
- releases,
221
+ releases : prefetched_releases ,
209
222
repository_metadata,
210
223
metadata,
211
224
is_library : krate. is_library ,
@@ -399,21 +412,17 @@ pub(crate) async fn crate_details_handler(
399
412
)
400
413
} ) ?;
401
414
402
- let version = match_version ( & mut conn, & params. name , & req_version)
415
+ let matched_release = match_version ( & mut conn, & params. name , & req_version)
403
416
. await ?
404
417
. assume_exact_name ( ) ?
405
418
. into_canonical_req_version_or_else ( |version| {
406
419
AxumNope :: Redirect (
407
420
format ! ( "/crate/{}/{}" , & params. name, version) ,
408
421
CachePolicy :: ForeverInCdn ,
409
422
)
410
- } ) ?
411
- . into_version ( ) ;
423
+ } ) ?;
412
424
413
- let mut details =
414
- CrateDetails :: new ( & mut conn, & params. name , & version, Some ( req_version. clone ( ) ) )
415
- . await ?
416
- . ok_or ( AxumNope :: VersionNotFound ) ?;
425
+ let mut details = CrateDetails :: from_matched_release ( & mut conn, & matched_release) . await ?;
417
426
418
427
match details. fetch_readme ( & storage) . await {
419
428
Ok ( readme) => details. readme = readme. or ( details. readme ) ,
@@ -670,23 +679,44 @@ mod tests {
670
679
assert_cache_control, assert_redirect, assert_redirect_cached, async_wrapper, wrapper,
671
680
TestDatabase , TestEnvironment ,
672
681
} ;
673
- use anyhow:: { Context , Error } ;
682
+ use anyhow:: Error ;
674
683
use kuchikiki:: traits:: TendrilSink ;
675
684
use semver:: Version ;
676
685
use std:: collections:: HashMap ;
677
686
687
+ async fn crate_details (
688
+ conn : & mut sqlx:: PgConnection ,
689
+ name : & str ,
690
+ version : & str ,
691
+ req_version : Option < ReqVersion > ,
692
+ ) -> CrateDetails {
693
+ let crate_id: i32 = sqlx:: query_scalar!( "SELECT id FROM crates WHERE name = $1" , name)
694
+ . fetch_one ( & mut * conn)
695
+ . await
696
+ . unwrap ( ) ;
697
+
698
+ let releases = releases_for_crate ( & mut * conn, crate_id) . await . unwrap ( ) ;
699
+
700
+ CrateDetails :: new (
701
+ & mut * conn,
702
+ name,
703
+ & Version :: parse ( version) . unwrap ( ) ,
704
+ req_version,
705
+ releases,
706
+ )
707
+ . await
708
+ . unwrap ( )
709
+ . unwrap ( )
710
+ }
711
+
678
712
async fn assert_last_successful_build_equals (
679
713
db : & TestDatabase ,
680
714
package : & str ,
681
715
version : & str ,
682
716
expected_last_successful_build : Option < & str > ,
683
717
) -> Result < ( ) , Error > {
684
718
let mut conn = db. async_conn ( ) . await ;
685
- let details =
686
- CrateDetails :: new ( & mut conn, package, & Version :: parse ( version) . unwrap ( ) , None )
687
- . await
688
- . with_context ( || anyhow:: anyhow!( "could not fetch crate details" ) ) ?
689
- . unwrap ( ) ;
719
+ let details = crate_details ( & mut conn, package, version, None ) . await ;
690
720
691
721
assert_eq ! (
692
722
details. last_successful_build,
@@ -851,10 +881,7 @@ mod tests {
851
881
852
882
let details = env. runtime ( ) . block_on ( async move {
853
883
let mut conn = db. async_conn ( ) . await ;
854
- CrateDetails :: new ( & mut conn, "foo" , & "0.2.0" . parse ( ) . unwrap ( ) , None )
855
- . await
856
- . unwrap ( )
857
- . unwrap ( )
884
+ crate_details ( & mut conn, "foo" , "0.2.0" , None ) . await
858
885
} ) ;
859
886
860
887
assert_eq ! (
@@ -972,10 +999,7 @@ mod tests {
972
999
for version in & [ "0.0.1" , "0.0.2" , "0.0.3" ] {
973
1000
let details = env. runtime ( ) . block_on ( async move {
974
1001
let mut conn = db. async_conn ( ) . await ;
975
- CrateDetails :: new ( & mut conn, "foo" , & version. parse ( ) . unwrap ( ) , None )
976
- . await
977
- . unwrap ( )
978
- . unwrap ( )
1002
+ crate_details ( & mut conn, "foo" , version, None ) . await
979
1003
} ) ;
980
1004
assert_eq ! (
981
1005
details. latest_release( ) . unwrap( ) . version,
@@ -1002,10 +1026,7 @@ mod tests {
1002
1026
for version in & [ "0.0.1" , "0.0.2" , "0.0.3-pre.1" ] {
1003
1027
let details = env. runtime ( ) . block_on ( async move {
1004
1028
let mut conn = db. async_conn ( ) . await ;
1005
- CrateDetails :: new ( & mut conn, "foo" , & version. parse ( ) . unwrap ( ) , None )
1006
- . await
1007
- . unwrap ( )
1008
- . unwrap ( )
1029
+ crate_details ( & mut conn, "foo" , version, None ) . await
1009
1030
} ) ;
1010
1031
assert_eq ! (
1011
1032
details. latest_release( ) . unwrap( ) . version,
@@ -1033,10 +1054,7 @@ mod tests {
1033
1054
for version in & [ "0.0.1" , "0.0.2" , "0.0.3" ] {
1034
1055
let details = env. runtime ( ) . block_on ( async move {
1035
1056
let mut conn = db. async_conn ( ) . await ;
1036
- CrateDetails :: new ( & mut conn, "foo" , & ( version. parse ( ) . unwrap ( ) ) , None )
1037
- . await
1038
- . unwrap ( )
1039
- . unwrap ( )
1057
+ crate_details ( & mut conn, "foo" , version, None ) . await
1040
1058
} ) ;
1041
1059
assert_eq ! (
1042
1060
details. latest_release( ) . unwrap( ) . version,
@@ -1072,10 +1090,7 @@ mod tests {
1072
1090
for version in & [ "0.0.1" , "0.0.2" , "0.0.3" ] {
1073
1091
let details = env. runtime ( ) . block_on ( async move {
1074
1092
let mut conn = db. async_conn ( ) . await ;
1075
- CrateDetails :: new ( & mut conn, "foo" , & version. parse ( ) . unwrap ( ) , None )
1076
- . await
1077
- . unwrap ( )
1078
- . unwrap ( )
1093
+ crate_details ( & mut conn, "foo" , version, None ) . await
1079
1094
} ) ;
1080
1095
assert_eq ! (
1081
1096
details. latest_release( ) . unwrap( ) . version,
@@ -1132,10 +1147,7 @@ mod tests {
1132
1147
1133
1148
let details = env. runtime ( ) . block_on ( async move {
1134
1149
let mut conn = db. async_conn ( ) . await ;
1135
- CrateDetails :: new ( & mut conn, "foo" , & "0.0.1" . parse ( ) . unwrap ( ) , None )
1136
- . await
1137
- . unwrap ( )
1138
- . unwrap ( )
1150
+ crate_details ( & mut conn, "foo" , "0.0.1" , None ) . await
1139
1151
} ) ;
1140
1152
assert_eq ! (
1141
1153
details. owners,
@@ -1158,10 +1170,7 @@ mod tests {
1158
1170
1159
1171
let details = env. runtime ( ) . block_on ( async move {
1160
1172
let mut conn = db. async_conn ( ) . await ;
1161
- CrateDetails :: new ( & mut conn, "foo" , & "0.0.1" . parse ( ) . unwrap ( ) , None )
1162
- . await
1163
- . unwrap ( )
1164
- . unwrap ( )
1173
+ crate_details ( & mut conn, "foo" , "0.0.1" , None ) . await
1165
1174
} ) ;
1166
1175
let mut owners = details. owners ;
1167
1176
owners. sort ( ) ;
@@ -1185,10 +1194,7 @@ mod tests {
1185
1194
1186
1195
let details = env. runtime ( ) . block_on ( async move {
1187
1196
let mut conn = db. async_conn ( ) . await ;
1188
- CrateDetails :: new ( & mut conn, "foo" , & "0.0.1" . parse ( ) . unwrap ( ) , None )
1189
- . await
1190
- . unwrap ( )
1191
- . unwrap ( )
1197
+ crate_details ( & mut conn, "foo" , "0.0.1" , None ) . await
1192
1198
} ) ;
1193
1199
assert_eq ! (
1194
1200
details. owners,
@@ -1207,10 +1213,7 @@ mod tests {
1207
1213
1208
1214
let details = env. runtime ( ) . block_on ( async move {
1209
1215
let mut conn = db. async_conn ( ) . await ;
1210
- CrateDetails :: new ( & mut conn, "foo" , & "0.0.1" . parse ( ) . unwrap ( ) , None )
1211
- . await
1212
- . unwrap ( )
1213
- . unwrap ( )
1216
+ crate_details ( & mut conn, "foo" , "0.0.1" , None ) . await
1214
1217
} ) ;
1215
1218
assert_eq ! (
1216
1219
details. owners,
@@ -1654,10 +1657,7 @@ mod tests {
1654
1657
1655
1658
let details = env. runtime ( ) . block_on ( async move {
1656
1659
let mut conn = env. async_db ( ) . await . async_conn ( ) . await ;
1657
- CrateDetails :: new ( & mut conn, "dummy" , & "0.5.0" . parse ( ) . unwrap ( ) , None )
1658
- . await
1659
- . unwrap ( )
1660
- . unwrap ( )
1660
+ crate_details ( & mut conn, "dummy" , "0.5.0" , None ) . await
1661
1661
} ) ;
1662
1662
assert ! ( matches!(
1663
1663
env. runtime( )
0 commit comments