Skip to content

Commit c2d1818

Browse files
committed
Auto merge of #3113 - Turbo87:top-version-cleanup, r=jtgeibel
Clean up `TopVersions` code This PR cleans up the code that figures out the `highest` and `newest` versions of a crate in several ways. I hope that the commit list gives enough context on the individual changes. Primarily, this decouples the code from the `Version` struct, and it moves the `0.0.0` defaulting to the `encodable()` method of the `Krate` model, instead of performing that in the low-level code directly. Like #3067, this PR is also in preparation for resolving #2710. r? `@jtgeibel`
2 parents fc123d5 + 7a71e00 commit c2d1818

File tree

5 files changed

+53
-52
lines changed

5 files changed

+53
-52
lines changed

src/controllers/krate/metadata.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::controllers::helpers::pagination::PaginationOptions;
99

1010
use crate::models::{
1111
Category, Crate, CrateCategory, CrateKeyword, CrateVersions, Keyword, RecentCrateDownloads,
12-
User, Version, VersionOwnerAction,
12+
TopVersions, User, Version, VersionOwnerAction,
1313
};
1414
use crate::schema::*;
1515
use crate::views::{
@@ -37,7 +37,7 @@ pub fn summary(req: &mut dyn RequestExt) -> EndpointResult {
3737
versions
3838
.grouped_by(&krates)
3939
.into_iter()
40-
.map(|versions| Version::top(versions.into_iter().map(|v| (v.created_at, v.num))))
40+
.map(TopVersions::from_versions)
4141
.zip(krates)
4242
.zip(recent_downloads)
4343
.map(|((top_versions, krate), recent_downloads)| {

src/controllers/krate/search.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ use diesel_full_text_search::*;
66
use crate::controllers::cargo_prelude::*;
77
use crate::controllers::helpers::Paginate;
88
use crate::controllers::util::AuthenticatedUser;
9-
use crate::models::{Crate, CrateBadge, CrateOwner, CrateVersions, OwnerKind, Version};
9+
use crate::models::{
10+
Crate, CrateBadge, CrateOwner, CrateVersions, OwnerKind, TopVersions, Version,
11+
};
1012
use crate::schema::*;
1113
use crate::util::errors::{bad_request, ChainError};
1214
use crate::views::EncodableCrate;
@@ -207,7 +209,7 @@ pub fn search(req: &mut dyn RequestExt) -> EndpointResult {
207209
let versions = versions
208210
.grouped_by(&crates)
209211
.into_iter()
210-
.map(|versions| Version::top(versions.into_iter().map(|v| (v.created_at, v.num))));
212+
.map(TopVersions::from_versions);
211213

212214
let badges: Vec<CrateBadge> = CrateBadge::belonging_to(&crates)
213215
.select((badges::crate_id, badges::all_columns))

src/models.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub use self::rights::Rights;
1313
pub use self::team::{NewTeam, Team};
1414
pub use self::token::{ApiToken, CreatedApiToken};
1515
pub use self::user::{NewUser, User};
16-
pub use self::version::{NewVersion, Version};
16+
pub use self::version::{NewVersion, TopVersions, Version};
1717

1818
pub mod helpers;
1919

src/models/krate.rs

+15-3
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,18 @@ impl Crate {
345345
let badges = badges.map(|bs| bs.into_iter().map(Badge::into).collect());
346346
let documentation = Crate::remove_blocked_documentation_urls(documentation);
347347

348+
let max_version = top_versions
349+
.highest
350+
.as_ref()
351+
.map(|v| v.to_string())
352+
.unwrap_or_else(|| "0.0.0".to_string());
353+
354+
let newest_version = top_versions
355+
.newest
356+
.as_ref()
357+
.map(|v| v.to_string())
358+
.unwrap_or_else(|| "0.0.0".to_string());
359+
348360
EncodableCrate {
349361
id: name.clone(),
350362
name: name.clone(),
@@ -356,8 +368,8 @@ impl Crate {
356368
keywords: keyword_ids,
357369
categories: category_ids,
358370
badges,
359-
max_version: top_versions.highest.to_string(),
360-
newest_version: top_versions.newest.to_string(),
371+
max_version,
372+
newest_version,
361373
documentation,
362374
homepage,
363375
exact_match,
@@ -407,7 +419,7 @@ impl Crate {
407419
pub fn top_versions(&self, conn: &PgConnection) -> QueryResult<TopVersions> {
408420
use crate::schema::versions::dsl::*;
409421

410-
Ok(Version::top(
422+
Ok(TopVersions::from_date_version_pairs(
411423
self.versions().select((updated_at, num)).load(conn)?,
412424
))
413425
}

src/models/version.rs

+31-44
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,29 @@ pub struct NewVersion {
4141
/// Typically used for a single crate.
4242
#[derive(Debug, Clone, Eq, PartialEq)]
4343
pub struct TopVersions {
44-
pub highest: semver::Version,
45-
pub newest: semver::Version,
44+
/// The "highest" version in terms of semver
45+
pub highest: Option<semver::Version>,
46+
/// The "newest" version in terms of publishing date
47+
pub newest: Option<semver::Version>,
4648
}
4749

48-
/// A default semver value, "0.0.0", for use in TopVersions
49-
fn default_semver_version() -> semver::Version {
50-
semver::Version {
51-
major: 0,
52-
minor: 0,
53-
patch: 0,
54-
pre: vec![],
55-
build: vec![],
50+
impl TopVersions {
51+
/// Return both the newest (most recently updated) and the
52+
/// highest version (in semver order) for a list of `Version` instances.
53+
pub fn from_versions(versions: Vec<Version>) -> Self {
54+
Self::from_date_version_pairs(versions.into_iter().map(|v| (v.created_at, v.num)))
55+
}
56+
57+
/// Return both the newest (most recently updated) and the
58+
/// highest version (in semver order) for a collection of date/version pairs.
59+
pub fn from_date_version_pairs<T>(pairs: T) -> Self
60+
where
61+
T: Clone + IntoIterator<Item = (NaiveDateTime, semver::Version)>,
62+
{
63+
let newest = pairs.clone().into_iter().max().map(|(_, v)| v);
64+
let highest = pairs.into_iter().map(|(_, v)| v).max();
65+
66+
Self { newest, highest }
5667
}
5768
}
5869

@@ -115,30 +126,6 @@ impl Version {
115126
.load(conn)
116127
}
117128

118-
/// Return both the newest (most recently updated) and the
119-
/// highest version (in semver order) for a collection of date/version pairs.
120-
pub fn top<T>(pairs: T) -> TopVersions
121-
where
122-
T: Clone + IntoIterator<Item = (NaiveDateTime, semver::Version)>,
123-
{
124-
TopVersions {
125-
newest: pairs
126-
.clone()
127-
.into_iter()
128-
.max()
129-
.unwrap_or((
130-
NaiveDateTime::from_timestamp(0, 0),
131-
default_semver_version(),
132-
))
133-
.1,
134-
highest: pairs
135-
.into_iter()
136-
.map(|(_, v)| v)
137-
.max()
138-
.unwrap_or_else(default_semver_version),
139-
}
140-
}
141-
142129
pub fn record_readme_rendering(version_id_: i32, conn: &PgConnection) -> QueryResult<usize> {
143130
use crate::schema::readme_renderings::dsl::*;
144131
use diesel::dsl::now;
@@ -255,7 +242,7 @@ impl NewVersion {
255242

256243
#[cfg(test)]
257244
mod tests {
258-
use super::{TopVersions, Version};
245+
use super::TopVersions;
259246
use chrono::NaiveDateTime;
260247

261248
#[track_caller]
@@ -272,10 +259,10 @@ mod tests {
272259
fn top_versions_empty() {
273260
let versions = vec![];
274261
assert_eq!(
275-
Version::top(versions),
262+
TopVersions::from_date_version_pairs(versions),
276263
TopVersions {
277-
highest: version("0.0.0"),
278-
newest: version("0.0.0"),
264+
highest: None,
265+
newest: None,
279266
}
280267
);
281268
}
@@ -284,10 +271,10 @@ mod tests {
284271
fn top_versions_single() {
285272
let versions = vec![(date("2020-12-03T12:34:56"), version("1.0.0"))];
286273
assert_eq!(
287-
Version::top(versions),
274+
TopVersions::from_date_version_pairs(versions),
288275
TopVersions {
289-
highest: version("1.0.0"),
290-
newest: version("1.0.0"),
276+
highest: Some(version("1.0.0")),
277+
newest: Some(version("1.0.0")),
291278
}
292279
);
293280
}
@@ -300,10 +287,10 @@ mod tests {
300287
(date("2020-12-03T12:34:56"), version("1.1.0")),
301288
];
302289
assert_eq!(
303-
Version::top(versions),
290+
TopVersions::from_date_version_pairs(versions),
304291
TopVersions {
305-
highest: version("2.0.0-alpha.1"),
306-
newest: version("1.1.0"),
292+
highest: Some(version("2.0.0-alpha.1")),
293+
newest: Some(version("1.1.0")),
307294
}
308295
);
309296
}

0 commit comments

Comments
 (0)