Skip to content

Commit e9b8edd

Browse files
committed
TopVersions for highest and newest
1 parent 777d918 commit e9b8edd

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
@@ -33,7 +33,7 @@ pub fn summary(req: &mut dyn Request) -> AppResult<Response> {
3333
versions
3434
.grouped_by(&krates)
3535
.into_iter()
36-
.map(|versions| Version::max(versions.into_iter().map(|v| v.num)))
36+
.map(|versions| Version::max(versions.into_iter().map(|v| v.num)).to_string())
3737
.zip(krates)
3838
.map(|(max_version, krate)| {
3939
Ok(krate.minimal_encodable(&max_version, None, false, None))
@@ -131,7 +131,7 @@ pub fn show(req: &mut dyn Request) -> AppResult<Response> {
131131
let badges = badges::table
132132
.filter(badges::crate_id.eq(krate.id))
133133
.load(&*conn)?;
134-
let max_version = krate.max_version(&conn)?;
134+
let top_versions = krate.top_versions(&conn)?;
135135

136136
#[derive(Serialize)]
137137
struct R {
@@ -143,7 +143,7 @@ pub fn show(req: &mut dyn Request) -> AppResult<Response> {
143143
}
144144
Ok(req.json(&R {
145145
krate: krate.clone().encodable(
146-
&max_version,
146+
&top_versions,
147147
Some(ids),
148148
Some(&kws),
149149
Some(&cats),

src/controllers/krate/publish.rs

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

161161
if let Some(readme) = new_crate.readme {
162162
render::render_and_upload_readme(
@@ -203,7 +203,7 @@ pub fn publish(req: &mut dyn Request) -> AppResult<Response> {
203203
};
204204

205205
Ok(req.json(&GoodCrate {
206-
krate: krate.minimal_encodable(&max_version, None, false, None),
206+
krate: krate.minimal_encodable(&top_versions.highest, None, false, None),
207207
warnings,
208208
}))
209209
})

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
@@ -50,6 +50,14 @@ pub struct Crate {
5050
pub max_upload_size: Option<i32>,
5151
}
5252

53+
/// The highest version (in semver order) and the most recently updated version
54+
/// for a single crate.
55+
#[derive(Debug, Clone)]
56+
pub struct TopVersions {
57+
pub highest: String,
58+
pub newest: String,
59+
}
60+
5361
/// We literally never want to select `textsearchable_index_col`
5462
/// so we provide this type and constant to pass to `.select`
5563
type AllColumns = (
@@ -206,7 +214,7 @@ impl<'a> NewCrate<'a> {
206214
}
207215

208216
impl Crate {
209-
/// SQL filter based on whether the crate's name loosly matches the given
217+
/// SQL filter based on whether the crate's name loosely matches the given
210218
/// string.
211219
///
212220
/// The operator used varies based on the input.
@@ -283,13 +291,16 @@ impl Crate {
283291

284292
pub fn minimal_encodable(
285293
self,
286-
max_version: &semver::Version,
294+
max_version: &str,
287295
badges: Option<Vec<Badge>>,
288296
exact_match: bool,
289297
recent_downloads: Option<i64>,
290298
) -> EncodableCrate {
291299
self.encodable(
292-
max_version,
300+
&TopVersions {
301+
highest: max_version.to_owned(),
302+
newest: max_version.to_owned(),
303+
},
293304
None,
294305
None,
295306
None,
@@ -302,7 +313,7 @@ impl Crate {
302313
#[allow(clippy::too_many_arguments)]
303314
pub fn encodable(
304315
self,
305-
max_version: &semver::Version,
316+
top_versions: &TopVersions,
306317
versions: Option<Vec<i32>>,
307318
keywords: Option<&[Keyword]>,
308319
categories: Option<&[Category]>,
@@ -341,8 +352,8 @@ impl Crate {
341352
keywords: keyword_ids,
342353
categories: category_ids,
343354
badges,
344-
max_version: max_version.to_string(),
345-
newest_version: max_version.to_string(), // FIXME: Make this the newest, not the highest
355+
max_version: top_versions.highest.to_owned(),
356+
newest_version: top_versions.newest.to_owned(),
346357
documentation,
347358
homepage,
348359
exact_match,
@@ -387,16 +398,28 @@ impl Crate {
387398
}
388399
}
389400

390-
pub fn max_version(&self, conn: &PgConnection) -> AppResult<semver::Version> {
401+
pub fn top_versions(&self, conn: &PgConnection) -> AppResult<TopVersions> {
391402
use crate::schema::versions::dsl::*;
392403

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

402425
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
@@ -303,7 +303,7 @@ impl TestAppBuilder {
303303
}
304304
}
305305

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

0 commit comments

Comments
 (0)