@@ -236,6 +236,27 @@ impl MatchedRelease {
236
236
}
237
237
}
238
238
239
+ fn semver_match < ' a , F : Fn ( & Release ) -> bool > (
240
+ releases : & ' a [ Release ] ,
241
+ req : & VersionReq ,
242
+ filter : F ,
243
+ ) -> Option < & ' a Release > {
244
+ if let Some ( release) = releases
245
+ . iter ( )
246
+ . filter ( |release| filter ( release) )
247
+ . find ( |release| req. matches ( & release. version ) )
248
+ {
249
+ Some ( release)
250
+ } else if req == & VersionReq :: STAR {
251
+ // semver `*` does not match pre-releases.
252
+ // When someone wants the latest release and we have only pre-releases
253
+ // just return the latest prerelease.
254
+ return releases. iter ( ) . find ( |release| filter ( release) ) ;
255
+ } else {
256
+ None
257
+ }
258
+ }
259
+
239
260
/// Checks the database for crate releases that match the given name and version.
240
261
///
241
262
/// `version` may be an exact version number or loose semver version requirement. The return value
@@ -307,14 +328,12 @@ async fn match_version(
307
328
ReqVersion :: Semver ( version_req) => version_req. clone ( ) ,
308
329
} ;
309
330
310
- // when matching semver requirements, we only want to look at non-yanked releases.
311
- let flt = |r : & & Release | r. yanked . is_none ( ) || r. yanked == Some ( false ) ;
312
-
313
- if let Some ( release) = releases
314
- . iter ( )
315
- . filter ( flt)
316
- . find ( |release| req_semver. matches ( & release. version ) )
317
- {
331
+ // when matching semver requirements,
332
+ // we generally only want to look at non-yanked releases,
333
+ // excluding releases which just contain in-progress builds
334
+ if let Some ( release) = semver_match ( & releases, & req_semver, |r : & Release | {
335
+ r. build_status != BuildStatus :: InProgress && ( r. yanked . is_none ( ) || r. yanked == Some ( false ) )
336
+ } ) {
318
337
return Ok ( MatchedRelease {
319
338
name : name. to_owned ( ) ,
320
339
corrected_name,
@@ -324,22 +343,17 @@ async fn match_version(
324
343
} ) ;
325
344
}
326
345
327
- // semver `*` does not match pre-releases.
328
- // When someone wants the latest release and we have only pre-releases
329
- // just return the latest prerelease.
330
- if req_semver == VersionReq :: STAR {
331
- return releases
332
- . iter ( )
333
- . find ( flt)
334
- . cloned ( )
335
- . map ( |release| MatchedRelease {
336
- name : name. to_owned ( ) ,
337
- corrected_name : corrected_name. clone ( ) ,
338
- req_version : input_version. clone ( ) ,
339
- release,
340
- all_releases : releases,
341
- } )
342
- . ok_or ( AxumNope :: VersionNotFound ) ;
346
+ // when we don't find any match with "normal" releases, we also look into in-progress releases
347
+ if let Some ( release) = semver_match ( & releases, & req_semver, |r : & Release | {
348
+ r. yanked . is_none ( ) || r. yanked == Some ( false )
349
+ } ) {
350
+ return Ok ( MatchedRelease {
351
+ name : name. to_owned ( ) ,
352
+ corrected_name,
353
+ req_version : input_version. clone ( ) ,
354
+ release : release. clone ( ) ,
355
+ all_releases : releases,
356
+ } ) ;
343
357
}
344
358
345
359
// Since we return with a CrateNotFound earlier if the db reply is empty,
@@ -1050,6 +1064,35 @@ mod test {
1050
1064
} ) ;
1051
1065
}
1052
1066
1067
+ #[ test]
1068
+ fn in_progress_releases_are_ignored_when_others_match ( ) {
1069
+ async_wrapper ( |env| async move {
1070
+ let db = env. async_db ( ) . await ;
1071
+
1072
+ // normal release
1073
+ release ( "1.0.0" , & env) . await ;
1074
+
1075
+ // in progress release
1076
+ env. async_fake_release ( )
1077
+ . await
1078
+ . name ( "foo" )
1079
+ . version ( "1.1.0" )
1080
+ . builds ( vec ! [
1081
+ FakeBuild :: default ( ) . build_status( BuildStatus :: InProgress )
1082
+ ] )
1083
+ . create_async ( )
1084
+ . await ?;
1085
+
1086
+ // STAR gives me the prod release
1087
+ assert_eq ! ( version( Some ( "*" ) , db) . await , exact( "1.0.0" ) ) ;
1088
+
1089
+ // exact-match query gives me the in progress release
1090
+ assert_eq ! ( version( Some ( "=1.1.0" ) , db) . await , exact( "1.1.0" ) ) ;
1091
+
1092
+ Ok ( ( ) )
1093
+ } )
1094
+ }
1095
+
1053
1096
#[ test]
1054
1097
// https://github.com/rust-lang/docs.rs/issues/1682
1055
1098
fn prereleases_are_considered_when_others_dont_match ( ) {
0 commit comments