@@ -454,6 +454,8 @@ pub(crate) async fn crate_details_handler(
454454struct ReleaseList {
455455 releases : Vec < Release > ,
456456 crate_name : String ,
457+ inner_path : String ,
458+ target : String ,
457459}
458460
459461impl_axum_webpage ! {
@@ -464,35 +466,85 @@ impl_axum_webpage! {
464466
465467#[ tracing:: instrument]
466468pub ( crate ) async fn get_all_releases (
467- Path ( params) : Path < CrateDetailHandlerParams > ,
469+ Path ( params) : Path < RustdocHtmlParams > ,
468470 Extension ( pool) : Extension < Pool > ,
469471) -> AxumResult < AxumResponse > {
470- let releases: Vec < Release > = spawn_blocking ( {
472+ let req_path: String = params. path . clone ( ) . unwrap_or_default ( ) ;
473+ let req_path: Vec < & str > = req_path. split ( '/' ) . collect ( ) ;
474+
475+ let release_found = match_version_axum ( & pool, & params. name , Some ( & params. version ) ) . await ?;
476+ trace ! ( ?release_found, "found release" ) ;
477+
478+ let ( version, _) = match release_found. version {
479+ MatchSemver :: Exact ( ( version, _) ) => ( version. clone ( ) , version) ,
480+ MatchSemver :: Latest ( ( version, _) ) => ( version, "latest" . to_string ( ) ) ,
481+ MatchSemver :: Semver ( _) => return Err ( AxumNope :: VersionNotFound ) ,
482+ } ;
483+
484+ let ( doc_targets, releases) : ( Vec < String > , Vec < Release > ) = spawn_blocking ( {
471485 let pool = pool. clone ( ) ;
472486 let params = params. clone ( ) ;
473487 move || {
474488 let mut conn = pool. get ( ) ?;
475489 let query = "
476- SELECT
477- crates.id AS crate_id
478- FROM crates
479- WHERE crates.name = $1;" ;
490+ SELECT
491+ crates.id AS crate_id,
492+ releases.doc_targets
493+ FROM crates
494+ INNER JOIN releases on crates.id = releases.crate_id
495+ WHERE crates.name = $1 and releases.version = $2;" ;
480496
481- let rows = conn. query ( query, & [ & params. name ] ) ?;
497+ let rows = conn. query ( query, & [ & params. name , & version ] ) ?;
482498
483499 let result = if rows. is_empty ( ) {
484- return Ok ( Vec :: new ( ) ) ;
500+ return Err ( AxumNope :: CrateNotFound . into ( ) ) ;
485501 } else {
486502 & rows[ 0 ]
487503 } ;
488- // get releases, sorted by semver
489- releases_for_crate ( & mut * conn, result. get ( "crate_id" ) )
504+
505+ Ok ( (
506+ MetaData :: parse_doc_targets ( result. get ( "doc_targets" ) ) ,
507+ // get releases, sorted by semver
508+ releases_for_crate ( & mut * conn, result. get ( "crate_id" ) ) ?,
509+ ) )
490510 }
491511 } )
492512 . await ?;
493513
514+ let inner;
515+ let ( target, inner_path) = {
516+ let mut inner_path = req_path. clone ( ) ;
517+
518+ let target = if inner_path. len ( ) > 1
519+ && doc_targets
520+ . iter ( )
521+ . any ( |s| Some ( s) == params. target . as_ref ( ) )
522+ {
523+ inner_path. remove ( 0 ) ;
524+ params. target . as_ref ( ) . unwrap ( )
525+ } else {
526+ ""
527+ } ;
528+
529+ inner = inner_path. join ( "/" ) ;
530+ ( target, inner. trim_end_matches ( '/' ) )
531+ } ;
532+ let inner_path = if inner_path. is_empty ( ) {
533+ format ! ( "{}/index.html" , params. name)
534+ } else {
535+ format ! ( "{}/{inner_path}" , params. name)
536+ } ;
537+
538+ let target = if target. is_empty ( ) {
539+ String :: new ( )
540+ } else {
541+ format ! ( "{target}/" )
542+ } ;
543+
494544 let res = ReleaseList {
495545 releases,
546+ target : target. to_string ( ) ,
547+ inner_path,
496548 crate_name : params. name ,
497549 } ;
498550 Ok ( res. into_response ( ) )
0 commit comments