Skip to content

Commit 5d0fe88

Browse files
committed
Refactor top_version into the version module
Where we used to have max_version, we now have two kinds of top versions: - the highest semver version - the most recently updated version.
1 parent c23c8c1 commit 5d0fe88

File tree

4 files changed

+51
-88
lines changed

4 files changed

+51
-88
lines changed

src/controllers/krate/metadata.rs

+2-23
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
//! Endpoints that expose metadata about a crate
22
//!
3-
//! These endpoints provide data that could be obtained direclty from the
3+
//! These endpoints provide data that could be obtained directly from the
44
//! index or cached metadata which was extracted (client side) from the
55
//! `Cargo.toml` file.
66
7-
use chrono::NaiveDateTime;
8-
97
use crate::controllers::prelude::*;
108
use crate::models::{
119
Category, Crate, CrateCategory, CrateKeyword, CrateVersions, Keyword, RecentCrateDownloads,
@@ -33,26 +31,7 @@ pub fn summary(req: &mut dyn Request) -> AppResult<Response> {
3331
versions
3432
.grouped_by(&krates)
3533
.into_iter()
36-
.map(|versions| {
37-
let pairs: Vec<_> = versions
38-
.into_iter()
39-
.map(|version| (version.created_at, version.num.to_string()))
40-
.collect();
41-
TopVersions {
42-
newest: pairs
43-
.to_owned()
44-
.into_iter()
45-
.max()
46-
.unwrap_or((NaiveDateTime::from_timestamp(0, 0), "0.0.0".to_owned()))
47-
.1,
48-
highest: Version::max(
49-
pairs
50-
.into_iter()
51-
.map(|(_, s)| semver::Version::parse(&s).unwrap()),
52-
)
53-
.to_string(),
54-
}
55-
})
34+
.map(|versions| Version::top(versions.into_iter().map(|v| (v.created_at, v.num))))
5635
.zip(krates)
5736
.map(|(top_versions, krate)| {
5837
Ok(krate.minimal_encodable(&top_versions, None, false, None))

src/controllers/krate/search.rs

+1-22
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
//! Endpoint for searching and discovery functionality
22
3-
use chrono::NaiveDateTime;
43
use diesel::dsl::*;
54
use diesel_full_text_search::*;
65

76
use crate::controllers::helpers::Paginate;
87
use crate::controllers::prelude::*;
9-
use crate::models::krate::TopVersions;
108
use crate::models::{Crate, CrateBadge, CrateOwner, CrateVersions, OwnerKind, Version};
119
use crate::schema::*;
1210
use crate::views::EncodableCrate;
@@ -181,26 +179,7 @@ pub fn search(req: &mut dyn Request) -> AppResult<Response> {
181179
.load::<Version>(&*conn)?
182180
.grouped_by(&crates)
183181
.into_iter()
184-
.map(|versions| {
185-
let pairs: Vec<_> = versions
186-
.into_iter()
187-
.map(|version| (version.created_at, version.num.to_string()))
188-
.collect();
189-
TopVersions {
190-
newest: pairs
191-
.to_owned()
192-
.into_iter()
193-
.max()
194-
.unwrap_or((NaiveDateTime::from_timestamp(0, 0), "0.0.0".to_owned()))
195-
.1,
196-
highest: Version::max(
197-
pairs
198-
.into_iter()
199-
.map(|(_, s)| semver::Version::parse(&s).unwrap()),
200-
)
201-
.to_string(),
202-
}
203-
});
182+
.map(|versions| Version::top(versions.into_iter().map(|v| (v.created_at, v.num))));
204183

205184
let badges = CrateBadge::belonging_to(&crates)
206185
.select((badges::crate_id, badges::all_columns))

src/models/krate.rs

+9-31
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ use url::Url;
88

99
use crate::app::App;
1010
use crate::email;
11-
use crate::util::{cargo_err, AppResult};
12-
11+
use crate::models::version::TopVersions;
1312
use crate::models::{
1413
Badge, Category, CrateOwner, CrateOwnerInvitation, Keyword, NewCrateOwnerInvitation, Owner,
1514
OwnerKind, ReverseDependency, User, Version,
1615
};
16+
use crate::util::{cargo_err, AppResult};
1717
use crate::views::{EncodableCrate, EncodableCrateLinks};
1818

1919
use crate::models::helpers::with_count::*;
@@ -48,14 +48,6 @@ pub struct Crate {
4848
pub max_upload_size: Option<i32>,
4949
}
5050

51-
/// The highest version (in semver order) and the most recently updated version
52-
/// for a single crate.
53-
#[derive(Debug, Clone)]
54-
pub struct TopVersions {
55-
pub highest: String,
56-
pub newest: String,
57-
}
58-
5951
/// We literally never want to select `textsearchable_index_col`
6052
/// so we provide this type and constant to pass to `.select`
6153
type AllColumns = (
@@ -347,8 +339,8 @@ impl Crate {
347339
keywords: keyword_ids,
348340
categories: category_ids,
349341
badges,
350-
max_version: top_versions.highest.to_owned(),
351-
newest_version: top_versions.newest.to_owned(),
342+
max_version: top_versions.highest.to_string(),
343+
newest_version: top_versions.newest.to_string(),
352344
documentation,
353345
homepage,
354346
exact_match,
@@ -398,25 +390,11 @@ impl Crate {
398390
pub fn top_versions(&self, conn: &PgConnection) -> AppResult<TopVersions> {
399391
use crate::schema::versions::dsl::*;
400392

401-
let results = self
402-
.versions()
403-
.select((updated_at, num))
404-
.load::<(NaiveDateTime, String)>(conn)?;
405-
406-
Ok(TopVersions {
407-
newest: results
408-
.to_owned()
409-
.into_iter()
410-
.max()
411-
.unwrap_or((NaiveDateTime::from_timestamp(0, 0), "0.0.0".to_owned()))
412-
.1,
413-
highest: Version::max(
414-
results
415-
.into_iter()
416-
.map(|(_, s)| semver::Version::parse(&s).unwrap()),
417-
)
418-
.to_string(),
419-
})
393+
Ok(Version::top(
394+
self.versions()
395+
.select((updated_at, num))
396+
.load::<(NaiveDateTime, semver::Version)>(conn)?,
397+
))
420398
}
421399

422400
pub fn owners(&self, conn: &PgConnection) -> AppResult<Vec<Owner>> {

src/models/version.rs

+39-12
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,25 @@ pub struct NewVersion {
3737
published_by: i32,
3838
}
3939

40+
/// The highest version (semver order) and the most recently updated version.
41+
/// Typically used for a single crate.
42+
#[derive(Debug, Clone)]
43+
pub struct TopVersions {
44+
pub highest: semver::Version,
45+
pub newest: semver::Version,
46+
}
47+
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![],
56+
}
57+
}
58+
4059
impl Version {
4160
pub fn encodable(self, crate_name: &str, published_by: Option<User>) -> EncodableVersion {
4261
let Version {
@@ -83,20 +102,28 @@ impl Version {
83102
.load(conn)
84103
}
85104

86-
pub fn max<T>(versions: T) -> semver::Version
105+
/// Return both the newest (most recently updated) and the
106+
/// highest version (in semver order) for a collection of date/version pairs.
107+
pub fn top<T>(pairs: T) -> TopVersions
87108
where
88-
T: IntoIterator<Item = semver::Version>,
109+
T: Clone + IntoIterator<Item = (NaiveDateTime, semver::Version)>,
89110
{
90-
versions
91-
.into_iter()
92-
.max()
93-
.unwrap_or_else(|| semver::Version {
94-
major: 0,
95-
minor: 0,
96-
patch: 0,
97-
pre: vec![],
98-
build: vec![],
99-
})
111+
TopVersions {
112+
newest: pairs
113+
.clone()
114+
.into_iter()
115+
.max()
116+
.unwrap_or((
117+
NaiveDateTime::from_timestamp(0, 0),
118+
default_semver_version(),
119+
))
120+
.1,
121+
highest: pairs
122+
.into_iter()
123+
.map(|(_, v)| v)
124+
.max()
125+
.unwrap_or_else(default_semver_version),
126+
}
100127
}
101128

102129
pub fn record_readme_rendering(version_id_: i32, conn: &PgConnection) -> QueryResult<usize> {

0 commit comments

Comments
 (0)