@@ -79,6 +79,7 @@ impl CrateDetails {
79
79
conn : & mut Client ,
80
80
name : & str ,
81
81
version : & str ,
82
+ version_or_latest : & str ,
82
83
up : & RepositoryStatsUpdater ,
83
84
) -> Option < CrateDetails > {
84
85
// get all stuff, I love you rustfmt
@@ -150,6 +151,7 @@ impl CrateDetails {
150
151
let metadata = MetaData {
151
152
name : krate. get ( "name" ) ,
152
153
version : krate. get ( "version" ) ,
154
+ version_or_latest : version_or_latest. to_string ( ) ,
153
155
description : krate. get ( "description" ) ,
154
156
rustdoc_status : krate. get ( "rustdoc_status" ) ,
155
157
target_name : krate. get ( "target_name" ) ,
@@ -281,16 +283,21 @@ pub fn crate_details_handler(req: &mut Request) -> IronResult<Response> {
281
283
let name = cexpect ! ( req, router. find( "name" ) ) ;
282
284
let req_version = router. find ( "version" ) ;
283
285
284
- let mut conn = extension ! ( req, Pool ) . get ( ) ?;
285
-
286
- match match_version ( & mut conn, name, req_version) . and_then ( |m| m. assume_exact ( ) ) ? {
287
- MatchSemver :: Exact ( ( version, _) ) => {
288
- let updater = extension ! ( req, RepositoryStatsUpdater ) ;
289
- let details = cexpect ! ( req, CrateDetails :: new( & mut conn, name, & version, updater) ) ;
286
+ if req_version == None {
287
+ let url = ctry ! (
288
+ req,
289
+ Url :: parse( & format!( "{}/crate/{}/latest" , redirect_base( req) , name, ) ) ,
290
+ ) ;
291
+ return Ok ( super :: redirect ( url) ) ;
292
+ }
290
293
291
- CrateDetailsPage { details } . into_response ( req)
292
- }
294
+ let mut conn = extension ! ( req, Pool ) . get ( ) ?;
293
295
296
+ let found_version =
297
+ match_version ( & mut conn, name, req_version) . and_then ( |m| m. assume_exact ( ) ) ?;
298
+ let ( version, version_or_latest) = match found_version {
299
+ MatchSemver :: Exact ( ( version, _) ) => ( version. clone ( ) , version) ,
300
+ MatchSemver :: Latest ( ( version, _) ) => ( version, "latest" . to_string ( ) ) ,
294
301
MatchSemver :: Semver ( ( version, _) ) => {
295
302
let url = ctry ! (
296
303
req,
@@ -302,16 +309,24 @@ pub fn crate_details_handler(req: &mut Request) -> IronResult<Response> {
302
309
) ) ,
303
310
) ;
304
311
305
- Ok ( super :: redirect ( url) )
312
+ return Ok ( super :: redirect ( url) ) ;
306
313
}
307
- }
314
+ } ;
315
+
316
+ let updater = extension ! ( req, RepositoryStatsUpdater ) ;
317
+ let details = cexpect ! (
318
+ req,
319
+ CrateDetails :: new( & mut conn, name, & version, & version_or_latest, updater)
320
+ ) ;
321
+
322
+ CrateDetailsPage { details } . into_response ( req)
308
323
}
309
324
310
325
#[ cfg( test) ]
311
326
mod tests {
312
327
use super :: * ;
313
328
use crate :: index:: api:: CrateOwner ;
314
- use crate :: test:: { wrapper, TestDatabase } ;
329
+ use crate :: test:: { assert_redirect , wrapper, TestDatabase } ;
315
330
use anyhow:: { Context , Error } ;
316
331
use kuchiki:: traits:: TendrilSink ;
317
332
use std:: collections:: HashMap ;
@@ -326,6 +341,7 @@ mod tests {
326
341
& mut db. conn ( ) ,
327
342
package,
328
343
version,
344
+ version,
329
345
db. repository_stats_updater ( ) ,
330
346
)
331
347
. with_context ( || anyhow:: anyhow!( "could not fetch crate details" ) ) ?;
@@ -459,6 +475,7 @@ mod tests {
459
475
& mut db. conn ( ) ,
460
476
"foo" ,
461
477
"0.2.0" ,
478
+ "0.2.0" ,
462
479
db. repository_stats_updater ( ) ,
463
480
)
464
481
. unwrap ( ) ;
@@ -534,6 +551,7 @@ mod tests {
534
551
& mut db. conn ( ) ,
535
552
"foo" ,
536
553
version,
554
+ version,
537
555
db. repository_stats_updater ( ) ,
538
556
)
539
557
. unwrap ( ) ;
@@ -564,6 +582,7 @@ mod tests {
564
582
& mut db. conn ( ) ,
565
583
"foo" ,
566
584
version,
585
+ version,
567
586
db. repository_stats_updater ( ) ,
568
587
)
569
588
. unwrap ( ) ;
@@ -595,6 +614,7 @@ mod tests {
595
614
& mut db. conn ( ) ,
596
615
"foo" ,
597
616
version,
617
+ version,
598
618
db. repository_stats_updater ( ) ,
599
619
)
600
620
. unwrap ( ) ;
@@ -634,6 +654,7 @@ mod tests {
634
654
& mut db. conn ( ) ,
635
655
"foo" ,
636
656
version,
657
+ version,
637
658
db. repository_stats_updater ( ) ,
638
659
)
639
660
. unwrap ( ) ;
@@ -696,6 +717,7 @@ mod tests {
696
717
& mut db. conn ( ) ,
697
718
"foo" ,
698
719
"0.0.1" ,
720
+ "0.0.1" ,
699
721
db. repository_stats_updater ( ) ,
700
722
)
701
723
. unwrap ( ) ;
@@ -726,6 +748,7 @@ mod tests {
726
748
& mut db. conn ( ) ,
727
749
"foo" ,
728
750
"0.0.1" ,
751
+ "0.0.1" ,
729
752
db. repository_stats_updater ( ) ,
730
753
)
731
754
. unwrap ( ) ;
@@ -755,6 +778,7 @@ mod tests {
755
778
& mut db. conn ( ) ,
756
779
"foo" ,
757
780
"0.0.1" ,
781
+ "0.0.1" ,
758
782
db. repository_stats_updater ( ) ,
759
783
)
760
784
. unwrap ( ) ;
@@ -779,6 +803,7 @@ mod tests {
779
803
& mut db. conn ( ) ,
780
804
"foo" ,
781
805
"0.0.1" ,
806
+ "0.0.1" ,
782
807
db. repository_stats_updater ( ) ,
783
808
)
784
809
. unwrap ( ) ;
@@ -956,4 +981,42 @@ mod tests {
956
981
Ok ( ( ) )
957
982
} ) ;
958
983
}
984
+
985
+ #[ test]
986
+ fn latest_url ( ) {
987
+ wrapper ( |env| {
988
+ env. fake_release ( )
989
+ . name ( "dummy" )
990
+ . version ( "0.4.0" )
991
+ . rustdoc_file ( "dummy/index.html" )
992
+ . rustdoc_file ( "x86_64-pc-windows-msvc/dummy/index.html" )
993
+ . default_target ( "x86_64-unknown-linux-gnu" )
994
+ . add_target ( "x86_64-pc-windows-msvc" )
995
+ . create ( ) ?;
996
+ let web = env. frontend ( ) ;
997
+
998
+ let resp = env. frontend ( ) . get ( "/crate/dummy/latest" ) . send ( ) ?;
999
+ assert ! ( resp. status( ) . is_success( ) ) ;
1000
+ assert ! ( resp. url( ) . as_str( ) . ends_with( "/crate/dummy/latest" ) ) ;
1001
+ let body = String :: from_utf8 ( resp. bytes ( ) . unwrap ( ) . to_vec ( ) ) . unwrap ( ) ;
1002
+ assert ! ( body. contains( "<a href=\" /crate/dummy/latest/features\" " ) ) ;
1003
+ assert ! ( body. contains( "<a href=\" /crate/dummy/latest/builds\" " ) ) ;
1004
+ assert ! ( body. contains( "<a href=\" /crate/dummy/latest/source/\" " ) ) ;
1005
+ assert ! ( body. contains( "<a href=\" /crate/dummy/latest\" " ) ) ;
1006
+
1007
+ assert_redirect ( "/crate/dummy/latest/" , "/crate/dummy/latest" , web) ?;
1008
+ assert_redirect ( "/crate/dummy" , "/crate/dummy/latest" , web) ?;
1009
+
1010
+ let resp_json = env
1011
+ . frontend ( )
1012
+ . get ( "/crate/aquarelle/latest/builds.json" )
1013
+ . send ( ) ?;
1014
+ assert ! ( resp_json
1015
+ . url( )
1016
+ . as_str( )
1017
+ . ends_with( "/crate/aquarelle/latest/builds.json" ) ) ;
1018
+
1019
+ Ok ( ( ) )
1020
+ } ) ;
1021
+ }
959
1022
}
0 commit comments