Skip to content

Commit 644e03d

Browse files
jyn514Joshua Nelson
authored and
Joshua Nelson
committed
Fix various bugs in match_version
- Ignore yanked versions - Ignore pre-release versions - Add lots of tests Note: this now queries `releases.version` instead of `crates.versions` so that I have accessed to `releases.yanked`. This _shouldn't_ affect behavior, but if a previous bug set `crates.versions` to something different, it will no longer be seen. Closes #223, #221
1 parent 10dc6f5 commit 644e03d

File tree

1 file changed

+52
-16
lines changed

1 file changed

+52
-16
lines changed

src/web/mod.rs

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ impl Handler for CratesfyiHandler {
186186
}
187187

188188
/// Represents the possible results of attempting to load a version requirement.
189+
#[derive(Debug, Clone, PartialEq, Eq)]
189190
enum MatchVersion {
190191
/// `match_version` was given an exact version, which matched a saved crate version.
191192
Exact(String),
@@ -226,19 +227,15 @@ fn match_version(conn: &Connection, name: &str, version: Option<&str>) -> MatchV
226227
.map(|v| if v == "newest" || v == "latest" { "*".to_owned() } else { v })
227228
.unwrap_or("*".to_string());
228229

229-
let versions = {
230-
let mut versions = Vec::new();
231-
let rows = conn.query("SELECT versions FROM crates WHERE name = $1", &[&name]).unwrap();
230+
let versions: Vec<String> = {
231+
let query = "SELECT version
232+
FROM releases INNER JOIN crates ON releases.crate_id = crates.id
233+
WHERE name = $1 AND yanked = false";
234+
let rows = conn.query(query, &[&name]).unwrap();
232235
if rows.len() == 0 {
233236
return MatchVersion::None;
234237
}
235-
let versions_json: Json = rows.get(0).get(0);
236-
for version in versions_json.as_array().unwrap() {
237-
let version: String = version.as_string().unwrap().to_owned();
238-
versions.push(version);
239-
}
240-
241-
versions
238+
rows.iter().map(|row| row.get(0)).collect()
242239
};
243240

244241
// first check for exact match
@@ -274,18 +271,18 @@ fn match_version(conn: &Connection, name: &str, version: Option<&str>) -> MatchV
274271
versions_sem
275272
};
276273

277-
// semver is acting weird for '*' (any) range if a crate only have pre-release versions
278-
// return first version if requested version is '*'
279-
if req_version == "*" && !versions_sem.is_empty() {
280-
return MatchVersion::Semver(format!("{}", versions_sem[0]));
281-
}
282-
283274
for version in &versions_sem {
284275
if req_sem_ver.matches(&version) {
285276
return MatchVersion::Semver(format!("{}", version));
286277
}
287278
}
288279

280+
// semver is acting weird for '*' (any) range if a crate only have pre-release versions
281+
// return first version if requested version is '*'
282+
if req_version == "*" && !versions_sem.is_empty() {
283+
return MatchVersion::Semver(format!("{}", versions_sem[0]));
284+
}
285+
289286
MatchVersion::None
290287
}
291288

@@ -517,4 +514,43 @@ mod test {
517514
Ok(())
518515
});
519516
}
517+
518+
#[test]
519+
fn test_match_version() {
520+
use web::{match_version, MatchVersion};
521+
522+
crate::test::wrapper(|env| {
523+
let db = env.db();
524+
let version = |v| match_version(&db.conn(), "foo", v);
525+
let release = |v| db.fake_release().name("foo").version(v).create().unwrap();
526+
527+
release("0.3.1-pre");
528+
assert_eq!(version(Some("*")), MatchVersion::Semver("0.3.1-pre".into()));
529+
530+
release("0.3.1-alpha");
531+
assert_eq!(version(Some("0.3.1-alpha")), MatchVersion::Exact("0.3.1-alpha".into()));
532+
533+
let release_id = release("0.3.0");
534+
let three = MatchVersion::Semver("0.3.0".into());
535+
assert_eq!(version(Some("*")), three);
536+
// same thing but make sure None behaves like we think it does
537+
assert_eq!(version(None), three);
538+
// make sure exact matches still work
539+
assert_eq!(version(Some("0.3.0")), MatchVersion::Exact("0.3.0".into()));
540+
541+
// https://github.com/rust-lang/docs.rs/issues/395
542+
let query = "UPDATE releases SET yanked = true WHERE id = $1 AND version = '0.3.0'";
543+
db.conn().query(query, &[&release_id]).unwrap();
544+
release("0.1.0+4.1");
545+
assert_eq!(version(Some("0.1.0+4.1")), MatchVersion::Exact("0.1.0+4.1".into()));
546+
assert_eq!(version(None), MatchVersion::Semver("0.1.0+4.1".into()));
547+
release("0.1.1");
548+
assert_eq!(version(None), MatchVersion::Semver("0.1.1".into()));
549+
release("0.5.1+zstd.1.4.4");
550+
assert_eq!(version(None), MatchVersion::Semver("0.5.1+zstd.1.4.4".into()));
551+
assert_eq!(version(Some("0.5.1+zstd.1.4.4")), MatchVersion::Exact("0.5.1+zstd.1.4.4".into()));
552+
553+
Ok(())
554+
})
555+
}
520556
}

0 commit comments

Comments
 (0)