Skip to content

Commit f65a640

Browse files
committed
TopVersions for highest and newest
1 parent 592f612 commit f65a640

File tree

5 files changed

+43
-20
lines changed

5 files changed

+43
-20
lines changed

src/controllers/krate/metadata.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub fn summary(req: &mut dyn Request) -> AppResult<Response> {
3131
versions
3232
.grouped_by(&krates)
3333
.into_iter()
34-
.map(|versions| Version::max(versions.into_iter().map(|v| v.num)))
34+
.map(|versions| Version::max(versions.into_iter().map(|v| v.num)).to_string())
3535
.zip(krates)
3636
.map(|(max_version, krate)| {
3737
Ok(krate.minimal_encodable(&max_version, None, false, None))
@@ -142,7 +142,7 @@ pub fn show(req: &mut dyn Request) -> AppResult<Response> {
142142
let badges = badges::table
143143
.filter(badges::crate_id.eq(krate.id))
144144
.load(&*conn)?;
145-
let max_version = krate.max_version(&conn)?;
145+
let top_versions = krate.top_versions(&conn)?;
146146

147147
#[derive(Serialize)]
148148
struct R {
@@ -154,7 +154,7 @@ pub fn show(req: &mut dyn Request) -> AppResult<Response> {
154154
}
155155
Ok(req.json(&R {
156156
krate: krate.clone().encodable(
157-
&max_version,
157+
&top_versions,
158158
Some(ids),
159159
Some(&kws),
160160
Some(&cats),

src/controllers/krate/publish.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ pub fn publish(req: &mut dyn Request) -> AppResult<Response> {
168168
// Update all badges for this crate, collecting any invalid badges in
169169
// order to be able to warn about them
170170
let ignored_invalid_badges = Badge::update_crate(&conn, &krate, new_crate.badges.as_ref())?;
171-
let max_version = krate.max_version(&conn)?;
171+
let top_versions = krate.top_versions(&conn)?;
172172

173173
if let Some(readme) = new_crate.readme {
174174
render::render_and_upload_readme(
@@ -215,7 +215,7 @@ pub fn publish(req: &mut dyn Request) -> AppResult<Response> {
215215
};
216216

217217
Ok(req.json(&GoodCrate {
218-
krate: krate.minimal_encodable(&max_version, None, false, None),
218+
krate: krate.minimal_encodable(&top_versions.highest, None, false, None),
219219
warnings,
220220
}))
221221
})

src/controllers/krate/search.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ pub fn search(req: &mut dyn Request) -> AppResult<Response> {
179179
.load::<Version>(&*conn)?
180180
.grouped_by(&crates)
181181
.into_iter()
182-
.map(|versions| Version::max(versions.into_iter().map(|v| v.num)));
182+
.map(|versions| Version::max(versions.into_iter().map(|v| v.num)).to_string());
183183

184184
let badges = CrateBadge::belonging_to(&crates)
185185
.select((badges::crate_id, badges::all_columns))

src/models/krate.rs

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ 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+
5159
/// We literally never want to select `textsearchable_index_col`
5260
/// so we provide this type and constant to pass to `.select`
5361
type AllColumns = (
@@ -204,7 +212,7 @@ impl<'a> NewCrate<'a> {
204212
}
205213

206214
impl Crate {
207-
/// SQL filter based on whether the crate's name loosly matches the given
215+
/// SQL filter based on whether the crate's name loosely matches the given
208216
/// string.
209217
///
210218
/// The operator used varies based on the input.
@@ -281,13 +289,16 @@ impl Crate {
281289

282290
pub fn minimal_encodable(
283291
self,
284-
max_version: &semver::Version,
292+
max_version: &str,
285293
badges: Option<Vec<Badge>>,
286294
exact_match: bool,
287295
recent_downloads: Option<i64>,
288296
) -> EncodableCrate {
289297
self.encodable(
290-
max_version,
298+
&TopVersions {
299+
highest: max_version.to_owned(),
300+
newest: max_version.to_owned(),
301+
},
291302
None,
292303
None,
293304
None,
@@ -300,7 +311,7 @@ impl Crate {
300311
#[allow(clippy::too_many_arguments)]
301312
pub fn encodable(
302313
self,
303-
max_version: &semver::Version,
314+
top_versions: &TopVersions,
304315
versions: Option<Vec<i32>>,
305316
keywords: Option<&[Keyword]>,
306317
categories: Option<&[Category]>,
@@ -339,8 +350,8 @@ impl Crate {
339350
keywords: keyword_ids,
340351
categories: category_ids,
341352
badges,
342-
max_version: max_version.to_string(),
343-
newest_version: max_version.to_string(), // FIXME: Make this the newest, not the highest
353+
max_version: top_versions.highest.to_owned(),
354+
newest_version: top_versions.newest.to_owned(),
344355
documentation,
345356
homepage,
346357
exact_match,
@@ -385,16 +396,28 @@ impl Crate {
385396
}
386397
}
387398

388-
pub fn max_version(&self, conn: &PgConnection) -> AppResult<semver::Version> {
399+
pub fn top_versions(&self, conn: &PgConnection) -> AppResult<TopVersions> {
389400
use crate::schema::versions::dsl::*;
390401

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

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

src/tests/util.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ impl TestAppBuilder {
305305
}
306306
}
307307

308-
/// A colleciton of helper methods for the 3 authentication types
308+
/// A collection of helper methods for the 3 authentication types
309309
///
310310
/// Helper methods go through public APIs, and should not modify the database directly
311311
pub trait RequestHelper {

0 commit comments

Comments
 (0)