@@ -454,6 +454,8 @@ pub(crate) async fn crate_details_handler(
454
454
struct ReleaseList {
455
455
releases : Vec < Release > ,
456
456
crate_name : String ,
457
+ inner_path : String ,
458
+ target : String ,
457
459
}
458
460
459
461
impl_axum_webpage ! {
@@ -464,35 +466,85 @@ impl_axum_webpage! {
464
466
465
467
#[ tracing:: instrument]
466
468
pub ( crate ) async fn get_all_releases (
467
- Path ( params) : Path < CrateDetailHandlerParams > ,
469
+ Path ( params) : Path < RustdocHtmlParams > ,
468
470
Extension ( pool) : Extension < Pool > ,
469
471
) -> 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 ( {
471
485
let pool = pool. clone ( ) ;
472
486
let params = params. clone ( ) ;
473
487
move || {
474
488
let mut conn = pool. get ( ) ?;
475
489
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;" ;
480
496
481
- let rows = conn. query ( query, & [ & params. name ] ) ?;
497
+ let rows = conn. query ( query, & [ & params. name , & version ] ) ?;
482
498
483
499
let result = if rows. is_empty ( ) {
484
- return Ok ( Vec :: new ( ) ) ;
500
+ return Err ( AxumNope :: CrateNotFound . into ( ) ) ;
485
501
} else {
486
502
& rows[ 0 ]
487
503
} ;
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
+ ) )
490
510
}
491
511
} )
492
512
. await ?;
493
513
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
+
494
544
let res = ReleaseList {
495
545
releases,
546
+ target : target. to_string ( ) ,
547
+ inner_path,
496
548
crate_name : params. name ,
497
549
} ;
498
550
Ok ( res. into_response ( ) )
0 commit comments