Skip to content

Commit 4d37ada

Browse files
committed
semver match should skip over in progress releases when we have others
1 parent e0f2ed0 commit 4d37ada

File tree

1 file changed

+67
-24
lines changed

1 file changed

+67
-24
lines changed

Diff for: src/web/mod.rs

+67-24
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)