@@ -584,8 +584,9 @@ pub(crate) async fn get_all_releases(
584584 Path ( params) : Path < RustdocHtmlParams > ,
585585 mut conn : DbConnection ,
586586) -> AxumResult < AxumResponse > {
587- let req_path: String = params. path . clone ( ) . unwrap_or_default ( ) ;
588- let req_path: Vec < & str > = req_path. split ( '/' ) . collect ( ) ;
587+ // NOTE: we're getting RustDocHtmlParams here, where both target and path are optional.
588+ // Due to how this handler is used in the `releases_list` macro, we either have
589+ // both values (when used in the topbar), or none (when used in the crate-details handler).
589590
590591 let matched_release = match_version ( & mut conn, & params. name , & params. version )
591592 . await ?
@@ -599,61 +600,26 @@ pub(crate) async fn get_all_releases(
599600 return Err ( AxumNope :: CrateNotFound ) ;
600601 }
601602
602- let doc_targets = sqlx:: query_scalar!(
603- "SELECT
604- releases.doc_targets
605- FROM releases
606- WHERE releases.id = $1;" ,
607- matched_release. id( ) . 0 ,
608- )
609- . fetch_optional ( & mut * conn)
610- . await ?
611- . ok_or ( AxumNope :: CrateNotFound ) ?
612- . map ( MetaData :: parse_doc_targets)
613- . ok_or_else ( || anyhow ! ( "empty doc targets for successful release" ) ) ?;
614-
615- let inner;
616- let ( target, inner_path) = {
617- let mut inner_path = req_path. clone ( ) ;
618-
619- let target = if inner_path. len ( ) > 1
620- && doc_targets
621- . iter ( )
622- . any ( |s| Some ( s) == params. target . as_ref ( ) )
623- {
624- inner_path. remove ( 0 ) ;
625- params. target . as_ref ( ) . unwrap ( )
626- } else {
627- ""
628- } ;
629-
630- inner = inner_path. join ( "/" ) ;
631- ( target, inner. trim_end_matches ( '/' ) )
632- } ;
633-
634- let target_name = matched_release
635- . target_name ( )
636- . ok_or_else ( || anyhow ! ( "empty target name for succesful release" ) ) ?;
637-
638- let inner_path = if inner_path. is_empty ( ) {
639- format ! ( "{target_name}/index.html" )
640- } else {
641- format ! ( "{target_name}/{inner_path}" )
603+ // NOTE: we don't check if the target exists here.
604+ // If the target doesn't exist, the target-redirect will think
605+ // it's part of the `inner_path`, don't find the file in storage,
606+ // and redirect to a search.
607+ let target = match params. target {
608+ Some ( t) if t. is_empty ( ) => t,
609+ Some ( t) => format ! ( "{t}/" ) ,
610+ None => String :: new ( ) ,
642611 } ;
643612
644- let target = if target. is_empty ( ) {
645- String :: new ( )
646- } else {
647- format ! ( "{target}/" )
648- } ;
613+ let inner_path = params. path . unwrap_or_default ( ) ;
614+ let inner_path = inner_path. trim_end_matches ( '/' ) ;
649615
650- let res = ReleaseList {
616+ Ok ( ReleaseList {
651617 releases : matched_release. all_releases ,
652618 target,
653- inner_path,
619+ inner_path : inner_path . to_string ( ) ,
654620 crate_name : params. name ,
655- } ;
656- Ok ( res . into_response ( ) )
621+ }
622+ . into_response ( ) )
657623}
658624
659625#[ derive( Debug , Clone , PartialEq ) ]
@@ -2034,6 +2000,17 @@ mod tests {
20342000 . create ( )
20352001 . await ?;
20362002
2003+ check_links (
2004+ // https://github.com/rust-lang/docs.rs/issues/2922
2005+ & env,
2006+ "/crate/dummy-ba/0.5.0/menus/releases/x86_64-unknown-linux-gnu/src/dummy_ba/de.rs.html" ,
2007+ vec ! [
2008+ "/crate/dummy-ba/0.5.0/target-redirect/x86_64-unknown-linux-gnu/src/dummy_ba/de.rs.html" . to_string( ) ,
2009+ "/crate/dummy-ba/0.4.0/target-redirect/x86_64-unknown-linux-gnu/src/dummy_ba/de.rs.html" . to_string( ) ,
2010+ ] ,
2011+ )
2012+ . await ;
2013+
20372014 check_links (
20382015 & env,
20392016 "/crate/dummy-ba/latest/menus/releases/dummy_ba/index.html" ,
0 commit comments