Skip to content

Commit a93598f

Browse files
committed
Expose num_versions column on the API
1 parent 15133c4 commit a93598f

File tree

29 files changed

+66
-18
lines changed

29 files changed

+66
-18
lines changed

src/controllers/krate/metadata.rs

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -75,21 +75,27 @@ pub async fn find_crate(
7575
.transpose()?
7676
.unwrap_or_default();
7777

78-
let (krate, downloads, default_version, yanked): (Crate, i64, Option<String>, Option<bool>) =
79-
Crate::by_name(&path.name)
80-
.inner_join(crate_downloads::table)
81-
.left_join(default_versions::table)
82-
.left_join(versions::table.on(default_versions::version_id.eq(versions::id)))
83-
.select((
84-
Crate::as_select(),
85-
crate_downloads::downloads,
86-
versions::num.nullable(),
87-
versions::yanked.nullable(),
88-
))
89-
.first(&mut conn)
90-
.await
91-
.optional()?
92-
.ok_or_else(|| crate_not_found(&path.name))?;
78+
let (krate, downloads, default_version, yanked, num_versions): (
79+
Crate,
80+
i64,
81+
Option<String>,
82+
Option<bool>,
83+
Option<i32>,
84+
) = Crate::by_name(&path.name)
85+
.inner_join(crate_downloads::table)
86+
.left_join(default_versions::table)
87+
.left_join(versions::table.on(default_versions::version_id.eq(versions::id)))
88+
.select((
89+
Crate::as_select(),
90+
crate_downloads::downloads,
91+
versions::num.nullable(),
92+
versions::yanked.nullable(),
93+
default_versions::num_versions.nullable(),
94+
))
95+
.first(&mut conn)
96+
.await
97+
.optional()?
98+
.ok_or_else(|| crate_not_found(&path.name))?;
9399

94100
let mut versions_publishers_and_audit_actions = if include.versions {
95101
let versions_and_publishers: Vec<(Version, Option<User>)> = Version::belonging_to(&krate)
@@ -183,6 +189,7 @@ pub async fn find_crate(
183189
let encodable_crate = EncodableCrate::from(
184190
krate.clone(),
185191
default_version.as_deref(),
192+
num_versions.unwrap_or_default(),
186193
yanked,
187194
top_versions.as_ref(),
188195
ids,

src/controllers/krate/publish.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -436,11 +436,12 @@ pub async fn publish(app: AppState, req: Parts, body: Body) -> AppResult<Json<Go
436436
let existing_default_version = default_versions::table
437437
.inner_join(versions::table)
438438
.filter(default_versions::crate_id.eq(krate.id))
439-
.select(DefaultVersion::as_select())
440-
.first(conn)
439+
.select((DefaultVersion::as_select(), default_versions::num_versions))
440+
.first::<(DefaultVersion, Option<i32>)>(conn)
441441
.await
442442
.optional()?;
443443

444+
let num_versions = existing_default_version.as_ref().and_then(|t|t.1).unwrap_or_default();
444445
let mut default_version = None;
445446
// Upsert the `default_value` determined by the existing `default_value` and the
446447
// published version. Note that this could potentially write an outdated version
@@ -450,7 +451,7 @@ pub async fn publish(app: AppState, req: Parts, body: Body) -> AppResult<Json<Go
450451
// Compared to only using a background job, this prevents us from getting into a
451452
// situation where a crate exists in the `crates` table but doesn't have a default
452453
// version in the `default_versions` table.
453-
if let Some(existing_default_version) = existing_default_version {
454+
if let Some((existing_default_version, _)) = existing_default_version {
454455
let published_default_version = DefaultVersion {
455456
id: version.id,
456457
num: semver,
@@ -562,6 +563,7 @@ pub async fn publish(app: AppState, req: Parts, body: Body) -> AppResult<Json<Go
562563
krate: EncodableCrate::from_minimal(
563564
krate,
564565
default_version.or(Some(version_string)).as_deref(),
566+
num_versions,
565567
Some(false),
566568
Some(&top_versions),
567569
false,

src/controllers/krate/search.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ pub async fn list_crates(
8282
0_f32.into_sql::<Float>(),
8383
versions::num.nullable(),
8484
versions::yanked.nullable(),
85+
default_versions::num_versions.nullable(),
8586
);
8687

8788
let mut seek: Option<Seek> = None;
@@ -113,6 +114,7 @@ pub async fn list_crates(
113114
rank,
114115
versions::num.nullable(),
115116
versions::yanked.nullable(),
117+
default_versions::num_versions.nullable(),
116118
));
117119
seek = Some(Seek::Relevance);
118120
query = query.then_order_by(rank.desc())
@@ -125,6 +127,7 @@ pub async fn list_crates(
125127
0_f32.into_sql::<Float>(),
126128
versions::num.nullable(),
127129
versions::yanked.nullable(),
130+
default_versions::num_versions.nullable(),
128131
));
129132
seek = Some(Seek::Query);
130133
}
@@ -227,6 +230,7 @@ pub async fn list_crates(
227230
EncodableCrate::from_minimal(
228231
record.krate,
229232
record.default_version.as_deref(),
233+
record.num_versions.unwrap_or_default(),
230234
record.yanked,
231235
Some(&max_version),
232236
record.exact_match,
@@ -704,6 +708,7 @@ struct Record {
704708
rank: f32,
705709
default_version: Option<String>,
706710
yanked: Option<bool>,
711+
num_versions: Option<i32>,
707712
}
708713

709714
type QuerySource = LeftJoinQuerySource<

src/controllers/summary.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ struct Record {
135135
default_version: Option<String>,
136136
#[diesel(select_expression = versions::columns::yanked.nullable())]
137137
yanked: Option<bool>,
138+
#[diesel(select_expression = default_versions::columns::num_versions.nullable())]
139+
num_versions: Option<i32>,
138140
}
139141

140142
fn encode_crates(
@@ -165,6 +167,7 @@ fn encode_crates(
165167
Ok(EncodableCrate::from_minimal(
166168
record.krate,
167169
record.default_version.as_deref(),
170+
record.num_versions.unwrap_or_default(),
168171
record.yanked,
169172
Some(&top_versions),
170173
false,

src/tests/krate/publish/snapshots/crates_io__tests__krate__publish__basics__new_krate.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ expression: response.json()
2727
"max_version": "1.0.0",
2828
"name": "foo_new",
2929
"newest_version": "1.0.0",
30+
"num_versions": 1,
3031
"recent_downloads": null,
3132
"repository": null,
3233
"updated_at": "[datetime]",

src/tests/krate/publish/snapshots/crates_io__tests__krate__publish__basics__new_krate_twice.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ expression: response.json()
2727
"max_version": "2.0.0",
2828
"name": "foo_twice",
2929
"newest_version": "2.0.0",
30+
"num_versions": 2,
3031
"recent_downloads": null,
3132
"repository": null,
3233
"updated_at": "[datetime]",

src/tests/krate/publish/snapshots/crates_io__tests__krate__publish__basics__new_krate_twice_alt.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ expression: response.json()
2727
"max_version": "2.0.0",
2828
"name": "foo_twice",
2929
"newest_version": "0.99.0",
30+
"num_versions": 2,
3031
"recent_downloads": null,
3132
"repository": null,
3233
"updated_at": "[datetime]",

src/tests/krate/publish/snapshots/crates_io__tests__krate__publish__basics__new_krate_weird_version.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ expression: response.json()
2727
"max_version": "0.0.0-pre",
2828
"name": "foo_weird",
2929
"newest_version": "0.0.0-pre",
30+
"num_versions": 1,
3031
"recent_downloads": null,
3132
"repository": null,
3233
"updated_at": "[datetime]",

src/tests/krate/publish/snapshots/crates_io__tests__krate__publish__basics__new_krate_with_token.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ expression: response.json()
2727
"max_version": "1.0.0",
2828
"name": "foo_new",
2929
"newest_version": "1.0.0",
30+
"num_versions": 1,
3031
"recent_downloads": null,
3132
"repository": null,
3233
"updated_at": "[datetime]",

src/tests/krate/publish/snapshots/crates_io__tests__krate__publish__build_metadata__version_with_build_metadata@build_metadata_1.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ expression: response.json()
2727
"max_version": "1.0.0+foo",
2828
"name": "foo",
2929
"newest_version": "1.0.0+foo",
30+
"num_versions": 1,
3031
"recent_downloads": null,
3132
"repository": null,
3233
"updated_at": "[datetime]",

src/tests/krate/publish/snapshots/crates_io__tests__krate__publish__build_metadata__version_with_build_metadata@build_metadata_2.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ expression: response.json()
2727
"max_version": "1.0.0-beta.1",
2828
"name": "foo",
2929
"newest_version": "1.0.0-beta.1",
30+
"num_versions": 1,
3031
"recent_downloads": null,
3132
"repository": null,
3233
"updated_at": "[datetime]",

src/tests/krate/publish/snapshots/crates_io__tests__krate__publish__build_metadata__version_with_build_metadata@build_metadata_3.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ expression: response.json()
2727
"max_version": "1.0.0+foo",
2828
"name": "foo",
2929
"newest_version": "1.0.0+foo",
30+
"num_versions": 1,
3031
"recent_downloads": null,
3132
"repository": null,
3233
"updated_at": "[datetime]",

src/tests/krate/publish/snapshots/crates_io__tests__krate__publish__categories__good_categories.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ expression: response.json()
2727
"max_version": "1.0.0",
2828
"name": "foo_good_cat",
2929
"newest_version": "1.0.0",
30+
"num_versions": 1,
3031
"recent_downloads": null,
3132
"repository": null,
3233
"updated_at": "[datetime]",

src/tests/krate/publish/snapshots/crates_io__tests__krate__publish__dependencies__dep_limit-2.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ expression: response.json()
2727
"max_version": "1.0.0",
2828
"name": "foo",
2929
"newest_version": "1.0.0",
30+
"num_versions": 1,
3031
"recent_downloads": null,
3132
"repository": null,
3233
"updated_at": "[datetime]",

src/tests/krate/publish/snapshots/crates_io__tests__krate__publish__edition__edition_is_saved.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ expression: response.json()
2727
"max_version": "1.0.0",
2828
"name": "foo",
2929
"newest_version": "1.0.0",
30+
"num_versions": 1,
3031
"recent_downloads": null,
3132
"repository": null,
3233
"updated_at": "[datetime]",

src/tests/krate/publish/snapshots/crates_io__tests__krate__publish__keywords__good_keywords.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ expression: response.json()
2727
"max_version": "1.0.0",
2828
"name": "foo_good_key",
2929
"newest_version": "1.0.0",
30+
"num_versions": 1,
3031
"recent_downloads": null,
3132
"repository": null,
3233
"updated_at": "[datetime]",

src/tests/krate/publish/snapshots/crates_io__tests__krate__publish__links__crate_with_links_field.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ expression: response.json()
2727
"max_version": "1.0.0",
2828
"name": "foo",
2929
"newest_version": "1.0.0",
30+
"num_versions": 1,
3031
"recent_downloads": null,
3132
"repository": null,
3233
"updated_at": "[datetime]",

src/tests/krate/publish/snapshots/crates_io__tests__krate__publish__manifest__boolean_readme.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ expression: response.json()
2727
"max_version": "1.0.0",
2828
"name": "foo",
2929
"newest_version": "1.0.0",
30+
"num_versions": 1,
3031
"recent_downloads": null,
3132
"repository": null,
3233
"updated_at": "[datetime]",

src/tests/krate/publish/snapshots/crates_io__tests__krate__publish__manifest__lib_and_bin_crate.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ expression: response.json()
2727
"max_version": "1.0.0",
2828
"name": "foo",
2929
"newest_version": "1.0.0",
30+
"num_versions": 1,
3031
"recent_downloads": null,
3132
"repository": null,
3233
"updated_at": "[datetime]",

src/tests/krate/publish/snapshots/crates_io__tests__krate__publish__max_size__tarball_between_default_axum_limit_and_max_upload_size.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ expression: response.json()
2727
"max_version": "1.1.0",
2828
"name": "foo",
2929
"newest_version": "1.1.0",
30+
"num_versions": 1,
3031
"recent_downloads": null,
3132
"repository": null,
3233
"updated_at": "[datetime]",

src/tests/krate/publish/snapshots/crates_io__tests__krate__publish__readme__new_krate_with_empty_readme.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ expression: response.json()
2727
"max_version": "1.0.0",
2828
"name": "foo_readme",
2929
"newest_version": "1.0.0",
30+
"num_versions": 1,
3031
"recent_downloads": null,
3132
"repository": null,
3233
"updated_at": "[datetime]",

src/tests/krate/publish/snapshots/crates_io__tests__krate__publish__readme__new_krate_with_readme.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ expression: response.json()
2727
"max_version": "1.0.0",
2828
"name": "foo_readme",
2929
"newest_version": "1.0.0",
30+
"num_versions": 1,
3031
"recent_downloads": null,
3132
"repository": null,
3233
"updated_at": "[datetime]",

src/tests/krate/publish/snapshots/crates_io__tests__krate__publish__readme__new_krate_with_readme_and_plus_version.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ expression: response.json()
2727
"max_version": "1.0.0+foo",
2828
"name": "foo_readme",
2929
"newest_version": "1.0.0+foo",
30+
"num_versions": 1,
3031
"recent_downloads": null,
3132
"repository": null,
3233
"updated_at": "[datetime]",

src/tests/routes/crates/snapshots/crates_io__tests__routes__crates__read__include_default_version.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ expression: response.json()
2828
"max_version": "0.0.0",
2929
"name": "foo_default_version",
3030
"newest_version": "0.0.0",
31+
"num_versions": 3,
3132
"recent_downloads": null,
3233
"repository": null,
3334
"updated_at": "[datetime]",

src/tests/routes/crates/snapshots/crates_io__tests__routes__crates__read__new_name.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ expression: response.json()
2828
"max_version": "0.0.0",
2929
"name": "new",
3030
"newest_version": "0.0.0",
31+
"num_versions": 1,
3132
"recent_downloads": null,
3233
"repository": null,
3334
"updated_at": "[datetime]",

src/tests/routes/crates/snapshots/crates_io__tests__routes__crates__read__show.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ expression: response.json()
3030
"max_version": "1.0.0",
3131
"name": "foo_show",
3232
"newest_version": "0.5.1",
33+
"num_versions": 3,
3334
"recent_downloads": 10,
3435
"repository": null,
3536
"updated_at": "[datetime]",

src/tests/routes/crates/snapshots/crates_io__tests__routes__crates__read__show_all_yanked.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ expression: response.json()
3030
"max_version": "0.0.0",
3131
"name": "foo_show",
3232
"newest_version": "0.0.0",
33+
"num_versions": 2,
3334
"recent_downloads": 10,
3435
"repository": null,
3536
"updated_at": "[datetime]",

src/tests/routes/crates/snapshots/crates_io__tests__routes__crates__read__show_minimal.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ expression: response.json()
2828
"max_version": "0.0.0",
2929
"name": "foo_show_minimal",
3030
"newest_version": "0.0.0",
31+
"num_versions": 3,
3132
"recent_downloads": null,
3233
"repository": null,
3334
"updated_at": "[datetime]",

src/views.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ pub struct EncodableCrate {
207207
pub downloads: i64,
208208
pub recent_downloads: Option<i64>,
209209
pub default_version: Option<String>,
210+
pub num_versions: i32,
210211
pub yanked: bool,
211212
// NOTE: Used by shields.io, altering `max_version` requires a PR with shields.io
212213
pub max_version: String,
@@ -225,6 +226,7 @@ impl EncodableCrate {
225226
pub fn from(
226227
krate: Crate,
227228
default_version: Option<&str>,
229+
num_versions: i32,
228230
yanked: Option<bool>,
229231
top_versions: Option<&TopVersions>,
230232
versions: Option<Vec<i32>>,
@@ -297,6 +299,7 @@ impl EncodableCrate {
297299
categories: category_ids,
298300
badges: [],
299301
default_version,
302+
num_versions,
300303
yanked,
301304
max_version,
302305
newest_version,
@@ -317,9 +320,11 @@ impl EncodableCrate {
317320
}
318321
}
319322

323+
#[allow(clippy::too_many_arguments)]
320324
pub fn from_minimal(
321325
krate: Crate,
322326
default_version: Option<&str>,
327+
num_versions: i32,
323328
yanked: Option<bool>,
324329
top_versions: Option<&TopVersions>,
325330
exact_match: bool,
@@ -329,6 +334,7 @@ impl EncodableCrate {
329334
Self::from(
330335
krate,
331336
default_version,
337+
num_versions,
332338
yanked,
333339
top_versions,
334340
None,
@@ -823,6 +829,7 @@ mod tests {
823829
downloads: 0,
824830
recent_downloads: None,
825831
default_version: None,
832+
num_versions: 0,
826833
yanked: false,
827834
max_version: "".to_string(),
828835
newest_version: "".to_string(),

0 commit comments

Comments
 (0)