Skip to content

Commit c0e6171

Browse files
committed
support /latest/ and others in build-details handler for consistency
1 parent cf22519 commit c0e6171

File tree

3 files changed

+106
-19
lines changed

3 files changed

+106
-19
lines changed

.sqlx/query-61e8789f7d2ddcfa951dc86c5f455cf4451f8f3b683c6bd1033e8ebaab97692e.json

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Justfile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@ sqlx-prepare ADDITIONAL_ARGS="":
1111
sqlx-check:
1212
just sqlx-prepare "--check"
1313

14-
lint:
15-
cargo clippy --all-features --all-targets --workspace --locked -- -D warnings
14+
lint *args:
15+
cargo clippy --all-features --all-targets --workspace --locked {{ args }} -- -D warnings
16+
17+
lint-fix:
18+
just lint --fix --allow-dirty --allow-staged
1619

1720
lint-js *args:
1821
deno run -A npm:eslint@9 static templates gui-tests eslint.config.js {{ args }}

src/web/build_details.rs

Lines changed: 79 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
use crate::{
22
AsyncStorage, Config,
3-
db::{
4-
BuildId,
5-
types::{BuildStatus, version::Version},
6-
},
3+
db::{BuildId, types::BuildStatus},
74
impl_axum_webpage,
85
web::{
96
MetaData,
7+
cache::CachePolicy,
108
error::{AxumNope, AxumResult},
119
extractors::{DbConnection, Path, rustdoc::RustdocParams},
1210
file::File,
13-
filters,
11+
filters, match_version,
1412
page::templates::{RenderBrands, RenderRegular, RenderSolid},
1513
},
1614
};
@@ -55,24 +53,37 @@ impl BuildDetailsPage {
5553

5654
#[derive(Clone, Deserialize, Debug)]
5755
pub(crate) struct BuildDetailsParams {
58-
pub(crate) name: String,
59-
pub(crate) version: Version,
6056
pub(crate) id: String,
6157
pub(crate) filename: Option<String>,
6258
}
6359

6460
pub(crate) async fn build_details_handler(
65-
Path(params): Path<BuildDetailsParams>,
61+
params: RustdocParams,
62+
Path(build_params): Path<BuildDetailsParams>,
6663
mut conn: DbConnection,
6764
Extension(config): Extension<Arc<Config>>,
6865
Extension(storage): Extension<Arc<AsyncStorage>>,
6966
) -> AxumResult<impl IntoResponse> {
70-
let id = params
67+
let id = build_params
7168
.id
7269
.parse()
7370
.map(BuildId)
7471
.map_err(|_| AxumNope::BuildNotFound)?;
7572

73+
let version = match_version(&mut conn, params.name(), params.req_version())
74+
.await?
75+
.assume_exact_name()?
76+
.into_canonical_req_version_or_else(|version| {
77+
AxumNope::Redirect(
78+
params
79+
.clone()
80+
.with_req_version(version)
81+
.build_details_url(id, build_params.filename.as_deref()),
82+
CachePolicy::ForeverInCdn,
83+
)
84+
})?
85+
.into_version();
86+
7687
let row = sqlx::query!(
7788
r#"SELECT
7889
builds.rustc_version,
@@ -87,8 +98,8 @@ pub(crate) async fn build_details_handler(
8798
INNER JOIN crates ON releases.crate_id = crates.id
8899
WHERE builds.id = $1 AND crates.name = $2 AND releases.version = $3"#,
89100
id.0,
90-
params.name,
91-
params.version.to_string(),
101+
params.name(),
102+
version as _
92103
)
93104
.fetch_optional(&mut *conn)
94105
.await?
@@ -114,7 +125,7 @@ pub(crate) async fn build_details_handler(
114125
.try_collect()
115126
.await?;
116127

117-
let current_filename = if let Some(filename) = params.filename {
128+
let current_filename = if let Some(filename) = build_params.filename {
118129
// if we have a given filename in the URL, we use that one.
119130
Some(filename)
120131
} else if let Some(default_target) = row.default_target {
@@ -144,8 +155,14 @@ pub(crate) async fn build_details_handler(
144155
(file_content, all_log_filenames, current_filename)
145156
};
146157

147-
let metadata = MetaData::from_crate(&mut conn, &params.name, &params.version, None).await?;
148-
let params = RustdocParams::from_metadata(&metadata);
158+
let metadata = MetaData::from_crate(
159+
&mut conn,
160+
params.name(),
161+
&version,
162+
Some(params.req_version().clone()),
163+
)
164+
.await?;
165+
let params = params.apply_metadata(&metadata);
149166

150167
Ok(BuildDetailsPage {
151168
metadata,
@@ -167,9 +184,12 @@ pub(crate) async fn build_details_handler(
167184

168185
#[cfg(test)]
169186
mod tests {
170-
use crate::test::{
171-
AxumResponseTestExt, AxumRouterTestExt, FakeBuild, async_wrapper,
172-
fake_release_that_failed_before_build,
187+
use crate::{
188+
db::types::{BuildId, ReleaseId},
189+
test::{
190+
AxumResponseTestExt, AxumRouterTestExt, FakeBuild, TestEnvironment, V0_1,
191+
async_wrapper, fake_release_that_failed_before_build,
192+
},
173193
};
174194
use kuchikiki::traits::TendrilSink;
175195
use test_case::test_case;
@@ -187,6 +207,22 @@ mod tests {
187207
.collect()
188208
}
189209

210+
async fn build_ids_for_release(
211+
conn: &mut sqlx::PgConnection,
212+
release_id: ReleaseId,
213+
) -> Vec<BuildId> {
214+
sqlx::query!(
215+
"SELECT id FROM builds WHERE rid = $1 ORDER BY id ASC",
216+
release_id as _
217+
)
218+
.fetch_all(conn)
219+
.await
220+
.unwrap()
221+
.into_iter()
222+
.map(|row| BuildId(row.id))
223+
.collect()
224+
}
225+
190226
#[test]
191227
fn test_partial_build_result() {
192228
async_wrapper(|env| async move {
@@ -475,4 +511,30 @@ mod tests {
475511
Ok(())
476512
});
477513
}
514+
515+
#[tokio::test(flavor = "multi_thread")]
516+
async fn build_detail_via_latest() -> anyhow::Result<()> {
517+
let env = TestEnvironment::new().await?;
518+
let rid = env
519+
.fake_release()
520+
.await
521+
.name("foo")
522+
.version(V0_1)
523+
.create()
524+
.await?;
525+
526+
let mut conn = env.async_db().async_conn().await;
527+
let build_id = {
528+
let ids = build_ids_for_release(&mut conn, rid).await;
529+
assert_eq!(ids.len(), 1);
530+
ids[0]
531+
};
532+
533+
env.web_app()
534+
.await
535+
.assert_success(&format!("/crate/foo/latest/builds/{build_id}"))
536+
.await?;
537+
538+
Ok(())
539+
}
478540
}

0 commit comments

Comments
 (0)