@@ -236,6 +236,27 @@ impl MatchedRelease {
236236 }
237237}
238238
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+
239260/// Checks the database for crate releases that match the given name and version.
240261///
241262/// `version` may be an exact version number or loose semver version requirement. The return value
@@ -307,14 +328,12 @@ async fn match_version(
307328 ReqVersion :: Semver ( version_req) => version_req. clone ( ) ,
308329 } ;
309330
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+ } ) {
318337 return Ok ( MatchedRelease {
319338 name : name. to_owned ( ) ,
320339 corrected_name,
@@ -324,22 +343,17 @@ async fn match_version(
324343 } ) ;
325344 }
326345
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+ } ) ;
343357 }
344358
345359 // Since we return with a CrateNotFound earlier if the db reply is empty,
@@ -1050,6 +1064,35 @@ mod test {
10501064 } ) ;
10511065 }
10521066
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+
10531096 #[ test]
10541097 // https://github.com/rust-lang/docs.rs/issues/1682
10551098 fn prereleases_are_considered_when_others_dont_match ( ) {
0 commit comments