@@ -44,7 +44,6 @@ pub struct Crate {
4444 pub updated_at : Timespec ,
4545 pub created_at : Timespec ,
4646 pub downloads : i32 ,
47- pub max_version : semver:: Version ,
4847 pub description : Option < String > ,
4948 pub homepage : Option < String > ,
5049 pub documentation : Option < String > ,
@@ -232,18 +231,20 @@ impl Crate {
232231 }
233232
234233 pub fn minimal_encodable ( self ,
234+ max_version : semver:: Version ,
235235 badges : Option < Vec < Badge > > ) -> EncodableCrate {
236- self . encodable ( None , None , None , badges)
236+ self . encodable ( max_version , None , None , None , badges)
237237 }
238238
239239 pub fn encodable ( self ,
240+ max_version : semver:: Version ,
240241 versions : Option < Vec < i32 > > ,
241242 keywords : Option < & [ Keyword ] > ,
242243 categories : Option < & [ Category ] > ,
243244 badges : Option < Vec < Badge > > )
244245 -> EncodableCrate {
245246 let Crate {
246- name, created_at, updated_at, downloads, max_version , description,
247+ name, created_at, updated_at, downloads, description,
247248 homepage, documentation, license, repository,
248249 readme : _, id : _, max_upload_size : _,
249250 } = self ;
@@ -254,7 +255,7 @@ impl Crate {
254255 let keyword_ids = keywords. map ( |kws| kws. iter ( ) . map ( |kw| kw. keyword . clone ( ) ) . collect ( ) ) ;
255256 let category_ids = categories. map ( |cats| cats. iter ( ) . map ( |cat| cat. slug . clone ( ) ) . collect ( ) ) ;
256257 let badges = badges. map ( |bs| {
257- bs. iter ( ) . map ( |b| b. clone ( ) . encodable ( ) ) . collect ( )
258+ bs. into_iter ( ) . map ( |b| b. encodable ( ) ) . collect ( )
258259 } ) ;
259260 EncodableCrate {
260261 id : name. clone ( ) ,
@@ -281,6 +282,16 @@ impl Crate {
281282 }
282283 }
283284
285+ pub fn max_version ( & self , conn : & GenericConnection ) -> CargoResult < semver:: Version > {
286+ let stmt = conn. prepare ( "SELECT num FROM versions WHERE crate_id = $1
287+ AND yanked = 'f'" ) ?;
288+ let rows = stmt. query ( & [ & self . id ] ) ?;
289+ Ok ( rows. iter ( )
290+ . map ( |r| semver:: Version :: parse ( & r. get :: < _ , String > ( "num" ) ) . unwrap ( ) )
291+ . max ( )
292+ . unwrap_or_else ( || semver:: Version :: parse ( "0.0.0" ) . unwrap ( ) ) )
293+ }
294+
284295 pub fn versions ( & self , conn : & GenericConnection ) -> CargoResult < Vec < Version > > {
285296 let stmt = conn. prepare ( "SELECT * FROM versions \
286297 WHERE crate_id = $1") ?;
@@ -383,14 +394,6 @@ impl Crate {
383394 }
384395 None => { }
385396 }
386- let zero = semver:: Version :: parse ( "0.0.0" ) . unwrap ( ) ;
387- if * ver > self . max_version || self . max_version == zero {
388- self . max_version = ver. clone ( ) ;
389- }
390- let stmt = conn. prepare ( "UPDATE crates SET max_version = $1
391- WHERE id = $2 RETURNING updated_at" ) ?;
392- let rows = stmt. query ( & [ & self . max_version . to_string ( ) , & self . id ] ) ?;
393- self . updated_at = rows. get ( 0 ) . get ( "updated_at" ) ;
394397 Version :: insert ( conn, self . id , ver, features, authors)
395398 }
396399
@@ -433,34 +436,34 @@ impl Crate {
433436 INNER JOIN crates
434437 ON crates.id = versions.crate_id
435438 WHERE dependencies.crate_id = $1
436- AND versions.num = crates.max_version
439+ AND versions.num = $2
437440 " ;
438441 let fetch_sql = format ! ( "SELECT DISTINCT ON (crate_downloads, crate_name)
439442 dependencies.*,
440443 crates.downloads AS crate_downloads,
441444 crates.name AS crate_name
442445 {}
443446 ORDER BY crate_downloads DESC
444- OFFSET $2
445- LIMIT $3 " ,
447+ OFFSET $3
448+ LIMIT $4 " ,
446449 select_sql) ;
447450 let count_sql = format ! ( "SELECT COUNT(DISTINCT(crates.id)) {}" , select_sql) ;
448451
449452 let stmt = conn. prepare ( & fetch_sql) ?;
450- let vec: Vec < _ > = stmt. query ( & [ & self . id , & offset, & limit] ) ?
453+ let max_version = self . max_version ( conn) ?. to_string ( ) ;
454+ let vec: Vec < _ > = stmt. query ( & [ & self . id , & max_version, & offset, & limit] ) ?
451455 . iter ( )
452456 . map ( |r| ( Model :: from_row ( & r) , r. get ( "crate_name" ) , r. get ( "crate_downloads" ) ) )
453457 . collect ( ) ;
454458 let stmt = conn. prepare ( & count_sql) ?;
455- let cnt: i64 = stmt. query ( & [ & self . id ] ) ?. iter ( ) . next ( ) . unwrap ( ) . get ( 0 ) ;
459+ let cnt: i64 = stmt. query ( & [ & self . id , & max_version ] ) ?. iter ( ) . next ( ) . unwrap ( ) . get ( 0 ) ;
456460
457461 Ok ( ( vec, cnt) )
458462 }
459463}
460464
461465impl Model for Crate {
462466 fn from_row ( row : & Row ) -> Crate {
463- let max: String = row. get ( "max_version" ) ;
464467 Crate {
465468 id : row. get ( "id" ) ,
466469 name : row. get ( "name" ) ,
@@ -471,7 +474,6 @@ impl Model for Crate {
471474 documentation : row. get ( "documentation" ) ,
472475 homepage : row. get ( "homepage" ) ,
473476 readme : row. get ( "readme" ) ,
474- max_version : semver:: Version :: parse ( & max) . unwrap ( ) ,
475477 license : row. get ( "license" ) ,
476478 repository : row. get ( "repository" ) ,
477479 max_upload_size : row. get ( "max_upload_size" ) ,
@@ -602,8 +604,9 @@ pub fn index(req: &mut Request) -> CargoResult<Response> {
602604 let mut crates = Vec :: new ( ) ;
603605 for row in stmt. query ( & args) ?. iter ( ) {
604606 let krate: Crate = Model :: from_row ( & row) ;
605- let badges = krate. badges ( conn) ;
606- crates. push ( krate. minimal_encodable ( badges. ok ( ) ) ) ;
607+ let badges = krate. badges ( conn) ?;
608+ let max_version = krate. max_version ( conn) ?;
609+ crates. push ( krate. minimal_encodable ( max_version, Some ( badges) ) ) ;
607610 }
608611
609612 // Query for the total count of crates
@@ -636,10 +639,11 @@ pub fn summary(req: &mut Request) -> CargoResult<Response> {
636639
637640 let to_crates = |stmt : pg:: stmt:: Statement | -> CargoResult < Vec < _ > > {
638641 let rows = stmt. query ( & [ ] ) ?;
639- Ok ( rows. iter ( ) . map ( |r| {
642+ rows. iter ( ) . map ( |r| {
640643 let krate: Crate = Model :: from_row ( & r) ;
641- krate. minimal_encodable ( None )
642- } ) . collect :: < Vec < EncodableCrate > > ( ) )
644+ let max_version = krate. max_version ( tx) ?;
645+ Ok ( krate. minimal_encodable ( max_version, None ) )
646+ } ) . collect ( )
643647 } ;
644648 let new_crates = tx. prepare ( "SELECT * FROM crates \
645649 ORDER BY created_at DESC LIMIT 10") ?;
@@ -691,6 +695,7 @@ pub fn show(req: &mut Request) -> CargoResult<Response> {
691695 let kws = krate. keywords ( conn) ?;
692696 let cats = krate. categories ( conn) ?;
693697 let badges = krate. badges ( conn) ?;
698+ let max_version = krate. max_version ( conn) ?;
694699
695700 #[ derive( RustcEncodable ) ]
696701 struct R {
@@ -701,7 +706,7 @@ pub fn show(req: &mut Request) -> CargoResult<Response> {
701706 }
702707 Ok ( req. json ( & R {
703708 krate : krate. clone ( ) . encodable (
704- Some ( ids) , Some ( & kws) , Some ( & cats) , Some ( badges)
709+ max_version , Some ( ids) , Some ( & kws) , Some ( & cats) , Some ( badges)
705710 ) ,
706711 versions : versions. into_iter ( ) . map ( |v| {
707712 v. encodable ( & krate. name )
@@ -784,6 +789,7 @@ pub fn new(req: &mut Request) -> CargoResult<Response> {
784789 & krate,
785790 new_crate. badges . unwrap_or_else ( HashMap :: new)
786791 ) ?;
792+ let max_version = krate. max_version ( req. tx ( ) ?) ?;
787793
788794 // Upload the crate to S3
789795 let mut handle = req. app ( ) . handle ( ) ;
@@ -854,7 +860,7 @@ pub fn new(req: &mut Request) -> CargoResult<Response> {
854860 #[ derive( RustcEncodable ) ]
855861 struct R { krate : EncodableCrate , warnings : Warnings }
856862 Ok ( req. json ( & R {
857- krate : krate. minimal_encodable ( None ) ,
863+ krate : krate. minimal_encodable ( max_version , None ) ,
858864 warnings : warnings
859865 } ) )
860866}
0 commit comments