Skip to content

Commit caf043c

Browse files
committed
controllers/krate/search: Expose the default_version field
1 parent 594c7cb commit caf043c

File tree

2 files changed

+58
-14
lines changed

2 files changed

+58
-14
lines changed

src/controllers/krate/search.rs

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,16 @@ pub async fn search(app: AppState, req: Parts) -> AppResult<Json<Value>> {
8787
crate_downloads::downloads,
8888
recent_crate_downloads::downloads.nullable(),
8989
0_f32.into_sql::<Float>(),
90+
versions::num.nullable(),
9091
);
9192

9293
let mut seek: Option<Seek> = None;
9394
let mut query = filter_params
9495
.make_query(&req, conn)?
9596
.inner_join(crate_downloads::table)
9697
.left_join(recent_crate_downloads::table)
98+
.left_join(default_versions::table)
99+
.left_join(versions::table.on(default_versions::version_id.eq(versions::id)))
97100
.select(selection);
98101

99102
if let Some(q_string) = &filter_params.q_string {
@@ -113,6 +116,7 @@ pub async fn search(app: AppState, req: Parts) -> AppResult<Json<Value>> {
113116
crate_downloads::downloads,
114117
recent_crate_downloads::downloads.nullable(),
115118
rank.clone(),
119+
versions::num.nullable(),
116120
));
117121
seek = Some(Seek::Relevance);
118122
query = query.then_order_by(rank.desc())
@@ -123,6 +127,7 @@ pub async fn search(app: AppState, req: Parts) -> AppResult<Json<Value>> {
123127
crate_downloads::downloads,
124128
recent_crate_downloads::downloads.nullable(),
125129
0_f32.into_sql::<Float>(),
130+
versions::num.nullable(),
126131
));
127132
seek = Some(Seek::Query);
128133
}
@@ -225,17 +230,19 @@ pub async fn search(app: AppState, req: Parts) -> AppResult<Json<Value>> {
225230

226231
let crates = versions
227232
.zip(data)
228-
.map(|(max_version, (krate, perfect_match, total, recent, _))| {
229-
EncodableCrate::from_minimal(
230-
krate,
231-
None,
232-
Some(&max_version),
233-
Some(vec![]),
234-
perfect_match,
235-
total,
236-
Some(recent.unwrap_or(0)),
237-
)
238-
})
233+
.map(
234+
|(max_version, (krate, perfect_match, total, recent, _, default_version))| {
235+
EncodableCrate::from_minimal(
236+
krate,
237+
default_version.as_deref(),
238+
Some(&max_version),
239+
Some(vec![]),
240+
perfect_match,
241+
total,
242+
Some(recent.unwrap_or(0)),
243+
)
244+
},
245+
)
239246
.collect::<Vec<_>>();
240247

241248
Ok(Json(json!({
@@ -615,6 +622,7 @@ mod seek {
615622
downloads,
616623
recent_downloads,
617624
rank,
625+
_,
618626
) = *record;
619627

620628
match *self {
@@ -637,11 +645,18 @@ mod seek {
637645
}
638646
}
639647

640-
type Record = (Crate, bool, i64, Option<i64>, f32);
648+
type Record = (Crate, bool, i64, Option<i64>, f32, Option<String>);
641649

642650
type QuerySource = LeftJoinQuerySource<
643-
InnerJoinQuerySource<crates::table, crate_downloads::table>,
644-
recent_crate_downloads::table,
651+
LeftJoinQuerySource<
652+
LeftJoinQuerySource<
653+
InnerJoinQuerySource<crates::table, crate_downloads::table>,
654+
recent_crate_downloads::table,
655+
>,
656+
default_versions::table,
657+
>,
658+
versions::table,
659+
diesel::dsl::Eq<default_versions::version_id, versions::id>,
645660
>;
646661

647662
type BoxedCondition<'a> = Box<

src/tests/routes/crates/list.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,12 @@ async fn index_include_yanked() {
713713
assert_eq!(json.crates[1].name, "newest_yanked");
714714
assert_eq!(json.crates[2].name, "oldest_yanked");
715715
assert_eq!(json.crates[3].name, "unyanked");
716+
assert_eq!(
717+
default_versions_iter(&json.crates)
718+
.flatten()
719+
.collect::<Vec<_>>(),
720+
["2.0.0", "1.0.0", "2.0.0", "2.0.0",]
721+
);
716722
}
717723

718724
// Do not include fully yanked (all versions were yanked) crates
@@ -721,6 +727,12 @@ async fn index_include_yanked() {
721727
assert_eq!(json.crates[0].name, "newest_yanked");
722728
assert_eq!(json.crates[1].name, "oldest_yanked");
723729
assert_eq!(json.crates[2].name, "unyanked");
730+
assert_eq!(
731+
default_versions_iter(&json.crates)
732+
.flatten()
733+
.collect::<Vec<_>>(),
734+
["1.0.0", "2.0.0", "2.0.0",]
735+
);
724736
}
725737
}
726738

@@ -738,6 +750,7 @@ async fn yanked_versions_are_not_considered_for_max_version() {
738750

739751
for json in search_both(&anon, "q=foo").await {
740752
assert_eq!(json.meta.total, 1);
753+
assert_eq!(json.crates[0].default_version, Some("1.0.0".into()));
741754
assert_eq!(json.crates[0].max_version, "1.0.0");
742755
}
743756
}
@@ -759,6 +772,7 @@ async fn max_stable_version() {
759772

760773
for json in search_both(&anon, "q=foo").await {
761774
assert_eq!(json.meta.total, 1);
775+
assert_eq!(json.crates[0].default_version, Some("1.0.0".into()));
762776
assert_eq!(json.crates[0].max_stable_version, Some("1.0.0".to_string()));
763777
}
764778
}
@@ -929,6 +943,9 @@ async fn pagination_links_included_if_applicable() {
929943
.iter()
930944
.all(|w| *w == 3));
931945
assert_eq!(page4.meta.total, 0);
946+
for p in [page1, page2, page3, page4] {
947+
assert!(default_versions_iter(&p.crates).all(Option::is_some));
948+
}
932949
}
933950

934951
#[tokio::test(flavor = "multi_thread")]
@@ -960,6 +977,7 @@ async fn seek_based_pagination() {
960977
assert_that!(resp.crates, len(eq(1)));
961978
url = Some(new_url);
962979
assert_eq!(resp.meta.total, 3);
980+
assert!(default_versions_iter(&resp.crates).all(Option::is_some));
963981
} else {
964982
assert_that!(resp.crates, empty());
965983
assert_eq!(resp.meta.total, 0);
@@ -993,11 +1011,13 @@ async fn test_pages_work_even_with_seek_based_pagination() {
9931011
let first = anon.search("per_page=1").await;
9941012
assert!(first.meta.next_page.unwrap().contains("seek="));
9951013
assert_eq!(first.meta.total, 3);
1014+
assert!(default_versions_iter(&first.crates).all(Option::is_some));
9961015

9971016
// Calling with page=2 will revert to offset-based pagination
9981017
let second = anon.search("page=2&per_page=1").await;
9991018
assert!(second.meta.next_page.unwrap().contains("page=3"));
10001019
assert_eq!(second.meta.total, 3);
1020+
assert!(default_versions_iter(&second.crates).all(Option::is_some));
10011021
}
10021022

10031023
#[tokio::test(flavor = "multi_thread")]
@@ -1096,6 +1116,8 @@ async fn search_both<U: RequestHelper>(anon: &U, query: &str) -> [crate::tests::
10961116
.as_deref()
10971117
.unwrap_or("seek=")
10981118
.contains("seek="));
1119+
assert!(default_versions_iter(&offset.crates).all(Option::is_some));
1120+
assert!(default_versions_iter(&seek.crates).all(Option::is_some));
10991121
[offset, seek]
11001122
}
11011123

@@ -1126,6 +1148,7 @@ async fn page_with_seek<U: RequestHelper>(
11261148
assert_that!(resp.crates, len(eq(1)));
11271149
url = Some(new_url.to_owned());
11281150
assert_ne!(resp.meta.total, 0);
1151+
assert!(default_versions_iter(&resp.crates).all(Option::is_some));
11291152
} else {
11301153
assert_that!(resp.crates, empty());
11311154
assert_eq!(resp.meta.total, 0);
@@ -1134,3 +1157,9 @@ async fn page_with_seek<U: RequestHelper>(
11341157
}
11351158
(results, calls)
11361159
}
1160+
1161+
fn default_versions_iter(
1162+
crates: &[crate::tests::EncodableCrate],
1163+
) -> impl Iterator<Item = &Option<String>> {
1164+
crates.iter().map(|c| &c.default_version)
1165+
}

0 commit comments

Comments
 (0)