From d55d1de0a349419b9648dae6caadbf04cad8e60f Mon Sep 17 00:00:00 2001 From: LeopoldArkham Date: Sun, 29 Jan 2017 17:13:49 +0100 Subject: [PATCH 1/7] Front-end changes --- app/models/dependency.js | 1 + app/styles/crate.scss | 2 ++ app/templates/crate/reverse-dependencies.hbs | 9 +++++---- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/models/dependency.js b/app/models/dependency.js index 5368a69b6ae..15bc44588d7 100644 --- a/app/models/dependency.js +++ b/app/models/dependency.js @@ -15,6 +15,7 @@ export default DS.Model.extend({ default_features: DS.attr('boolean'), features: DS.attr('string'), kind: DS.attr('string'), + downloads: DS.attr('number'), featureList: computed('features', function() { return this.get('features').split(','); diff --git a/app/styles/crate.scss b/app/styles/crate.scss index 05e2b453280..e8d0ab0b69c 100644 --- a/app/styles/crate.scss +++ b/app/styles/crate.scss @@ -127,6 +127,8 @@ } .downloads { @include display-flex; @include align-items(center); } + .rev-dep-downloads {padding-left: 7px} + .quick-links { ul { @include display-flex; diff --git a/app/templates/crate/reverse-dependencies.hbs b/app/templates/crate/reverse-dependencies.hbs index a1d2fcc9813..070331fb098 100644 --- a/app/templates/crate/reverse-dependencies.hbs +++ b/app/templates/crate/reverse-dependencies.hbs @@ -13,15 +13,16 @@ -
+
{{#each model as |dependency|}}
{{#link-to 'crate' dependency.crate_id}}{{dependency.crate_id}}{{/link-to}} requires {{dependency.req}}
- {{#link-to 'crate' dependency.crate_id class='arrow'}} - - {{/link-to}} +
+ + {{ format-num dependency.downloads }} +
{{/each}}
From 1fe13d6694383334756910397b7cffa35725b98e Mon Sep 17 00:00:00 2001 From: LeopoldArkham Date: Sun, 29 Jan 2017 17:29:14 +0100 Subject: [PATCH 2/7] UI fix --- app/templates/crate/reverse-dependencies.hbs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/crate/reverse-dependencies.hbs b/app/templates/crate/reverse-dependencies.hbs index 070331fb098..b5b0d3f6e4c 100644 --- a/app/templates/crate/reverse-dependencies.hbs +++ b/app/templates/crate/reverse-dependencies.hbs @@ -15,7 +15,7 @@
{{#each model as |dependency|}} -
+
{{#link-to 'crate' dependency.crate_id}}{{dependency.crate_id}}{{/link-to}} requires {{dependency.req}}
From 148d411d3b1c7c52dcb16aab5413a393c8890a42 Mon Sep 17 00:00:00 2001 From: LeopoldArkham Date: Sun, 29 Jan 2017 17:46:20 +0100 Subject: [PATCH 3/7] Backend changes --- src/dependency.rs | 16 +++++++++++++--- src/krate.rs | 25 +++++++++++++------------ src/version.rs | 2 +- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/dependency.rs b/src/dependency.rs index 66827e6c5f1..78db2f8afd5 100644 --- a/src/dependency.rs +++ b/src/dependency.rs @@ -29,6 +29,7 @@ pub struct EncodableDependency { pub features: String, pub target: Option, pub kind: Kind, + pub downloads: i32, } #[derive(Copy, Clone)] @@ -76,9 +77,17 @@ impl Dependency { } } - pub fn encodable(self, crate_name: &str) -> EncodableDependency { - let Dependency { id, version_id, crate_id: _, req, optional, - default_features, features, target, kind } = self; + // `downloads` need only be specified when generating a reverse dependency + pub fn encodable(self, crate_name: &str, downloads: Option) -> EncodableDependency { + let Dependency { id, + version_id, + crate_id: _, + req, + optional, + default_features, + features, + target, + kind } = self; EncodableDependency { id: id, version_id: version_id, @@ -89,6 +98,7 @@ impl Dependency { features: features.join(","), target: target, kind: kind, + downloads: downloads.unwrap_or(0), } } } diff --git a/src/krate.rs b/src/krate.rs index 1fc5a486a79..897ecc4a5c5 100644 --- a/src/krate.rs +++ b/src/krate.rs @@ -420,30 +420,32 @@ impl Crate { Ok(rows.iter().map(|r| Model::from_row(&r)).collect()) } - /// Returns (dependency, dependent crate name) + /// Returns (dependency, dependent crate name, dependent crate downloads) pub fn reverse_dependencies(&self, conn: &GenericConnection, offset: i64, limit: i64) - -> CargoResult<(Vec<(Dependency, String)>, i64)> { + -> CargoResult<(Vec<(Dependency, String, i32)>, i64)> { let select_sql = " FROM dependencies INNER JOIN versions ON versions.id = dependencies.version_id INNER JOIN crates ON crates.id = versions.crate_id + INNER JOIN crate_downloads + ON crate_downloads.crate_id = versions.crate_id WHERE dependencies.crate_id = $1 AND versions.num = crates.max_version "; - let fetch_sql = format!("SELECT DISTINCT ON (crate_name) - dependencies.*, + let fetch_sql = format!("SELECT dependencies.*, + crate_downloads.downloads AS crate_downloads, crates.name AS crate_name {} - ORDER BY crate_name ASC + ORDER BY crate_downloads DESC OFFSET $2 - LIMIT $3", select_sql); - let count_sql = format!("SELECT COUNT(DISTINCT(crates.id)) {}", + LIMIT $3", select_sql); + let count_sql = format!("SELECT COUNT(DISTINCT(crates.id)) {}", select_sql); let stmt = try!(conn.prepare(&fetch_sql)); let vec: Vec<_> = try!(stmt.query(&[&self.id, &offset, &limit])) @@ -1172,12 +1174,11 @@ pub fn reverse_dependencies(req: &mut Request) -> CargoResult { let name = &req.params()["crate_id"]; let conn = try!(req.tx()); let krate = try!(Crate::find_by_name(conn, &name)); - let tx = try!(req.tx()); let (offset, limit) = try!(req.pagination(10, 100)); - let (rev_deps, total) = try!(krate.reverse_dependencies(tx, offset, limit)); - let rev_deps = rev_deps.into_iter().map(|(dep, crate_name)| { - dep.encodable(&crate_name) - }).collect(); + let (rev_deps, total) = try!(krate.reverse_dependencies(conn, offset, limit)); + let rev_deps = rev_deps.into_iter() + .map(|(dep, crate_name, downloads)| dep.encodable(&crate_name, Some(downloads))) + .collect(); #[derive(RustcEncodable)] struct R { dependencies: Vec, meta: Meta } diff --git a/src/version.rs b/src/version.rs index 2265d445db8..98c27b758b8 100644 --- a/src/version.rs +++ b/src/version.rs @@ -296,7 +296,7 @@ pub fn dependencies(req: &mut Request) -> CargoResult { let tx = try!(req.tx()); let deps = try!(version.dependencies(tx)); let deps = deps.into_iter().map(|(dep, crate_name)| { - dep.encodable(&crate_name) + dep.encodable(&crate_name, None) }).collect(); #[derive(RustcEncodable)] From e146920d040e297d56d5a5966c13a4032cc8e363 Mon Sep 17 00:00:00 2001 From: LeopoldArkham Date: Sun, 29 Jan 2017 18:20:29 +0100 Subject: [PATCH 4/7] Missed a chunk --- src/krate.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/krate.rs b/src/krate.rs index 897ecc4a5c5..a3c827903d3 100644 --- a/src/krate.rs +++ b/src/krate.rs @@ -449,9 +449,9 @@ impl Crate { let stmt = try!(conn.prepare(&fetch_sql)); let vec: Vec<_> = try!(stmt.query(&[&self.id, &offset, &limit])) - .iter().map(|r| { - (Model::from_row(&r), r.get("crate_name")) - }).collect(); + .iter() + .map(|r| (Model::from_row(&r), r.get("crate_name"), r.get("crate_downloads"))) + .collect(); let stmt = try!(conn.prepare(&count_sql)); let cnt: i64 = try!(stmt.query(&[&self.id])).iter().next().unwrap().get(0); From a067b84d9a1338c9635d4451f95f5e7c9c7ddd0b Mon Sep 17 00:00:00 2001 From: LeopoldArkham Date: Sun, 29 Jan 2017 19:40:13 +0100 Subject: [PATCH 5/7] crate_downloads -> crates.downloads --- src/krate.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/krate.rs b/src/krate.rs index a3c827903d3..4481acd779e 100644 --- a/src/krate.rs +++ b/src/krate.rs @@ -432,13 +432,11 @@ impl Crate { ON versions.id = dependencies.version_id INNER JOIN crates ON crates.id = versions.crate_id - INNER JOIN crate_downloads - ON crate_downloads.crate_id = versions.crate_id WHERE dependencies.crate_id = $1 AND versions.num = crates.max_version "; let fetch_sql = format!("SELECT dependencies.*, - crate_downloads.downloads AS crate_downloads, + crates.downloads AS crate_downloads, crates.name AS crate_name {} ORDER BY crate_downloads DESC From 8faad3d434baff9125a9f5e32b66f77a812637e1 Mon Sep 17 00:00:00 2001 From: LeopoldArkham Date: Sun, 29 Jan 2017 20:31:30 +0100 Subject: [PATCH 6/7] Never program on a Sunday evening. Dedup results and sort outside of SQL --- src/krate.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/krate.rs b/src/krate.rs index 4481acd779e..66f192abdb7 100644 --- a/src/krate.rs +++ b/src/krate.rs @@ -435,21 +435,22 @@ impl Crate { WHERE dependencies.crate_id = $1 AND versions.num = crates.max_version "; - let fetch_sql = format!("SELECT dependencies.*, + let fetch_sql = format!("SELECT DISTINCT ON (crate_name) + dependencies.*, crates.downloads AS crate_downloads, crates.name AS crate_name {} - ORDER BY crate_downloads DESC OFFSET $2 LIMIT $3", select_sql); let count_sql = format!("SELECT COUNT(DISTINCT(crates.id)) {}", select_sql); let stmt = try!(conn.prepare(&fetch_sql)); - let vec: Vec<_> = try!(stmt.query(&[&self.id, &offset, &limit])) + let mut vec: Vec<_> = try!(stmt.query(&[&self.id, &offset, &limit])) .iter() .map(|r| (Model::from_row(&r), r.get("crate_name"), r.get("crate_downloads"))) .collect(); + vec.sort_by(|a: &(_, _, i32), b: &(_, _, i32)| b.2.cmp(&a.2)); let stmt = try!(conn.prepare(&count_sql)); let cnt: i64 = try!(stmt.query(&[&self.id])).iter().next().unwrap().get(0); From 97de37dcc471d51313e10b86a13bb6eeec2aeb8f Mon Sep 17 00:00:00 2001 From: LeopoldArkham Date: Mon, 6 Feb 2017 19:16:12 +0100 Subject: [PATCH 7/7] Back to SQL --- src/krate.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/krate.rs b/src/krate.rs index 66f192abdb7..202d7404626 100644 --- a/src/krate.rs +++ b/src/krate.rs @@ -435,22 +435,22 @@ impl Crate { WHERE dependencies.crate_id = $1 AND versions.num = crates.max_version "; - let fetch_sql = format!("SELECT DISTINCT ON (crate_name) + let fetch_sql = format!("SELECT DISTINCT ON (crate_downloads, crate_name) dependencies.*, crates.downloads AS crate_downloads, crates.name AS crate_name {} + ORDER BY crate_downloads DESC OFFSET $2 LIMIT $3", select_sql); let count_sql = format!("SELECT COUNT(DISTINCT(crates.id)) {}", select_sql); let stmt = try!(conn.prepare(&fetch_sql)); - let mut vec: Vec<_> = try!(stmt.query(&[&self.id, &offset, &limit])) + let vec: Vec<_> = try!(stmt.query(&[&self.id, &offset, &limit])) .iter() .map(|r| (Model::from_row(&r), r.get("crate_name"), r.get("crate_downloads"))) .collect(); - vec.sort_by(|a: &(_, _, i32), b: &(_, _, i32)| b.2.cmp(&a.2)); let stmt = try!(conn.prepare(&count_sql)); let cnt: i64 = try!(stmt.query(&[&self.id])).iter().next().unwrap().get(0);