@@ -442,6 +442,8 @@ pub(crate) async fn crate_details_handler(
442442struct ReleaseList {
443443 releases : Vec < Release > ,
444444 crate_name : String ,
445+ inner_path : String ,
446+ target : String ,
445447}
446448
447449impl_axum_webpage ! {
@@ -452,28 +454,74 @@ impl_axum_webpage! {
452454
453455#[ tracing:: instrument]
454456pub ( crate ) async fn get_all_releases (
455- Path ( params) : Path < CrateDetailHandlerParams > ,
457+ Path ( params) : Path < RustdocHtmlParams > ,
456458 mut conn : DbConnection ,
457459) -> AxumResult < AxumResponse > {
458- let crate_id = sqlx:: query_scalar!(
460+ let req_path: String = params. path . clone ( ) . unwrap_or_default ( ) ;
461+ let req_path: Vec < & str > = req_path. split ( '/' ) . collect ( ) ;
462+
463+ let release_found = match_version ( & mut conn, & params. name , Some ( & params. version ) ) . await ?;
464+ trace ! ( ?release_found, "found release" ) ;
465+
466+ let ( version, _) = match release_found. version {
467+ MatchSemver :: Exact ( ( version, _) ) => ( version. clone ( ) , version) ,
468+ MatchSemver :: Latest ( ( version, _) ) => ( version, "latest" . to_string ( ) ) ,
469+ MatchSemver :: Semver ( _) => return Err ( AxumNope :: VersionNotFound ) ,
470+ } ;
471+
472+ let row = sqlx:: query!(
459473 "SELECT
460- crates.id AS crate_id
474+ crates.id AS crate_id,
475+ releases.doc_targets
461476 FROM crates
462- WHERE crates.name = $1;" ,
477+ INNER JOIN releases on crates.id = releases.crate_id
478+ WHERE crates.name = $1 and releases.version = $2;" ,
463479 params. name,
480+ & version,
464481 )
465482 . fetch_optional ( & mut * conn)
466- . await ?;
483+ . await ?
484+ . ok_or ( AxumNope :: CrateNotFound ) ?;
467485
468- let releases: Vec < Release > = if let Some ( crate_id) = crate_id {
469- // get releases, sorted by semver
470- releases_for_crate ( & mut conn, crate_id) . await ?
486+ // get releases, sorted by semver
487+ let releases: Vec < Release > = releases_for_crate ( & mut conn, row. crate_id ) . await ?;
488+
489+ let doc_targets = MetaData :: parse_doc_targets ( row. doc_targets ) ;
490+
491+ let inner;
492+ let ( target, inner_path) = {
493+ let mut inner_path = req_path. clone ( ) ;
494+
495+ let target = if inner_path. len ( ) > 1
496+ && doc_targets
497+ . iter ( )
498+ . any ( |s| Some ( s) == params. target . as_ref ( ) )
499+ {
500+ inner_path. remove ( 0 ) ;
501+ params. target . as_ref ( ) . unwrap ( )
502+ } else {
503+ ""
504+ } ;
505+
506+ inner = inner_path. join ( "/" ) ;
507+ ( target, inner. trim_end_matches ( '/' ) )
508+ } ;
509+ let inner_path = if inner_path. is_empty ( ) {
510+ format ! ( "{}/index.html" , params. name)
471511 } else {
472- Vec :: new ( )
512+ format ! ( "{}/{inner_path}" , params. name)
513+ } ;
514+
515+ let target = if target. is_empty ( ) {
516+ String :: new ( )
517+ } else {
518+ format ! ( "{target}/" )
473519 } ;
474520
475521 let res = ReleaseList {
476522 releases,
523+ target : target. to_string ( ) ,
524+ inner_path,
477525 crate_name : params. name ,
478526 } ;
479527 Ok ( res. into_response ( ) )
0 commit comments